CRI ADX  Last Updated: 2024-03-21 14:32 p
Raw PCMの再生

サンプルのディレクトリ

/cri/pc/samples/criatomex/raw_pcm_playback

サンプルで使用しているデータ

なし

サンプルの解説

プログラムで生成した生PCMデータを出力するサンプルです。
Raw PCMボイスとシームレス連結再生機能を利用し、無限に生成したサイン波形の出力を行っています。
Raw PCMデータを生成して出力するサンプルコードを以下に示します。
void main()
{
/* Raw PCMボイスプールの作成 */
rawpcm_vpconfig.identifier = RAW_PCM_VOICE_POOL_ID;
rawpcm_vpconfig.num_voices = 1;
rawpcm_vpconfig.player_config.max_channels = 1;
raw]pcm_vpconfig.player_config.max_sampling_rate = PCM_SAMPLING_RATE;
rawpcm_vpconfig.player_config.pcm_format = CRIATOM_PCM_FORMAT_SINT16;
&rawpcm_vpconfig, NULL, 0);
/* 再生する音声データのフォーマット情報を指定 */
criAtomExPlayer_SetSamplingRate(player, PCM_SAMPLING_RATE);
criAtomExPlayer_SetVoicePoolIdentifier(app_obj->player, RAW_PCM_VOICE_POOL_ID);
/* 次回データを供給するためのコールバック関数を指定 */
criAtomExPlayer_SetDataRequestCallback(player, app_data_request_func, app_obj);
/* 最初のデータを指定して再生 */
memset(app_obj->pcm_buffer[0], 0, PCM_BUFFER_LENGTH * sizeof(CriSint16));
app_obj->sin_offset = 0.0f;
app_obj->pcm_buffer_current = 0;
criAtomExPlayer_SetData(app_obj->player,
app_obj->pcm_buffer[0], PCM_BUFFER_LENGTH * sizeof(CriSint16));
}
static void app_data_request_func(
void *obj, CriAtomExPlaybackId id, CriAtomPlayerHn player)
{
AppObj *app_obj = (AppObj*)obj;
CriFloat32 sin_offset = app_obj->sin_offset;
CriFloat32 sin_step = 2.0f * 3.141592f * app_obj->sin_frequency / PCM_SAMPLING_RATE;
/* 使用バッファ切り替え */
app_obj->pcm_buffer_current++;
app_obj->pcm_buffer_current %= 2;
CriSint16 *buffer = app_obj->pcm_buffer[app_obj->pcm_buffer_current];
/* サイン波形を生成 */
for (i = 0; i < PCM_BUFFER_LENGTH; i++) {
buffer[i] = (CriSint16)(sinf(sin_offset) * 32767.0f);
sin_offset += sin_step;
}
app_obj->sin_offset = fmodf(sin_offset, 2.0f * 3.141592f);
/* プレーヤーに次のデータをセット */
criAtomPlayer_SetData(player, buffer, PCM_BUFFER_LENGTH * sizeof(CriSint16));
}
#define CRIATOMEX_FORMAT_RAW_PCM
Definition: cri_atom_ex.h:1936
void criAtomExPlayer_SetVoicePoolIdentifier(CriAtomExPlayerHn player, CriAtomExVoicePoolIdentifier identifier)
ボイスプール識別子の指定
void criAtomExPlayer_SetData(CriAtomExPlayerHn player, void *buffer, CriSint32 size)
音声データのセット(オンメモリデータの指定)
void criAtomExPlayer_SetFormat(CriAtomExPlayerHn player, CriAtomExFormat format)
フォーマットの指定
CriAtomExPlaybackId criAtomExPlayer_Start(CriAtomExPlayerHn player)
再生の開始
void criAtomExPlayer_SetDataRequestCallback(CriAtomExPlayerHn player, CriAtomExPlayerDataRequestCbFunc func, void *obj)
データ要求コールバック関数の登録
CriUint32 CriAtomExPlaybackId
再生ID
Definition: cri_atom_ex.h:3756
void criAtomExPlayer_SetNumChannels(CriAtomExPlayerHn player, CriSint32 num_channels)
チャンネル数の指定
void criAtomExPlayer_SetSamplingRate(CriAtomExPlayerHn player, CriSint32 sampling_rate)
サンプリングレートの指定
#define criAtomExVoicePool_SetDefaultConfigForRawPcmVoicePool(p_config)
RawPCMボイスプール作成用コンフィグ構造体にデフォルト値をセット
Definition: cri_atom_ex.h:675
CriAtomExVoicePoolHn criAtomExVoicePool_AllocateRawPcmVoicePool(const CriAtomExRawPcmVoicePoolConfig *config, void *work, CriSint32 work_size)
RawPCMボイスプールの作成
struct CriAtomPlayerTag * CriAtomPlayerHn
Atomプレーヤーハンドル
Definition: cri_atom.h:2427
void criAtomPlayer_SetData(CriAtomPlayerHn player, void *buffer, CriSint32 buffer_size)
音声データのセット(オンメモリデータの指定)


使用するバッファについて

criAtomExPlayer_SetData に指定するバッファは指定後、2回目のコールバックが呼ばれるまで破棄してはいけません。
基本的にダブルバッファ以上で運用してください。
CriAtomExPlayerStatusCRIATOMEXPLAYER_STATUS_STOP になったら破棄しても問題ありません。

バッファのサイズは小さすぎると音途切れが発生する場合があります。
1サーバー周期分以上のバッファが必要です。以下の式を参考にしてください。

  • 1サーバー周期分 = サンプリングレート / サーバー周波数
  • バッファサイズ = 1サーバー周期分 + 安全マージン分
    例えば48000Hzの場合、1024サンプル分のバッファを用意してください。

マルチチャンネルデータ

マルチチャンネルデータの場合、インターリーブ形式でデータを作る必要があります。
インターリーブデータの作り方は以下のコードをご参考ください。
float L_ch[1024];
float R_ch[1024];
float *buffer[1024 * 2];
buffer[0] = L_ch[0];
buffer[1] = R_ch[0];
buffer[2] = L_ch[1];
buffer[3] = R_ch[1];
buffer[4] = L_ch[2];
buffer[5] = R_ch[2];
:
:
criAtomPlayer_SetData(player, buffer, sizeof(buffer));