C/C++でALSAを使ってLinuxデスクトップの音声を取得

2020/05/22 00:33CC++

Linuxのデスクトップ環境でALSA APIを使って音声を取得します。
pulseaudioを使っているものとします。

pulseaudioの設定

デスクトップで再生している音声を取得したいのでpacmdで設定します。
list-sourcesしてMonitor of ***に該当するものをデフォルトに設定します。

$pacmd
>list-sources
>set-default-source 0

音声の取得

#include <alsa/asoundlib.h>

int main() {
    const int n = 1024;
    const int channels = 2;
    snd_pcm_t* pcm;
    snd_pcm_hw_params_t* params;
    snd_pcm_format_t pcmfmt = SND_PCM_FORMAT_S16_LE;
    snd_pcm_hw_params_alloca(&params);

    if (snd_pcm_open(&pcm, "default", SND_PCM_STREAM_CAPTURE, 0) < 0) {
        // エラー処理
    };
    if (snd_pcm_hw_params_any(pcm, params) < 0) {
        // エラー処理
    }
    if (snd_pcm_hw_params_set_rate(pcm, params, 44100, 0) < 0) {
        // エラー処理
    }
    if (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
        // エラー処理
    }
    if (snd_pcm_hw_params_set_format(pcm, params, pcmfmt) < 0) {
        // エラー処理
    }
    if (snd_pcm_hw_params_set_channels(pcm, params, channels) < 0) {
        // エラー処理
    }
    if (snd_pcm_hw_params(pcm, params) < 0) {
        // エラー処理
    }
    if (snd_pcm_prepare(pcm) < 0) {
        // エラー処理
    }

    snd_pcm_hw_free(pcm);

    int16_t* buffer = (int16_t*) malloc(n*snd_pcm_format_width(pcmfmt)/8*channels);

    if (snd_pcm_readi(pcm, buffer, n) < n) {
        // エラー処理
    }

    free(buffer);
}

取得するフレーム数は1024だとリアルタイムで使う用にちょうどいいぐらいでした。