Raw PCMの再生

サンプルのディレクトリ

/cri/pc/samples/criatomex/raw_pcm_playback

サンプルの解説

プログラムで生成した生PCMデータを出力するサンプルです。
Raw PCMボイスとシームレス連結再生機能を利用し、無限に生成したサイン波形の出力を行っています。
Raw PCMデータを生成して出力するサンプルコードを以下に示します。
void main()
{
    /* Raw PCMボイスプールの作成 */
    criAtomExVoicePool_SetDefaultConfigForRawPcmVoicePool(&rawpcm_vpconfig);
    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;
    app_obj->rawpcm_pool = criAtomExVoicePool_AllocateRawPcmVoicePool(
        &rawpcm_vpconfig, NULL, 0);

    /* 再生する音声データのフォーマット情報を指定 */
    criAtomExPlayer_SetFormat(player, CRIATOMEX_FORMAT_RAW_PCM);
    criAtomExPlayer_SetSamplingRate(player, PCM_SAMPLING_RATE);
    criAtomExPlayer_SetNumChannels(player, 1);
    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));

    criAtomExPlayer_Start(player);
}
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));
}

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

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

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

マルチチャンネルデータ

マルチチャンネルデータの場合、インターリーブ形式でデータを作る必要があります。
インターリーブデータの作り方は以下のコードをご参考ください。
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));

CRI Middleware logo Copyright (c) 2006-2018 CRI Middleware Co., Ltd.