LoginSignup
7
4

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-04-16

概要

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点を一致させる必要がある

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4