このサンプルはワークメモリ既にある波形データをPCMストリームを利用して再生を行うプログラムです.
サウンドライブラリ・ドライバの初期化を行い,440Hzの音を再生する.
処理の流れとしては
本サンプルには下記の注意事項があります.
実際のコーディングを下記に提示する.なお,このサンプルはエラーチェックをかなり省いています.
/********************************************************* * * Sound Library Sample * * ワークメモリ上の波形データをPCMストリームで再生する. * *********************************************************/ #include <sd_sg.h> /* 前もって転送しておく波形サイズ(単位はバイト) */ #define PRE_TRANS_SZ (0x4000) /* 再生中に転送する波形サイズ(単位はバイト) */ #define TRANS_SZ (0x1000) SDE_ERR OnMemoryPCMStream( Sint8 ch_num, チャンネル数(モノラルは0,ステレオは1) SDE_PCM_TYPE src_type, 波形データのタイプ. Uint16 src_freq, サンプリング周波数(本当にサンプリング周波数が入っているわけではない) Void *ch0_src_adr, チャンネル0(ステレオの場合は左チャンネル)の再生波形の先頭アドレス. Void *ch1_src_adr, 左チャンネルの再生波形の先頭アドレス(ステレオの場合のみ有功.モノラルの時は無視される) Sint32 src_sz) 波形サイズ(単位はバイト) { SDPSTM pstm_handle = NULL; Sint32 seek_sz, ch; Sint8 *seek_adr[ SDD_PSTM_CH_MAX]; SDMEMBLK memblk[ SDD_PSTM_CH_MAX]; Sint32 i; /* * ローカル変数の初期化 */ for ( i = 0; i < [ SDD_PSTM_CH_MAX]; i++) { memblk[ i] = NULL; } seek_adr[ 0] = ch0_src_adr; seek_adr[ 1] = ch1_src_adr; /* * PCMストリームポートのハンドルを取得する */ #if PCM_CH==1 /* * モノラルの場合 */ /* リングバッファは0番使用する */ if ( sdPstmOpenPort( &pstm_handle, PSTM_CH, 0) != SDE_ERR_NOTHING) #elif PCM_CH==2 /* * ステレオの場合 */ /* リングバッファは0番と1番を使用する */ if ( sdPstmOpenPort( &pstm_handle, PSTM_CH, 0, 1) != SDE_ERR_NOTHING) #else #error PCMチャンネルは1もしくは2のみ指定可能. #endif /* PCM_CH==1 */ { /* エラーが起こった */ goto exit; } /* * メモリブロックハンドルの取得 */ for ( ch = 0; ch < ch_num; ch++) { if ( sdMemBlkCreate( &memblk[ ch]) != SDE_ERR_NOTHING) { /* エラーが起こった */ goto exit; } } /* * まずあらかじめリングバッファを少し埋めておく */ for ( ch = 0; ch < ch_num; ch++) { Bool flg; /* 念の為転送していいかどうか調べてみる */ do { sdPstmIsTransfer( pstm_handle, ch, PRE_TRANS_SZ, &flg); } while ( flg != true); /* 実際に転送 */ sdMemBlkSetPrm( memblk[ ch], seek_adr[ ch], PRE_TRANS_SZ, SDD_MEMBLK_SYNC_FUNC, NULL); sdPstmTransfer( pstm_handle, memblk[ ch]); /* シーク位置の移動 */ seek_adr[ ch] = &seek_adr[ ch][ PRE_TRANS_SZ]; } /* * PCMストリーム再生開始 */ if ( sdPstmPlay( pcm_handle, src_type, src_freq, 0) != SDE_ERR_NOTHING) { /* エラーが起こった */ goto exit; } /* * 必要分だけ波形データを逐次転送する */ for ( seek_sz = PRE_TRANS_SZ; seek_sz < src_sz; seek_sz += TRANS_SZ) { for ( ch = 0; ch < ch_num; ch++) { Bool flg; /* 念の為転送していいかどうか調べてみる */ do { sdPstmIsTransfer( pstm_handle, ch, TRANS_SZ, &flg); } while ( flg != true); /* 実際に転送 */ sdMemBlkSetPrm( memblk[ ch], seek_adr[ ch], TRANS_SZ, SDD_MEMBLK_SYNC_FUNC, NULL); sdPstmTransfer( pstm_handle, memblk[ ch]); /* シーク位置の移動 */ seek_adr[ ch] = &seek_adr[ ch][ TRANS_SZ]; } } exit: if ( pstm_handle != NULL) { /* PSTMポートの再生停止 */ sdPstmStop( pcm_handle); /* PSTMポートのハンドルの破棄 */ sdPstmClosePort( pstm_handle); } for ( i = 0; i < ch_num; i++) { if ( memblk[ i] != NULL) { sdMemBlkDestory( memblk[ i]); } } } /*EOF*/ |
現在メモリブロックハンドルにのコールバック関数SDD_MEMBLK_SYNC_FUNCを使用していますが,独自でコールバック関数を用意することで波形データの転送終了を待たずに別の処理をすることが可能になります(その場合上記のサンプルよりかなり複雑な処理になります)