Microsoft DirectMusic によるクロスフェード ソリューション

Scott Selfon
Audio Content Consultant, Xbox Advanced Technology Group

November 2001

要約: 本ドキュメントは、Microsoft DirectMusic 用のコンテンツ作成ツールである Microsoft DirectMusic Producer のさまざまな側面を扱った一連の記事のうちの一編です。この記事では、ボリューム コントローラ カーブ、オーディオパス、および Microsoft DirectX オーディオ スクリプティングを使って、セグメント間でのクロスフェードを実現する方法について説明します。

はじめに

クロスフェーディングは、ある要素のオーディオから別の要素のオーディオにスムーズに移行する際に、最も多く使われるテクニックです。Microsoft(R) DirectMusic(R) の多くの機能は、特にダウンローダブル サウンド (DLS) を使ったコンテンツで「完全な作曲」が行われた音楽的なトランジションを作成可能なように設計されていますが、DirectMusic はセグメント間でのクロスフェードを行う機能も備えています。ただし、この機能にはいくつかの制限と注意事項があります。ここでは、コンテンツ作成者の観点から、クロスフェードを実現するための最も単純な方法を 2 つ紹介します。

  • ボリューム コントロールの変化をコンテンツの中に組み込む DirectMusic は既存の MIDI コントロール変更機能を拡張していますので、従来の MIDI よりも簡単にクロスフェードを実装できます、またレンダリング済みのウェーブ コンテンツの間で簡単なクロスフェードも可能です。
  • **オーディオパスを使って、その上で再生されるすべてのコンテンツのボリュームをコントロールする
    **DirectX(R) オーディオ スクリプティングに含まれている機能により、複数のパフォーマンス チャンネルを使うウェーブや MIDI コンテンツに合わせて簡単に調整できるダイナミックなクロスフェードが作成できます。

この 2 つの場合について、コンテンツ作成者がオーサリングの際に注意しなくてはならないことと、開発者またはスクリプト作成者が実装しなくてはならない細かい機能について説明します。

この記事では以下のトピックを扱っています。

  • 開発者またはスクリプト作成者のための注意事項
  • コンテンツへのクロスフェードの組み込み
  • 強化された CC 機能とクロスフェード
  • クロスフェードしたセグメントの停止
  • より複雑なクロスフェードの処理
  • CC クロスフェードのスクリプティング
  • オーディオパスによるクロスフェード
  • ダッキング
  • 結論: 各種のクロスフェード テクニックのトレードオフ
  • 関連情報

開発者またはスクリプト作成者のための注意事項

解説を始める前に、クロスフェードの障害となる可能性のある、DirectMusic のいくつかの制限事項について説明しておきます。

  • プライマリ セグメントは一度に 1 つしか再生できません。クロスフェードは、その性質上、複数のコンテンツを同時に再生しなくてはなりません。ただし、プライマリ セグメントの上には任意の数のセカンダリ セグメントをレイヤ化して置くことができます。したがって、クロスフェードを実現するには、クロスフェードを使用したいすべてのコンテンツをセカンダリ セグメントとして再生するという方法が一番簡単です。プライマリ セグメントは別の理由から必要となることもあります。たとえば、クロスフェードの影響を受けない、一定したバックグラウンド環境音を提供したり、他のコンテンツとの同期に使うメジャーやビートの通知として使用するケースです。セカンダリ セグメントは、プライマリ セグメントの内容とは独立に再生できます。
  • 個々の DirectMusic パフォーマンスでは、一度に 1 つのテンポしか使用できません。もちろんテンポは随時変更できますが、2 つのセグメントを同時に異なるテンポで再生することはできません。このせいで、クロスフェードが難しくなることがあります。2 つのコンテンツが同一のテンポを持っていない限り、片方が通常よりも遅く、または速く再生されることになります。この問題の解決策としては、コンテンツ内でテンポをスムーズに変化させたり、テンポを変えるための中間トランジション セグメントを使うなどが考えられます。また、それぞれが独自のテンポを持つ複数の DirectMusic パフォーマンスを使うという方法もあります。

コンテンツへのクロスフェードの組み込み

異なる要素間でクロスフェードを実現する最も簡単な方法の1つとして、それを自動的に行ってくれるコンテンツを作成するというものがあります。この方法では、開発者やスクリプト作成者の側の作業が軽減され (コンテンツを指示通りに再生すれば済みます)、コンテンツ作成者はクロスフェード カーブのタイミングと品質を正確に制御できます。コンテンツに組み込まれたクロスフェードは、通常は MIDI CC (continuous controller) #7 (ボリューム) を使用します。CC #11 (expression) を使うこともできますが、少し後で述べるように、過去においてエクスプレッション コントローラを使わざるをえなかった主な問題の 1 つは、DirectMusic コンテンツ内の他の手段によって解決することが可能です。

最も基本的なシナリオでは、2 つのミュージック セグメントが存在します。一方のセグメントが再生を開始した後、任意のタイミングでもう一方のセグメントを最初は無音で開始し、両者の間でクロスフェードを実行します。話を単純にするために、ウェーブ トラックから作成した Seg1 と Seg2 という 2 つのセグメントが存在するとしましょう。

最初のステップとして、これらのトラックが独立したパフォーマンス チャンネル (PChannels) 上に存在することを確認します。ウェーブには MIDI ベースのコンテンツの制限はありません。つまり、PChannel では、複数の独立したサウンドを同時に再生できます。ただし、PChannel 上で再生される個々のウェーブは、MIDI コントローラ カーブに対応します。

Seg1 のウェーブ トラック パートを PChannel 1 に、Seg2 のウェーブ トラック パートを PChannel 2 に配置します。PChannel を割り当てるには、ウェーブ トラックを右クリックし、[Properties] をクリックし、[Wave Part] タブを選択し、このパートの独自のチャンネルを選択します。

**注   **パートとトラックの違いに注意してください。トラックは任意の数のパートから構成できます。個々のパートは 1 つの PChannel に割り当てられます。1つのチャンネルに複数のパートが置けますが、MIDI の制限が適用されます。たとえば、すべてのパートは同じ音色上で再生され、そのチャンネル上のすべてのコントローラ カーブの影響を受けます。

図 1. ウェーブ パートの [プロパティ] ウィンドウ

Dd188494.dmp_crossfade_fig2(ja-jp,MSDN.10).gif

図 2. セグメント内のウェーブ パート

タイトル バーの左の最初の "2" は、このパート上のすべてのウェーブが PChannel 2 上で再生されることを示しています。

これで 2 つのウェーブが独立した PChannel 上で再生されるようになったので、それぞれに相手側の PChannel をフェード アウトし、自分側の PChannel をフェードインする CC 情報の再生が可能です。このためには、次の操作を行います。

  1. 第 1 のセグメントにシーケンス トラックを追加します。キーボード ショートカット CTRL+INSERT を使うか、セグメントを右クリックして、ショートカット メニューの [Add Track(s)] をクリックします。

  2. デフォルトのシーケンス トラック パートは PChannel 1 にあります。新たなトラックを PChannel 2 に追加するので (両方のチャンネルでボリュームを変更するため)、シーケンス トラックを右クリックし、[Add Sequence Part(s)] をクリックします。もうひとつの方法として、CTRL+SHIFT+INSERT のショートカットを使うこともできます。

  3. 表示されたダイアログ ボックスで、PChannel 2 を選択し、[Create New Part] をクリックします。

    図 3. [Add New Part] ダイアログ ボックス

  4. [Close] をクリックします。

  5. PChannel 1 上のパートを展開します。パートをダブルクリックするか、トラックの右端の最大化ボタンをクリックします。

    図 4. PChannel 1 上のシーケンス トラック パートを最大化した様子

    シーケンス トラック パートを構成する 2 つのストリップが見えます。その下には、ノート ストリップ (ピアノ ロール) と CC ストリップがあります。

  6. PChannel 1 の CC ストリップを右クリックし、[Add New CC Track] をクリックします。ダイアログ ボックスで、[7 Volume-create] をクリックします。CC ストリップの右半分に "Vol" が表示されます。

  7. CC ストリップを最大化して、ボリューム コントローラ ストリップを表示します。

  8. PChannel 1 上のウェーブをフェードインします。0 から 127 (または希望の相対ボリューム) まで上昇し、クロスフェードの期間だけ続くボリューム カーブを描きます。このためには、トラックを 1 回クリックし、INSERT キーを押すか、ショートカット メニューから [Draw Curve] を選択します。その後、ドラッグによって、希望のカーブのアウトラインを描きます。

    図 5. PChannel 1 でフェードインするボリューム カーブ

    カーブの [プロパティ] ウィンドウを開いて、その値を変更すれば、別のスタイル カーブが使えます (対数、線形、指数など)。

  9. PChannel 2 に対して、ステップ 5~8 を繰り返します。ただし、ボリューム カーブはフェードインではなくフェードアウトさせます。ショートカットとして、カーブを PChannel 1 からコピーし、PChannel 2 のシーケンス パートの Volume controller ストリップに貼り付け、その [プロパティ] ウィンドウを開いて [Flip Horizontal] ボタンをクリックするという方法もあります。

  10. 第 2 のセグメントについて、ステップ 1~9 を繰り返します。ただしステップ 7 と 8 では、2 つのカーブを反転させて、PChannel 1 がフェードアウト、PChannel 2 がフェードインするようにします。

    図 6. 第 2 のセグメントが完成した様子。第 1 セグメントは、2 つのカーブが反転していることを除けば同じ内容です。

この手順を使うと、クロスフェードをきわめて簡単に実装できます。Seg1 を再生すると、Seg2 のウェーブが再生されている PChannel 上でフェードアウトし、自分の PChannel 上ではフェードインします。ただし、いくつかの問題が残ります。

  • 無音状態からセグメントの再生を始めるときには、フル ボリュームで開始するべきでしょう。同じように、セグメントがループするときには、繰り返してクロスフェードを行うべきではないでしょう。
  • コンテンツがすでにボリュームまたはエクスプレッション コントローラ カーブを使用していた場合には、グローバル フェーダと衝突することになります。
  • 最も重要なのは、この解決策ではクロスフェードアウトされたセグメントは停止されないということです。PChannel は無音状態になっていますが、セグメントの再生は続けられています。セグメントを停止するのは、アプリケーションまたはスクリプトの責任です。これを無視すると、同じサウンドの複数のコピーが、いくつかはフル ボリュームで、残りは無音で同時に再生されているという状態になります。もっと悪いことに、コンテンツがループしていた場合には、予期しないタイミングでクロスフェードが再び発生します。さらに、ハードウェア ボイス、メモリ、そして DVD やハード ディスクの帯域幅を無駄に消費することにもなりかねません。

まず最初の 2 つの問題を扱い、第3の問題についてはスクリプティングの項で説明します。

強化された CC 機能とクロスフェード

最初の 2 つの問題は、どのタイミングでも変化する可能性のあるインタラクティブなミュージックで MIDI コントローラを使うときの、一般的な場合の具体例として位置づけられます。

  • CC を適用するべきであることはわかっていても、それをどこから開始すればいいのかがわからないことがあります。たとえば、ミュージックがすでにフェードアウトしているときに、それをフェードアウトさせるコントローラ情報に遭遇した場合、フェードアウトさせるためだけのために急にフル ボリュームに上げるというようなことはするべきではありません。
  • レイヤ化されたコンテンツの複数の部分が同じ MIDI コントローラを同時に使用していると、衝突が生じます。たとえば、コンテンツにボリューム カーブが含まれており、ボリューム カーブを使ってフェードを行った場合、従来の MIDI の動作では、ボリュームは 2 つのカーブの間で細かく切り替わり、最後まで残った方が勝つことになります。

DirectMusic は、この両方の問題に対する解決方法を提供しています。コントローラ カーブの [Properties] ウィンドウを開くと、従来の MIDI の連続的なコントローラとの違いがすぐにわかります。

Dd188494.dmp_crossfade_fig7(ja-jp,MSDN.10).gif

図 7. 個々の連続的なコントローラ カーブの [Properties] ウィンドウ

ダイアログ ボックスの下部の 2 つのオプションに注目してください。[Start From Current] は第 1 の問題に対する解決方法を提供します。このチェック ボックスが選択されていると、カーブの再生が開始される時点で、その開始値は現在のコントローラの値に置き換えられます。コンテンツがフル ボリュームだった場合には、ボリュームが 0 になるまでフェードアウトします。コンテンツのボリュームがすでに0だった場合には、値 0 から値 0 へのカーブになり、何の効果も生じません。この機能は、コンテンツが何度もフェードインとフェードアウトを繰り返すという問題を解決します。

また、これには付随的なメリットがあります。一般に DirectMusic は MIDI コントローラ カーブを最適化し、数百個の冗長な MIDI コントローラ メッセージが送信されないようにしています。このため、0から0へのカーブになった場合、シンセサイザに同一の MIDI メッセージが大量に送られることはありません。

次に、[Additive Curve ID] という意味のわかりにくい名前を持つオプションについて説明します。この機能は、複数の同時コントローラ カーブの問題に対処します。同じ ID を持つすべてのカーブは、従来の MIDI と同じように適用されます。同時に発生した場合には衝突を起こし、実際に使用される値は細かく変動します。しかし、カーブに別の ID を与えておけば、他のカーブ ID を使用している他のカーブに重ね合わせて適用されるようになります。コントローラのタイプによっては、重ね合わせではなく、両方のカーブがコンテンツに逐次適用されることもあります。ボリューム コントローラ カーブのケースでは、これはマルチステージのミキシングのようなものと考えることができます。ミュージカル スコアが 1 つの加算的カーブ ID (たとえば 0) を持つボリューム カーブを持っており、クロスフェード カーブは別の加算的カーブ ID (たとえば 1)を持っているとします。クロスフェード カーブがフル ボリュームになっているときには、カーブが存在しないものとして扱われます。ミュージカル コンテンツの中のカーブは、そのままの形で適用されます。そしてクロスフェード カーブがゼロ ボリュームに落ちたときには、他のカーブ ID 値のカーブがどのようになっていても、ミュージックは無音で再生されます。

この機能は、上に示した第 2 の問題に対する解決策を提供します。コンテンツを作成するときに、純粋に音楽的な理由で使用する他のボリューム コントローラ カーブとは別の加算的カーブ ID をクロスフェード ボリューム コントローラ カーブに持たせれば、両者は再生するコンテンツのボリューム レベルに加算的に適用されることになります。

クロスフェードされたセグメントの停止

さて残った問題は、クロスフェードされて無音状態になったセグメントを、どのように停止するかということです。これはいくつかの方法で実現できますが、一般にはコンテンツそのものとは関係のないところで行います。おそらく一番簡単なのは、通知方式を使用する方法でしょう。コンテンツの中に、他のセグメントを停止するようアプリケーションに指示するインジケータを埋め込みます。誰がミュージックの動作を制御しているのか (スクリプト作成者か開発者か) によって、これはいくつかの方法で行うことができます。

スクリプティングの場合には、セグメントの中のスクリプト トラックに、カーブが終了した時点でスクリプト ルーチン呼び出しを置いておくのが一番簡単です。その後、スクリプト作成者はこのルーチンを使って、再生中の他のコンテンツをすべて停止します。たとえば、上記のシナリオでは、スクリプト作成者に以前の無音状態のセグメントを停止させる "CrossfadeDone" という名前のルーチンを作成させます。このルーチンについては、少し後で詳しく説明します。

Dd188494.dmp_crossfade_fig8(ja-jp,MSDN.10).gif

図 8. スクリプト トラックの中のスクリプト ルーチン呼び出し

スクリプト作成者は、現在は無音状態で再生されている以前のセグメント (この例では Seg2) を停止する、この名前のルーチンを作成することになります。

開発者が関与している場合には、イベントが発生したことを知らせるための、これと似た方法が使えます。歌詞トラックを使用する方法です。歌詞(テキスト)メッセージを使ってアプリケーションに情報を渡し、アプリケーションは DirectMusic ツールを使ってこの情報を取り出します。歌詞メッセージをインターセプトするサンプル ツールについては、記事「ATL による DirectMusic ツールの作成」を参照してください。

Dd188494.dmp_crossfade_fig9(ja-jp,MSDN.10).gif

図 9. 歌詞トラックの中の歌詞

アプリケーションは、事前に合意されたテキストを含んでいる歌詞メッセージを受け取ったら、それに応じてセグメントを停止します。

コンテンツの実装を追加しなくても、別の方法として、開発者は DirectMusic ツールを使ってクロスフェードの完了を判断できます。開発者が、パフォーマンスを通ってシンセサイザに向かうあらゆるタイプのDirectMusic メッセージを「受け取る」するための DirectMusic ツールが用意されています。ただし、再生中のコンテンツの中で、ボリューム 0 を送信しているボリューム コントローラ メッセージを探すツールを実装するのは、簡単な作業ではありません。

より複雑なクロスフェードの処理

ここまででは、開発者の関与もいくぶんはあるにせよ、コンテンツの中で基本的なクロスフェードを作成する方法を説明してきました。もちろん、これには制限があります。たとえば、クロスフェードはつねに一定の長さを持つことになります。この制限は、CC カーブのみを含んでいる独立したセカンダリ セグメントを使用することで回避できるでしょう。クロスフェードによって特定のセグメントに移行したい場合には、目的のセグメントとこの独立したクロスフェード セグメントの再生を同時に開始します。より短時間でクロスフェードを行いたいときには、より急なボリューム カーブを持つ別のセカンダリ セグメントを再生します。コンテンツ作成者は、ゲーム内でミュージックがたどりうるさまざまな経路に応じて、各種の PChannel とクロスフェードのスピードの組み合わせを含んだコントロール情報のみを持つセグメント ライブラリの構築が可能です。

しかし、起こりうるすべての組み合わせとクロスフェードの長さに応じたセグメントを作成するのは、時間がかかる作業となります。また、結局は作曲者の作成した内容によって制限されることになります。完全にダイナミックなクロスフェードは、ほとんど不可能です。たとえば、キャラクターが 2 点間を移動するときに、キャラクターの現在位置に基づくクロスフェードをコンテンツ内に組み込むのは困難です。そのキャラクターは、歩く向きを変えたり、予想したよりもゆっくりと歩くかもしれません。

きわめてダイナミックな情報や、大量のクロスフェード可能なコンテンツを扱うときには、その情報を開発者に伝えて、プログラム的な解決策を使う方が有効です。さまざまな期間と PChannel のボリューム カーブを、アクティブな DirectMusic パフォーマンスに反映させることは、開発者にとってはかなり簡単な仕事なのです。コンテンツ作成者は、クロスフェードがどれだけの速度で起こり、コンテンツの個々の部分がどのチャンネルを使用するかを伝えるだけで済みます。

CC クロスフェードのスクリプティング

これまでの説明をベースにし、チャンネルのボリュームを変更するセカンダリ セグメントをトリガすることで(また無音のコンテンツを停止するのを忘れないようにすることで)、適切なクロスフェードを作成できます。では、同じシナリオとコンテンツをもとに、簡単なコード例を作成してみましょう。

すでに述べたように、Seg1.sgp と Seg2.sgp の 2 つのセグメントがあります。Seg1 は PChannel 1 に、Seg2 は PChannel 2 にウェーブを持っています。どちらにもボリューム カーブが組み込まれており、[Start from Current] フラグが有効になっているので、一方が開始されると、もう一方はフェードアウトされます。アプリケーションまたは他のセグメントがルーチンを呼び出したときに、この両者の間でクロスフェードを行う基本的なスクリプトを作成することにします。

コードを読みやすくするために、現在再生されているセグメントを追跡する SegNum という名前のグローバル変数を使用します。これが 0 ならば、どちらのセグメントも再生されていません。グローバル変数を扱うための常道として、これを初期値に設定する初期化ルーチンを使用します。


Dim SegNum
 
SubInit
    SegNum = 0
End Sub

次に、新しいセグメントを開始するルーチンをセットアップします。ボリューム コントローラ カーブ情報はコンテンツの中に組み込まれているので、新しいセグメントを再生すると、前のセグメントは自動的にフェードアウトすることに注意してください。


SubSwitchAndCrossfade
    If SegNum = 1 Then
        Seg2.Play IsSecondary
        SegNum = 2
    Else
        Seg1.Play IsSecondary
        SegNum = 1
    End If
End Sub

最後に、クロスフェードの前に再生されていたセグメントを停止します。ここでは、前に説明したコンテンツ内のスクリプト トラックを使用します。セグメントのスクリプト トラックの中のコントローラ カーブの終わりに合わせて、スクリプト ルーチン呼び出しを追加します。呼び出されるルーチンは、次のようなものになるでしょう。


SubCrossfadeDone
    If SegNum = 1 then
        Seg2.Stop AtImmediate
    ElseIf SegNum = 2 then
        Seg1.Stop AtImmediate
    End If
End Sub

これはすでにクロスフェードアウトされたセグメントを停止するだけなので、リスナーには何の変化も感じられません。

オーディオパスによるクロスフェード

オーディオ パスは特定のオーディオを再生から出力へとどのようなルートを通るかを DirectMusic に指定するアクティブな構成です、クロスフェードを実現するための手段として、連続的なコントローラの代わりにこのオーディオパスが使えます。一般にオーディオパスでは、マルチチャンネル セグメントの間でのクロスフェードを比較的簡単に扱えます。たとえば、それぞれ 16 個以上のチャンネルを含んでいる、細かいオーケストレーションが行われた DLS スコアの間でクロスフェードするのに必要なボリュームカーブを作成するのには、かなりの時間がかかるでしょう。

一般に開発者にとっても、オーディオパスはよりフレンドリーなインターフェイスを提供します。アプリケーションは、MIDI ボリューム カーブをパフォーマンスに適用したり通知を受け取る代わりに、複数のオーディオパスのボリュームを同時にコントロールするだけで、各オーディオパス上で再生されている個々のセグメントのボリュームをコントロールできます。

これはオーディオパスに関する第 1 のキー ポイントに関連しています。少なくとも MIDI コントローラに関する限り、オーディオパスは互いに独立して動作できます。個々のオーディオパスは PChannel を独自の物理チャンネルのセットにマッピングしています。したがって、オーディオパスを使用する場合には、クロスフェードを行うコンテンツに一意のチャンネルを持たせるという配慮をする必要がありません。1 つのオーディオパスのチャンネル 1~25 のコンテンツをフェードインしながら、別のオーディオパスのチャンネル 1~16 のコンテンツをフェードアウトさせるというようなことが可能です。ただし、1 つのオーディオパスの中では、同じ制限が存在することに注意してください。また、DirectMusic パフォーマンスの制限も適用されます。具体的には、同時に 1 つのプライマリ セグメントしか使用できず、1 つのテンポを共有します。

オーディオパスは、標準のオーディオパス構成から、または DirectMusic Producer で作成されたオーディオパス構成ファイルから作成できます。1 つのオーディオパス構成ファイルから複数の独立したオーディオパスを作成することができ、これはサウンド エフェクトや、後に示すようにクロスフェードなどの機能を実現したいときに便利です。

前に使った、2 つのセグメントをクロスフェードさせるというシナリオを取り上げることにしましょう。今回は、これらのセグメントは DLS をベースにしており、それぞれが PChannel 1~16 を占有します。開発者またはスクリプト作成者に、1 つの標準構成あるいはコンテンツ作成者が作成したオーディオパス構成ファイルからオーディオパスを作成させます、そしてそのオーディオパスの最初のセグメントを再生します。その後で、別のセグメントにクロスフェードするときには、アプリケーションまたはスクリプトは第 2 のオーディオパスを作成し、これをゼロ ボリュームに設定し、第 2 のセグメントの再生を開始します。次に、第 1 のオーディオパスのボリュームをゼロまで下げながら、第2のオーディオパスをフル ボリュームまで上げていきます。前と同様に、第 1 のセグメントがフェードアウトしおわったら、それを停止し、ボイスとリソースを解放するためにオーディオパスを解放します。

オーディオパス クロスフェードのスクリプティング

オーディオパスを使うと、開発者は複数の PChannel のグループのボリュームを 1 つのコントロール ポイントで簡単に変更できます。しかし、スクリプティングを使用しているコンテンツ作成者にとって、オーディオパスはフェードを行うための簡単なインターフェイスともなっています。

DirectX オーディオ スクリプティングはオーディオ構成ファイルしか使えません。標準オーディオパスを使うには、開発者の関与が必要です。ただし、オーディオ構成ファイルは標準オーディオパス構成から簡単に作成できるので、この点は大きな問題にはなりません。

Dd188494.dmp_crossfade_fig10(ja-jp,MSDN.10).gif

図 10. [New Audiopath] ダイアログ ボックス

新規のオーディオパス構成ファイルを作成するとき、このダイアログ ボックスから新規のファイルのベースとなる任意の既存のオーディオパス構成ファイルまたは任意の標準オーディオパスが使えます。

すでにオーディオパス構成ファイルを作成しており (名前は "MusicConfig")、これをプロジェクト ツリーの中のスクリプトにドラッグしたとします。話を単純にするために、アプリケーションがスクリプトを初期化したときに、最初のミュージックを再生するものとします。この場合、初期化作業と変数は次のようになります。


Dim SegNum
Dim Audiopath1
Dim Audiopath2
 
SubInit
    Set Audiopath1 = MusicConfig.Create
    Audiopath1.SetVolume 0
    Seg1.Play IsSecondary, Audiopath1
    SegNum = 1
End Sub

2 つの新しい変数を使って、アクティブな 2 つのオーディオパスを追跡します。クロスフェードの際には、両方の変数がアクティブになります。それ以外のときには、片方の変数のみがアクティブになっています。アクティブに実行されるオーディオパスを作成するには、AudiopathConfig.Create メソッドを使用します。アクティブ オーディオパスのボリュームを設定するには、Audiopath.SetVolume メソッドを使用します。DirectMusic の他の側面とは異なり、オーディオパス上のボリュームはデシベル単位であることに注意してください。0 がフル ボリュームであり、-9600 が無音状態と見なされます。オーディオパスを作成し、フル ボリュームに設定します。次に、これを使ってセグメントを再生します。Segment.Play メソッドの第 2 パラメータは、どのオーディオパスを使用するかを指定します。このパラメータがなければ、セグメントはデフォルト オーディオパスを使って再生されます。最後に、再生中のセグメントを識別するために、SegNum を 1 に設定します。

クロスフェードのルーチンは前に示したものとよく似ていますが、クロスフェードのボリュームと期間を、コンテンツの中に組み込むのではなく、スクリプト内で制御できるようになっています。


SubSwitchAndCrossfade
    If SegNum = 1 Then
        set Audiopath2 = MusicConfig.create
        Audiopath2.SetVolume -9600
        Seg2.Play IsSecondary, Audiopath2
        SegNum = 2
        Audiopath2.SetVolume 0, 5000
        Audiopath1.SetVolume -9600, 5000
    ElseIf SegNum = 2 Then
        set Audiopath1 = MusicConfig.create
        Audiopath1.SetVolume -9600
        Seg1.Play IsSecondary, Audiopath1
        SegNum = 1
        Audiopath1.SetVolume 0, 5000
        Audiopath2.SetVolume -9600, 5000
    End If
End Sub

まず、ターゲット セグメントのための実行オーディオパスを作成します。このオーディオパスは、最初は無音状態に設定されています。この無音のオーディオパス上で、セグメントの再生を開始します。最後に、このオーディオパスのボリュームを上げると同時に、他方のオーディオパスのボリュームを下げていきます。Audiopath.SetVolume ルーチンの第2パラメータは、ミリ秒単位の時間幅です。ここでは 5 秒間のクロスフェードを作成しています。

最後に、セグメントを停止し、使われなくなったオーディオパスを破棄する必要があります。クロスフェードが 5 秒後に終了するということがわかっている場合には、各セグメントのスクリプト トラックの 6 秒目にスクリプト ルーチン呼び出しを追加します。このルーチンは次のようになります。


SubCrossfadeDone
    If SegNum = 1 Then
        Seg2.Stop AtImmediate
        set Audiopath2 = nothing
    ElseIf SegNum = 2 Then
        Seg1.Stop AtImmediate
        Set Audiopath1 = nothing
    End If
End Sub

オーディオ パスを nothing に設定すると、そのオーディオパスは破棄されます。これらのコンテンツ部分の間でクロスフェードが頻繁に行われる場合には、両方のオーディオパスをアクティブなまま残しておくといいでしょう。

ダッキング

これまで説明してきた内容は、1 つのオーディオのボリュームが下がると同時に、より重要なオーディオの再生が始まるというダッキングの概念にも簡単に適用できます。たとえば、キャラクターが話し始めたときに、音楽のボリュームを下げるというような処理が考えられます。ダッキングされた音楽は再生が続けられ、停止する必要がないという点で、ダッキングはトランジション的なクロスフェードよりも管理はいくぶん簡単です。

セグメント内に置かれたダイアログは、スクリプト トラックまたは MIDI コントローラ カーブを使って、パフォーマンスの他の側面のボリュームのダッキングができます。これはオーディオパスの使い方としても便利です。たとえば、第 1 のオーディオパスでは音楽を再生し、第 2 のオーディオパスではダイアログを、第 3 のオーディオパスではサウンド エフェクトを再生するとします。ダイアログを再生する準備ができたら、上記のいずれかの手法を使って、音楽と、必要ならばサウンド エフェクトのボリュームを下げます。ダイアログが終了したら、音楽のボリュームを元に戻します。

結論: 各種のクロスフェード テクニックのトレードオフ

本ドキュメントでは、DirectMusic でクロスフェードを実現するためのいくつかの方法を示しました。ひとつの方法として、開発者にすべてのクロスフェードを処理してくれるよう依頼できます。この場合には、特定のパフォーマンス チャンネル上の MIDI コントローラ メッセージを使用するか、複数のオーディオパスを使用します。前者では、すべてのコンテンツが 1 つのオーディオパス上で再生されるため、CPU 時間とリソースの消費量が少なくなるでしょう。後者では、必要な通信の量が少なく、コンテンツに関する知識がまったく不要なので、開発者にとっては実装が簡単になる一方、アプリケーションはクロスフェードそのものに加えて、オーディオパスの作成と破棄も管理しなくてはなりません。

もうひとつの方法として、コンテンツ作成者がクロスフェードの動作のかなりの部分をコントロールする場合でも、これと似たようなトレードオフが存在します。コンテンツ作成者は、コンテンツそのものに MIDI ボリューム カーブを組み込むことができます。このようなコンテンツはきわめて使いやすく、開発者またはスクリプト作成者は単にセグメントを再生するだけで、コンテンツのクロスフェードが自動的に行われます。また、柔軟性が欲しい場合、または他のコンテンツのフェードインとフェードアウトを行わずにセグメントを簡単に再生したい場合のために、クロスフェード情報を含んだ 1 つまたは複数の独立したセカンダリ セグメントを作成する方法についても説明しました。この場合、開発者またはスクリプト作成者は、ゲームのダイナミックな特性に基づいて、特定のクロスフェード (速度、カーブのスロープなど) を選んで再生できます。

オーディオパスを使うと、時間が節約できることがありますが、余分なリソースが消費される可能性があり、スクリプト作成者または開発者による支援も必要となります。

スクリプティングを使うと、開発者の側としてはクロスフェードを開始するスクリプトを実際に呼び出すだけで済むクロスフェードを作成できます。スクリプティングを使わない場合は、セグメントがクロスフェードアウトして無音状態になったときには、開発者がそのセグメントを停止する責任を負うことを忘れないようにしてください。

関連情報

この記事で説明した DirectX オーディオ スクリプティング、オーディオパス、および DirectMusic のその他の側面の詳細については、DirectMusic Producer のヘルプを参照してください。ルーチンのアプリケーションからの呼び出しと、アプリケーションがコントローラ カーブ メッセージを送信する方法については、DirectX Software Development Kit (SDK) のヘルプを参照してください。

このシリーズの以下の記事では、DirectMusic Producer の使い方に関する詳しい情報を提供しています。