ASIOを利用してWAVファイルを再生する
(その3)

ストリームバッファにサウンドデータを書き込む

ASIOではサウンド入出力バッファが空くと、ASIOドライバよりアプリケーションが事前に登録したコールバック関数が呼び出されます。

このコールバック関数でアプリケーション側は、出力チャンネルのデータフォーマットを取得して、次に出力するサウンドデータをストリームバッファに書き込みます。

ストリームバッファに書き込みが完了したら、ASIOドライバに対して出力データの書き込み完了を通知します。

サンプルコードを以下に示します。


/****************************************************************************/
/*!
 *  @brief  データバッファの切り替え通知.
 *
 *  @param  [in]    index       バッファ番号.
 *  @param  [in]    processNow  ASIOTrue = すぐに処理が可能.
 *
 *  @retval なし.
 */
static void     bufferSwitch( long index, ASIOBool processNow )
{
    if( WavSize[0] > 0 || WavSize[1] > 0 ){
        if( ReadCnt >= WavSize[ActivePage] ){
            PostMessage( AppWnd, WM_USER, ActivePage, 0 );

            ActivePage = (ActivePage + 1) & 1;
            ReadCnt    = 0;
        }
    }
    BYTE*   buf_l = (BYTE*)(BufInfo[0].buffers[index]);
    BYTE*   buf_r = (BYTE*)(BufInfo[1].buffers[index]);

    //! チャンネル情報を取得する.
    ASIOChannelInfo info;
    info.channel = BufInfo[0].channelNum;
    info.isInput = BufInfo[0].isInput;
    ASIOGetChannelInfo( &info );

    switch( info.type ){
    case ASIOSTInt16LSB:
        //! 16ビットオーディオの場合.
        memset( buf_l, 0, BufSize * 2 );
        memset( buf_r, 0, BufSize * 2 );
        if( WavSize[ActivePage] > 0 ){
            short*  dst_l = (short*)buf_l;
            short*  dst_r = (short*)buf_r;
            short*  src   = (short*)&(WavBuf[ActivePage][ReadCnt]);
            DWORD   limit = (WavSize[ActivePage] - ReadCnt) / 4;
            if( limit > BufSize ){
                limit = BufSize;
            }
            for( DWORD i = 0; i < limit; i++ ){
                *(dst_l++) = *(src++);
                *(dst_r++) = *(src++);
            }
            ReadCnt += (BufSize * 4);
        }
        break;

    case ASIOSTInt24LSB:
        //! 24ビットオーディオの場合.
        memset( buf_l, 0, BufSize * 3 );
        memset( buf_r, 0, BufSize * 3 );
        if( WavSize[ActivePage] > 0 ){
            BYTE*   dst_l = buf_l;
            BYTE*   dst_r = buf_r;
            BYTE*   src   = &(WavBuf[ActivePage][ReadCnt]);
            DWORD   limit = (WavSize[ActivePage] - ReadCnt) / 4;
            if( limit > BufSize ){
                limit = BufSize;
            }
            for( DWORD i = 0; i < limit; i++ ){
                *(dst_l++) = 0x00;
                *(dst_l++) = *(src++);
                *(dst_l++) = *(src++);

                *(dst_r++) = 0x00;
                *(dst_r++) = *(src++);
                *(dst_r++) = *(src++);
            }
            ReadCnt += (BufSize * 4);
        }
        break;

    case ASIOSTInt32LSB:
        //! 32ビットオーディオの場合.
        memset( buf_l, 0, BufSize * 4 );
        memset( buf_r, 0, BufSize * 4 );
        if( WavSize[ActivePage] > 0 ){
            short*  dst_l = (short*)buf_l;
            short*  dst_r = (short*)buf_r;
            short*  src   = (short*)&(WavBuf[ActivePage][ReadCnt]);
            DWORD   limit = (WavSize[ActivePage] - ReadCnt) / 4;
            if( limit > BufSize ){
                limit = BufSize;
            }
            for( DWORD i = 0; i < limit; i++ ){
                *(dst_l++) = 0;
                *(dst_l++) = *(src++);
                *(dst_r++) = 0;
                *(dst_r++) = *(src++);
            }
            ReadCnt += (BufSize * 4);
        }
        break;

    case ASIOSTInt32LSB16:
    case ASIOSTInt32LSB18:
    case ASIOSTInt32LSB20:
    case ASIOSTInt32LSB24:
    case ASIOSTFloat32LSB:
    case ASIOSTInt32MSB:
    case ASIOSTInt32MSB16:
    case ASIOSTInt32MSB18:
    case ASIOSTInt32MSB20:
    case ASIOSTInt32MSB24:
    case ASIOSTFloat32MSB:
        memset( buf_l, 0, BufSize * 4 );
        memset( buf_r, 0, BufSize * 4 );
        break;

    case ASIOSTFloat64LSB:
    case ASIOSTFloat64MSB: 
        memset( buf_l, 0, BufSize * 8 );
        memset( buf_r, 0, BufSize * 8 );
        break;

    case ASIOSTInt16MSB:
        memset( buf_l, 0, BufSize * 2 );
        memset( buf_r, 0, BufSize * 2 );
        break;

    case ASIOSTInt24MSB:
        memset( buf_l, 0, BufSize * 3 );
        memset( buf_r, 0, BufSize * 3 );
        break;
    }
    // ASIOOutputReady()をサポートしている場合、毎回ASIOOutputReady()を呼び出す.
    ASIOOutputReady();
}
	

チャンネル情報を取得する

ASIOGetChannelInfo()を呼び出して、チャンネル情報を取得します。


    ASIOError ASIOGetChannelInfo( ASIOChannelInfo* info )
	

引数説明
info

チャンネル情報を格納するデータ(ASIOChannelInfo構造体)のポインタ
構造体のメンバ channel と isInput に問い合わせるチャンネルの情報をセットして呼び出します。

戻り値がASE_OKであれば、チャンネル情報が取得できます。

ASIOChannelInfo構造体は以下のとおりです。

メンバ名説明
channel

問い合わせるチャンネル番号を指定します。

isInput

問い合わせるチャンネルの入力/出力を次の値で指定します。
 - ASIOTrue
   入力チャンネル。
 - ASIOFalse
   出力チャンネル。

isActive

問い合わせたチャンネルがアクティブかどうかを次の値で表します。
 - ASIOTrue
   アクティブ。
 - ASIOFalse
   非アクティブ。

channelGroup

チャンネル・グループ番号。

type

サンプルデータのフォーマットが以下の値で返されます。
 - ASIOSTInt16MSB
   MSB(Big Endian) 16ビット
 - ASIOSTInt24MSB
   MSB 20ビット または、MSB 24ビット
 - ASIOSTInt32MSB
   MSB 32ビット
 - ASIOSTFloat32MSB
   32ビット単精度実数(Big Endian)
 - ASIOSTFloat64MSB
   64ビット倍精度実数(Big Endian)
 - ASIOSTInt32MSB16
   32ビット幅のMSB16ビットデータ
 - ASIOSTInt32MSB18
   32ビット幅のMSB18ビットデータ
 - ASIOSTInt32MSB20
   32ビット幅のMSB20ビットデータ
 - ASIOSTInt32MSB24
   32ビット幅のMSB24ビットデータ
 - ASIOSTInt16LSB
   LSB(Little Endian) 16ビット
 - ASIOSTInt24LSB
   LSB 20ビット または、LSB 24ビット
 - ASIOSTInt32LSB
   LSB 32ビット
 - ASIOSTFloat32LSB
   32ビット単精度実数(Little Endian)
 - ASIOSTFloat64LSB
   64ビット倍精度実数(Little Endian)
 - ASIOSTInt32LSB16
   32ビット幅のLSB16ビットデータ
 - ASIOSTInt32LSB18
   32ビット幅のLSB18ビットデータ
 - ASIOSTInt32LSB20
   32ビット幅のLSB20ビットデータ
 - ASIOSTInt32LSB24
   32ビット幅のLSB24ビットデータ
 - ASIOSTDSDInt8LSB1
   DSD 1ビットデータ(8 サンプル/バイト) LSB
 - ASIOSTDSDInt8MSB1
   DSD 1ビットデータ(8 サンプル/バイト) MSB
 - ASIOSTDSDInt8NER8
   DSD 8ビットデータ(1 サンプル/バイト)

name[32]

チャンネル名を示す文字列。

出力バッファ処理の完了をドライバに通知する

サウンド出力するデータをバッファにセットしたらASIOOutputReady()を呼び出して、アプリケーションで出力バッファへの処理が完了したことをドライバに通知します。


    ASIOError ASIOOutputReady( void )
	

戻り値がASE_OKならば通知完了です。



ASIOは Steinberg Media Technologies AG社の商標です。
Windowsは米国Microsoft Corporationの登録商標です。