ワークメモリについて

CRI Atomライブラリのいくつかの関数は、実行時に作業用のメモリ領域(ワークメモリ)を必要とするものがあります。
本項では、ワークメモリの用途や、ワークメモリの割り当て方法について説明します。

ワークメモリが必要な処理

ワークメモリを必要とする処理には、以下のものがあります。
各処理の詳細は以下のとおりです。

(1) ライブラリの初期化

CRI Atomライブラリは、初期化時にスレッドの作成等を行うため、ワークメモリを必要とします。
初期化時に必要なワークメモリのサイズは、criAtomEx_CalculateWorkSize関数で計算が可能です。
ライブラリが初期化時に必要とするワークメモリのサイズは、初期化時に指定するフレームワーク等の設定(CriAtomExConfig)によって変化します。
例えば、スレッドモデルがCRIATOMEX_THREAD_MODEL_MULTIの場合、CRI Atomライブラリはスレッドを作成するため、スレッド作成用のメモリ領域を必要とします。
しかし、スレッドモデルがCRIATOMEX_THREAD_MODEL_USER_MULTICRIATOMEX_THREAD_MODEL_SINGLEの場合、CRI Atomライブラリはスレッドを作成しないため、スレッド作成用のメモリ領域を必要としません。
そのため、スレッドモデルにCRIATOMEX_THREAD_MODEL_MULTIを指定する場合に比べ、CRIATOMEX_THREAD_MODEL_USER_MULTICRIATOMEX_THREAD_MODEL_SINGLE指定時は必要なワークメモリのサイズが小さくなります。
[注意]
スレッドモデルにCRIATOMEX_THREAD_MODEL_USER_MULTICRIATOMEX_THREAD_MODEL_SINGLEを指定した場合、必要なメモリサイズは小さくなりますが、サーバー処理の負荷が大きくなります。
CRIATOMEX_THREAD_MODEL_MULTI指定時に別スレッド上で行われる処理を、全てサーバー処理内で行うようになるため。)
そのため、ユーザ自身でサーバー処理の負荷変動を吸収する仕組みを実装する必要があるため、実装の難度は高くなります。
(2) ボイスプールの作成

ボイスプールを作成する際には、データ読み込み用のバッファや音声データのデコードに使用する作業領域、サウンド出力用のリソース等を確保するため、ワークメモリが必要になります。
ボイスプール作成時に必要なワークメモリのサイズは、ボイスプレーヤを作成する関数によって異なります。
ボイスプール作成関数と、ワークメモリサイズ計算関数の対応付けは、以下のとおりです。
ボイスプール作成関数とワークメモリサイズ計算関数
ボイスプール作成関数 ワークメモリ計算関数
criAtomExVoicePool_AllocateStandardVoicePool criAtomExVoicePool_CalculateWorkSizeForStandardVoicePool
criAtomExVoicePool_AllocateAdxVoicePool criAtomExVoicePool_CalculateWorkSizeForAdxVoicePool
criAtomExVoicePool_AllocateHcaVoicePool criAtomExVoicePool_CalculateWorkSizeForHcaVoicePool
criAtomExVoicePool_AllocateHcaMxVoicePool criAtomExVoicePool_CalculateWorkSizeForHcaMxVoicePool


ライブラリの初期化と同様、ボイスプールの作成時に必要なワークメモリのサイズは、ボイスプール作成時の設定( CriAtomExAdxVoicePoolConfig 等)によって変化します。
具体的には、最大出力チャンネル数や最大サンプリング周波数については、指定する値が小さいほど必要とするワークメモリは小さくなります。
例えば、ボイスプールでモノラル音声しか再生しない場合、最大出力チャンネル数を1に指定することで、2を指定する場合に比べてワークメモリを小さく抑えることが可能です。
同様に、サンプリング周波数が24kHz以下の音声しか再生しない、最大サンプリング周波数に24000を指定することで、48000を指定する場合に比べてワークメモリを小さく押さえることが可能です。
[注意]
最大出力チャンネル数を1に設定してボイスプールを作成した場合、作成されたボイスプールではステレオ音声を再生することはできません。
同様に、最大サンプリング周波数を24kHzに設定してボイスプールを作成した場合、作成されたボイスプールでは32kHzや48kHzの音声を再生することはできません。
(3) ACFの登録

ACFを登録する際には、ACF情報を保存する領域やACFファイルから直接登録する場合は、データ読み込み用のバッファを確保するため、ワークメモリが必要になります。
ACF登録に必要なワークメモリのサイズは、ACFを登録する方法により異なります。
ACF登録関数と、ワークメモリサイズ計算関数の対応付けは、以下のとおりです。
ACF登録関数とワークメモリサイズ計算関数
ACF登録関数 ワークメモリ計算関数
criAtomEx_RegisterAcfConfig criAtomEx_CalculateWorkSizeForRegisterAcfConfig
criAtomEx_RegisterAcfData criAtomEx_CalculateWorkSizeForRegisterAcfData
criAtomEx_RegisterAcfFile criAtomEx_CalculateWorkSizeForRegisterAcfFile

(4) ACBのロード

ACBをロードする際には、ACB情報を保存する領域や、ACBファイルからロードする場合はデータ読み込み用のバッファを確保するため、ワークメモリが必要になります。
ACBのロードに必要なワークメモリのサイズは、ACBのロード方法により異なります。
ACBロード関数と、ワークメモリサイズ計算関数の対応付けは、以下のとおりです。
ACBロード関数とワークメモリサイズ計算関数
ACBロード関数 ワークメモリ計算関数
criAtomExAcb_LoadAcbData criAtomExAcb_CalculateWorkSizeForLoadAcbData
criAtomExAcb_LoadAcbFile criAtomExAcb_CalculateWorkSizeForLoadAcbFile

(5) D-BASの作成

D-BASはストリーミングバッファの管理機能であるため、ストリーミングバッファと、ストリーミングバッファを管理するためのワークメモリが必要です。
D-BAS作成時に必要なワークメモリのサイズは、ストリーミング再生を利用するアプリケーション単位、またはシーン単位で異なります。
D-BAS作成関数とワークメモリサイズ計算関数
D-BAS作成関数 ワークメモリ計算関数
criAtomExDbas_Create criAtomExDbas_CalculateWorkSize

D-BASに設定する消費ビットレートを求める際は、以下の関数を使用します。
各コーデックの消費ビットレート計算関数
ADX HCA(HCA-MX)
criAtomEx_CalculateAdxBitrate criAtomEx_CalculateHcaBitrate

各機種固有のコーデックが存在する場合、上記と同様の関数が機種固有ヘッダーで宣言されています。
(6) AtomExプレーヤの作成

AtomExプレーヤを作成する際には、プレーヤ領域や、ファイルパスを保存する領域を確保するため、ワークメモリが必要になります。
AtomExプレーヤ作成時に必要なワークメモリのサイズは、ファイルパス指定の再生を行うかどうかにより異なります。
AtomExプレーヤ作成関数と、ワークメモリサイズ計算関数の対応付けは、以下のとおりです。
AtomExプレーヤ作成関数とワークメモリサイズ計算関数
AtomExプレーヤ作成関数 ワークメモリ計算関数
criAtomExPlayer_Create criAtomExPlayer_CalculateWorkSize

ワークメモリの割り当て方法

CRI Atomライブラリを使用する場合、ライブラリを初期化する際や、AtomExプレーヤを作成する際に、ライブラリが使用する作業領域として"ワークメモリ"を与える必要があります。
CRI Atomライブラリに対してワークメモリを割り当てる方法として、CRI Atomライブラリは以下2通りの方法を提供しています。
各方式の詳細は以下のとおりです。
(1) Fixed Memory方式について

Fixed Memory方式は、ワークメモリを必要とする関数を実行する際に、必要なワークメモリを関数の引数としてセットする方法です。
criAtomEx_Initialize関数(ライブラリの初期化)や、criAtomExPlayer_Create関数(AtomExプレーヤの作成)等、ライブラリに対してメモリを割り当てる必要があるAPIについては、関数の引数に必ず以下の2つのパラメーターが含まれています。
例えば、criAtomEx_Initialize関数の場合、第二引数の「void *work」と、第三引数の「CriSint32 size」が上記に該当します。
これらのAPIを実行する際には、ユーザはあらかじめ確保しておいたメモリ領域を、関数の引数としてセットする必要があります。
関数にセットするワークメモリのサイズは、専用のワークメモリサイズ計算関数を用いて計算します。
例えば、criAtomEx_Initialize関数の場合、関数の実行に必要なワークメモリのサイズは、criAtomEx_CalculateWorkSize関数を使って計算することが可能です。
以上の手順をまとめると、Fixed Memory方式によるワークメモリの割り当て手順は以下のようになります。
  1. ワークメモリ要求関数(※)に必要なワークメモリのサイズを計算する。
  2. 計算結果として返されたサイズ分のメモリを確保する。
  3. 確保されたメモリを引数とし、ワークメモリ要求関数を実行する。
※ワークメモリ要求関数:関数実行時にワークメモリを必要とする関数。
[例]
Fixed Memory方式を用いて初期化処理を行う例を、以下に示します。
main()
{
    void *work;             // ワークメモリアドレス
    CriSint32 size;        // ワークメモリサイズ
        :
    // ライブラリの初期化に必要なワークメモリのサイズを計算
    size = criAtomEx_CalculateWorkSize(&config);
    
    // ワークメモリの確保
    work = malloc((size_t)size);
    
    // ライブラリの初期化
    // →確保済みのワークメモリを指定する。
    criAtomEx_Initialize(&config, work, size);
        :
    // アプリケーションのメイン処理
    // →この間、確保したメモリは保持し続ける。
        :
    // アプリケーションを終了する際に終了処理を行う
    criAtomEx_Finalize();
    
    // 必要なくなったワークメモリを解放する
    free(work);
        :
}

[注意]
ワークメモリとしてセットした領域は、ライブラリの終了処理を行うまでの間、ライブラリ内で様々な用途に利用されます。
初期化時にセットしたワークメモリについては、終了処理を行うまでの間ユーザが保持し続ける必要があります。
(ワークメモリを他の用途に転用したり、解放しないでください。)
(2) User Allocator方式について

関数実行毎にワークメモリを割り当てる方法の他に、ユーザが作成したメモリアロケーターをCRI Atomライブラリにセットする方法があります。
この方法を、User Allocator方式と呼んでいます。
User Allocator方式を使用する場合、ユーザはあらかじめメモリ確保関数と、メモリ解放関数を用意し、CRI Atomライブラリにセットする必要があります。
メモリ確保関数は標準ライブラリのmalloc関数に相当するもので、指定したサイズ分のメモリを動的に確保し、メモリブロックのアドレスを返す関数です。
同様に、メモリ解放関数は標準ライブラリのfree関数に相当するもので、メモリ確保関数で確保されたメモリブロックを解放する関数です。 ユーザはこれら2つの機能を、CRI Atomライブラリが規定するインターフェースに合わせて実装し、登録する必要があります。
具体的なインターフェースと登録関数は以下のとおりです。
実装インターフェースと登録関数
実装インターフェース 登録関数
メモリ確保関数
CriAtomMallocFunc
criAtomEx_SetUserAllocator マクロ
メモリ解放関数
CriAtomFreeFunc
criAtomEx_SetUserAllocatorマクロ


メモリ確保関数とメモリ解放関数をCRI Atomライブラリにセットすることで、CRI Atomライブラリはワークメモリの確保/解放を全て登録された関数経由で行うよう動作を変更します。
そのため、User Allocator方式を用いる場合、ワークメモリ要求関数を実行する際でもワークメモリを関数に指定する必要はありません。
(メモリアドレスにNULL、メモリサイズに0を指定します。)
以上の手順をまとめると、User Allocator方式によるワークメモリの割り当て手順は以下のようになります。
  1. メモリ確保関数とメモリ解放関数をCRI Atomライブラリに登録する。
  2. ワークメモリ要求関数を実行する。
    (メモリアドレスはNULL、メモリサイズは0を指定する。)
[例]
User Allocator方式を用いて初期化処理を行う例を、以下に示します。
// 独自のメモリ確保関数
void *user_malloc(void *obj, CriUint32 size)
{
    void *mem;
    
    // メモリの確保
    mem = malloc(size);
    
    return (mem);
}

// 独自のメモリ解放関数を用意
void user_free(void *obj, void *mem)
{
    // メモリの解放
    free(mem);
    
    return;
}

main()
{
    // 独自のメモリアロケーターを登録
    criAtomEx_SetUserAllocator(user_malloc, user_free, NULL);
    
    // ライブラリの初期化
    // ワークメモリにはNULLと0を指定する。
    // →必要なメモリは、登録したメモリ確保関数を使って確保される。
    criAtomEx_Initialize(NULL, NULL, 0);
        :
    // アプリケーションのメイン処理
        :
    // アプリケーションを終了する際に終了処理を行う
    // →初期化時に確保されたメモリは、登録したメモリ解放関数を使って解放される。
    criAtomEx_Finalize();
        :
}


Next:ハンドルについて

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