バージョン

menu_open

Wwise サウンドエンジン ソースプラグインの作成方法

ソースプラグインインターフェースの実装

ソースプラグインは、物理モデリング、変調合成、サンプリング合成などを含む合成法を使用して、出力バッファにオーディオコンテンツを提供します。このドキュメントで詳述されているように、ソースプラグイン記述は AK::IAkSourcePlugin インターフェース実装より構成されます。ここでは、AKIAkSourcePlugin インターフェース固有の関数のみが取り扱われています。他のプラグインタイプと共有されるインターフェースに関する情報は、 Wwise サウンドエンジン プラグインの作り方 をご参照ください。詳細は、提供の Sine サンプルを参照してください(サンプル)。

AK::IAkSourcePlugin::Init()

このメソッドは、ソースプラグインがデータ処理、メモリ割り当て、初期条件設定を実行できるよう準備するものです。

プラグインは、メモリアロケータインターフェース(AKIAkPluginMemAlloc)へのポインタで渡されます。提供されているメモリ割り当てマクロを使用して、全ての動的メモリ割り当てをこのインターフェースを介して行う必要があります(Allocating/De-allocating オーディオプラグインにおけるメモリ 参照)。最も一般的なメモリ割り当てのニーズ、つまり初期化時の割り当ておよび終了時の解放では、プラグインがアロケータへのポインタを保持する必要がありません。終了時にもこのポインタがプラグインに提供されるためです。

AK::IAkSourcePluginContext インターフェースは、ループ反復数やソースプラグインが動作するコンテキストに関連するその他の情報の取得を可能にします。これはまた、AKIAkPluginContextBase::GlobalContext()を介してグローバルコンテキストにアクセスできます。

また、プラグインは、関連するパラメータノードインターフェースへのポインタを受け取ります( AK::IAkPluginParam )。ほとんどのプラグインは、関連するパラメータノードへの参照を保持して、実行時にパラメータを取得することになるでしょう。詳細は、Communication Between Parameter Nodes and Plug-ins. を参照してください。

これらのインターフェースは全てプラグインのライフスパンを通じて有効なので、必要に応じてこれらへの内部参照を保持しておくのが安全です。

プラグインが実行されるプラットフォームにネイティブなオーディオフォーマットは、AK::IAkSourcePlugin::Init() 関数の引数として渡されます。オーディオフォーマット変換によって生じるパフォーマンスペナルティを避けるために、プラグインがプラットフォームのネイティブフォーマットで出力されることをお勧めします。何らかの理由で、ソースがこのフォーマットでの出力に適していない場合は、インターリーブされた16ビット符号付きサンプルも出力するおそれがあります。マルチチャンネル構成では、ソースプラグインがインターリブデータまたはデインターリーブデータのどちらで出力するかを指定する必要があります(AkAudioFormat::uInterleaveID)。デフォルトのネイティブ設定は、AK_NONINTERLEAVED です。デインターリーブされたデータを出力する場合、ソースプラグインは AkAudioBuffer::GetChannel() メソッドを使用して各チャンネルのバッファにアクセスする必要があります。インターリブされたデータを出力する場合には、AkAudioBuffer::GetInterleavedData() を使用します。ソースプラグインのインタリーブされたデータの7.1チャンネルの場合、チャネルの順序はL-R-C-LFE-BL-BR-SL-SRです。詳細は、 AkAudioBuffer構造体を使用するデータにアクセスする を参照してください。

渡されたチャンネルマスクは、モノ(センタースピーカーのみ)チャンネル構成にデフォルトで設定されます。このチャンネルマスクを、ソースプラグインに出力させたい任意のチャンネル構成に変更する場合があるかもしれません。以下のコード例では、チャンネルマスクがステレオに変更されています。各 Execute で受信するオーディオバッファは、初期化時にプラグインに指定されるフォーマットに対応可能で、プラグインのライフスパンを通じて変更されることがないため、初期化ルーチン中に後の処理で必要となる全てのフォーマット情報を格納しておくのが安全でしょう。

AKRESULT CAkDCOffset::Init( AK::IAkPluginMemAlloc *     in_pAllocator,              // Memory allocator interface.
                            AK::IAkSourcePluginContext * in_pSourcePluginContext,   // Source plugin context
                            AK::IAkPluginParam *        in_pParams,                 // Effect parameters.
                            AkAudioFormat &             io_rFormat                  // Supported audio output format.
                            )   
{
    // Keep a pointer to associated parameter node.
    m_pParams = reinterpret_cast<CAkMyPluginParams*>( in_pParams );
    
    // Setup helper to handle looping and possibly changing duration of synthesis
    m_DurationHandler.Setup( m_pParams->fDuration, in_pSourceFXContext->GetNumLoops(), io_rFormat.uSampleRate ); 

    // Output format set to Mono native by default (input). Change to Stereo output.
    io_rFormat.channelConfig.SetStandard(AK_SPEAKER_SETUP_STEREO);

    ...

    return AK_Success;
}
Note.gif
Note: AK::IAkSourcePlugin::Init() は、エフェクトがインスタンスを生成するたびに呼び出されます。これはボイスの再生開始時、またはミキシングバスがインスタンス化された場合に起きます。他のサウンドが既に再生されていることが常なので、これは合理的な時間の間に発生する必要があります。大きな共通/グローバルなデータ構造を初期化する必要がある場合には、プラグインライブラリを登録している時に行うのがよいでしょう。詳細は、プラグインからグローバル サウンド エンジン コールバックを使用する を参照してください。

AK::IAkSourcePlugin::GetDuration()

このメソッドは、サウンド遷移時のクロスフェード処理を行うために、初期化の後でサウンドエンジンによって呼び出されます。ソースの推定持続時間はミリ秒で単位で返されます。ルーピングに有限回の反復が印加されている場合、サウンドの反復が何回再生されるかを考慮して、返される継続期間が総持続時間に対応している必要があります。無限ループが選択されている場合、または、ソース持続時間が不明な場合、返される期間はゼロでなければなりません。無限ループ選択時に、AKIAkSourcePluginContext::GetNumLoops() を介して取得されるループ回数は、常にゼロであることに注意してください。

// Get the duration of the source in milliseconds.
AkTimeMs CAkDCOffset::GetDuration( ) const
{
    return m_DurationHandler.GetDuration() * 1000.f; 
}
Note.gif
Note: RTPC パラメータがプラグインの継続時間を変更すると、クロスフェード遷移が期待される期間を持続しない場合があります。
Note.gif
Note: ソースプラグインの(ルーピングを含む)経過時間管理を処理する最も簡単な方法は、Sine プラグインの例のように AkFXDurationHandler サービスを使用することです (サンプル)。

AK::IAkSourcePlugin::StopLooping()

このメソッドは、ブレークアクションを受信した際にサウンドエンジンによって呼び出されます。ブレークアクションとは、滑らかな停止のことです。 この関数によって、プラグインは再生を滑らかに終了させる方法を実装します。通常は、単純にルーピングを停止して、リリースがある場合はこれを再生します。 この関数は、ブレークコマンドを無視または処理する場合には、AK_Success を返します。 プラグインがこれを処理しない場合、この関数は AK_Fail を返し、これによりソースは再生を停止します。

Stop playback after the current loop iteration AKRESULT CAkDCOffset::StopLooping() { m_DurationHandler.SetLooping( 1 ); // No longer looping. return AK_Success; }

Note.gif
Note: この関数はオプションです。これを実装しない場合、ソースはブレークコマンドを無視して最後まで正常に再生します。

AK::IAkSourcePlugin::GetEnvelope()

このメソッドは、次の Execute() への呼び出しで、ソースプラグインが生成する正規化された振幅エンベロープ値の推定値を、0 と1の間で取得するために呼び出されます。Wwise の現在のバージョンでは、これは、アルゴリズムがよりソフトな音を減衰させるためにエンベロープの推定値を使用する HDR 処理のために使用されます。この関数はオプションです:1 (デフォルト)を返すと、HDR バス下でプラグインが使用される場合に、よりソフトな音の減衰が一定になります。

これを実装することにした場合には、これが正規化されたエンベロープ値を返すこと、つまり、あなたが生成しようとしている波形のピーク値を認識していること、または、エンベロープの現在の値のみを返せるように、振幅エンベロープとゲインが分離されていることを確認してください。

AK::IAkSourcePlugin::Execute()

このメソッドは、ソースプラグインのオーディオ信号処理アルゴリズムを実行し、オーディオ出力バッファを充填します( AkAudioBuffer構造体を使用するデータにアクセスする 参照)。関数の入力時には、出力バッファの AkAudioBuffer::uValidFrames フィールドは、常にゼロになり、有効なオーディオフレームがチャンネルバッファに存在しないことを意味します。AkAudioBufferMaxFrames() メソッドは、ソースが充填するべきオーディオサンプルフレームの最大数を返します。プラグインは、たとえば、継続時間などのパラメータ値に応じて、出力サンプルフレームがいくつ生成されるべきかを判定します。これに従ったオーディオバッファの AkAudioBuffer::uValidFrames フィールド設定によりサンプルフレームが実際にいくつ生成されたかを、DSPの実行後にソースプラグインがオーディオパイプラインへ通知します。

Note.gif
Note: 一般に、このアルゴリズムはパイプラインの枯渇を避けるために、フルバッファを常に生成しようとします。

ソースプラグインが AkAudioBuffer 構造体の eState フィールドを AK_DataReady に設定している限り、Execute() ルーチンが呼び出されます。AK_NoMoreData が返されると、プラグインが終了し、オーディオパイプラインによって呼び出されることはありません。 Wwise の現在のバージョンは、6チャンネルまで出力するソースプラグインをサポートしています(5.1 セットアップ、 チェンネルの配列 参照)。

ソースプラグインの実行に関する重要な注意事項

  • ソースプラグインは、完全なサンプルフレーム、つまり、指定された出力フォーマットの各チャンネルに対するサンプルを常に生成する必要があります。
  • プラグインが、実行時にRTPCをサポートするパラメータをチェックするよう確認するのはあなたの責任です。パラメータノードから値を取得するためのアクセサメソッドを共有パラメータインターフェースに実装し、実行時にこれを必要に応じて頻繁に呼び出す必要があります。詳細は、Communication Between Parameter Nodes and Plug-ins. を参照してください。ほとんどのパラメータ値については、各バッファごとに1度チェックするだけでじゅうぶんです。信号の不連続を避けるためにパラメータ値(たとえば、ゲインなど)を上昇させる方法についてはサンプルコード例を参照してください(サンプル)。
  • Wwiseでプラグインが使用される場合、パラメータが RTPC をサポートするかどうかに関わらず、パラメータの変更はパラメータノードまで送信されます。これにより、Wwise 使用の必要に応じて、プラグインは非 RTPC 値に対して実行時の値変更をサポートできるようになります。プラグインがこれをサポートしないようにするには、初期化時にパラメータ値のコピーを作成し、プラグインの存続期間を通じてこれらの値が変化しないようにする必要があります。これに関する例は、CAkToneGenInit をご参照ください。
  • AK::IAkSourcePlugin::Execute() メソッドで実行される処理を最適化し、これがバッファによって表されるタイムスライス内で十分に完了されるようにする必要があります。これを怠ると、このソースパイプラインおよび場合によっては他のソースパイプラインのソース不足が発生する可能性があります。また、サウンドエンジンのパフォーマンスにも大きな影響が与えられる可能性もあります。

DC オフセットプラグイン Execute() 関数を以下に示しています。更なる詳細は、CAkSrcSineExecute() と様々なトーンジェネレータの DSP ルーチンを参照してください。

// This example demonstrates a simple application which outputs a steady DC offset signal using an RTPC parameter.
void CAkDCOffset::Execute( AkAudioBuffer * io_pBuffer ) 
{   
    // Set new duration when it changes (e.g. RTPC parameter)
    m_DurationHandler.SetDuration( m_pParams->fDuration );
    
    // Determine how many sample frames to produce this execution and set uValidFrames and eState according to current state
    m_DurationHandler.ProduceBuffer( io_pBuffer ); 
    
    // Retrieve RTPC DC offset parameter
    AkReal32 fDCOffset = m_pParams->GetDCOffset( );
        
    // DC offset output DSP (supports any number of channels)
    for ( unsigned int i = 0; i < m_uNumChannels; ++i )
    {
        AkSampleType * pBufOut = io_pBuffer->GetChannel(i); // AkSampleType is platform specific (AkReal32 on software platforms).
        AkUInt32 uFrameCount = io_pBuffer->uValidFrames;
        while ( uFrameCount-- )
        {
            *pBufOut++ = AK_FLOAT_TO_SAMPLETYPE( fDCOffset );       // DC-offset output, will convert normalized float to platform supported format.
        }
    }
}

AK::IAkSourcePlugin::Execute()

バーチャルボイスが「Play from elapsed time (経過した時間から再生)」に設定された時、AKIAkSourcePlugin::TimeSkip() が Execute() に置き換わります。これにより、必要であれば、ソースプラグインがその内部状態 (高度な合成時間など) を継続して更新できます。これは、プラグイン実行によるCPUヒットの大半を回避しながら行われたであろう処理をシミュレートするためにも使用することができます。要求されたフレーム数を考慮して、io_uFrames パラメータでExecute()を呼び出し、生成されるはずだったフレーム数を調整し、その時点でオーディオ出力かあるかないかによって、AK_DataReady または AK_NoMoreDataを返します。

AK_NotImplemented を返すと、通常のボイスの実行をトリガーします (バーチャルでなかったかのように)。従って、適切な「Play from elapsed time」動作のCPUの節約はできません。

// This example shows how to skip the processing of some frames when the virtual voice is set to "Play from elapsed time".
AKRESULT CAkDCOffset::TimeSkip( AkUInt32 &io_uFrames )
{
    AkUInt16 uValidFrames = (AkUInt16)io_uFrames;
    AkUInt16 uMaxFrames = (AkUInt16)io_uFrames;
    AKRESULT eResult = m_DurationHandler.ProduceBuffer( uMaxFrames, uValidFrames );
    io_uFrames = uValidFrames;
    return eResult;
}
\

詳細については、以下のセクションをご参照ください: Wwiseサウンドエンジン プラグインの概要, エフェクトプラグイン インタフェースの実装, オーディオプラグイン Wwiseオーサリング 部分の記述


このページはお役に立ちましたか?

サポートは必要ですか?

ご質問や問題、ご不明点はございますか?お気軽にお問い合わせください。

サポートページをご確認ください

あなたのプロジェクトについて教えてください。ご不明な点はありませんか。

プロジェクトを登録していただくことで、ご利用開始のサポートをいたします。

Wwiseからはじめよう