portAudioでストリーミング処理 + マルチチャンネル処理

概要

portaudioを使ってストリーミング音声処理をしたい
オーディオインタフェースを使う場合のマルチチャンネル入力(4ch,8ch...)の場合のコードの書き方を載せる

環境

portAudio
win10
WASAPI(DirectSoundではマルチチャンネル入力ができなかった,OSやサウンドドライバに依ってマルチチャンネルが使える/使えないが決まるので注意)

ソースコード(C言語)

  • portAduioを使ってデバイスをopen
  • callback関数によってオーディオストリーミングを処理
  • callback関数内でストリーミングから入力チャンネルを切り分ける
portaudio_multiInput_sample.c
PaStream *stream;
PaError err;

static int NUM_OF_CHANNEL = 4;
/* Open an audio I/O stream. */
err = Pa_OpenDefaultStream( &stream,
                            NUM_OF_CHANNEL,          /* 4 input channels */
                            0,          /* no output channel*/
                            NULL,  /* 32 bit floating point output */
                            SAMPLE_RATE,
                            256,        /* frames per buffer, i.e. the number
                                               of sample frames that PortAudio will
                                               request from the callback. Many apps
                                               may want to use
                                               paFramesPerBufferUnspecified, which
                                               tells PortAudio to pick the best,
                                               possibly changing, buffer size.*/
                            Callback, /* this is your callback function */
                            &data ); /*This is a pointer that will be passed to
                                      your callback*/
if( err != paNoError ) goto error;

static int Callback( const void *inputBuffer, void *outputBuffer,
                           unsigned long framesPerBuffer,
                           const PaStreamCallbackTimeInfo* timeInfo,
                           PaStreamCallbackFlags statusFlags,
                           void *userData )
{
  //入力信号は16bitの音声信号
  SP16 **recogData; 

  //チャンネルごとのメモリ確保
  recogData = (SP16**)malloc(sizeof(SP16*) * NUM_OF_CHANNEL);
  for(int i=0; i<NUM_OF_CHANNEL; i++)
    recogData[i] = (flaot*)malloc(sizeof(SP16*) * framesPerBuffer);

  //ストリーミングからチャンネル毎に信号を切り分ける
  SP16 *in = (SP16*)inputBuffer;
  for (int j=0; j<NUM_OF_CHANNEL; j++)
    for (int i=0; i<framesPerBuffer; i++)
      recogData[j][i] = in[i*NUM_OF_CHANNEL+j];
}

要点

以下の部分でストリーミング入力を切り分けている

//ストリーミングからチャンネル毎に信号を切り分ける
SP16 *in = (SP16*)inputBuffer;
for (int j=0; j<NUM_OF_CHANNEL; j++)
  for (int i=0; i<framesPerBuffer; i++)
    recogData[j][i] = in[i*NUM_OF_CHANNEL+j];

解説

ストリーミングの場合,inputBuffer変数としてcallbackに渡されるデータは
|1chのデータ| |2chのデータ| |3chのデータ|...|Nchのデータ|
各データ長はストリーミングのframePerBuffer引数として渡されている
なのでfor文でこれらを切り分けている

注意点

streamingをopenする際には「オーディオインタフェース側のsampling rateやbit深度」と「プログラムで指定するsampling rateやbit深度」が一致していないとerrorを吐く
オーディオインタフェースの設定,ソフトウェアのオーディオドライバ,portaudioのプログラムの3点を一致させる必要がある

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.