曲のセクションを正しくループするには?


8

私は私のゲーム用に小さなミュージックエンジンをC#とXNAでプログラミングしています。その1つの側面は、曲からセクションをループする可能性です。たとえば、私の曲にはイントロパートがあり、曲が最後(または他の特定のポイント)に達すると、イントロパートが終わったところにジャンプして戻ります。(A-B-B-B ...)

今私はIrrKlankを使用していますが、これは隙間なく完璧に機能していますが、問題があります。

どこに戻るかという点は少し不正確です。ここにいくつかのサンプルコードがあります:

public bool Passed(float time)
    {
        if ( PlayPosition >= time )
            return true;
        return false;
    }
//somewhere else
if( song.Passed( 10.0f ) )
   song.JumpTo( 5.0f );

ここで問題は、曲が10秒経過しても、10.1fまで数ミリ秒再生され、その後5秒にジャンプすることです。それはそれほど劇的ではありませんが、私のニーズには非常に不正確です。私はそれをそのように修正しようとしました:

public bool Passed( float time )
{
      if( PlayPosition + 3 * dt >= time && PlayPosition <= time )
             return true;
      return false;
}

(dtはデルタ時間、最後のフレームからの経過時間)

しかし、私はそうは思いません、それはそのための良い解決策です。

私の問題(そして私の英語、そう/ o /)を理解して私を助けてくれることを願っています:)


サウンドをストリーミングするか、一度にロードするかを選択できますか?
tesselode 2012

可能だと思います。現在、曲全体をロードしています。曲内をジャンプする方が速いと思ったからです。この問題を解決するためにマルチスレッド化を試みていますが、まだ不運です:/
Teflo

代わりにサウンドをストリーミングしてみてください。結局のところ、曲の小さなチャンクをほぼ瞬時にロードできるはずです。
tesselode 2012

曲はどのようにエンコードされていますか?
michael.bartnett 2012

おそらく、「passed」を使用する代わりに、コールバック関数を実行する(イベントのような)キューを追加できます。私はあなたがあなたの時間をどのように管理するか知りません。しかし、これまでに読み取ったバイト数を使用して、それを合計バイト数と比較し、正確な時間に変換することはできませんか?1秒間に読み取られるデータ量を計算できるはずです。これがどれほど速く進むかはわかりません。しかし、多分それからあなたはより正確に時間を読むことができます。
Sidar 2012

回答:


3

私の意見では、より単純でより一般的な解決策は、2つの異なるトラック(イントロとループセクション)を持つことです。次に、唯一の問題は、イントロがいつ終了するかを検出することです(30fpsを使用する場合は完全に正確ではありませんが、非常に簡単です)。次に、ループを有効にして2番目のトラックを再生できます。

したがって、ループセクションを巻き戻す必要があるたびにではなく、最初にループを開始するときに、再生のエラーをわずかな遅延に減らします。


0

理想的な解決策は、曲のどの部分を次にバッファにロードする必要があるかを事前に知ることです。各「セクション」A-B-Cには開始時刻と終了時刻があり、ファイルの正しい部分を正しい順序でロードするのは低レベルのストリーミングシステムです。ただし、これを機能させるには固定ビットレートが必要であり、次にスキップする必要があるファイル内の場所を見つけるのは非常に困難な場合があります。

私はirrKlangサイトをざっと見ましたが、独自のファイル形式リーダー/デコーダーを記述してエンジンを拡張できる可能性を誇っています。そのため、試してみてください。

ファイルアクセスを上書きするチュートリアルもここにあります。私のオリジナルのアイデアを試してみたり、Elidebが言ったように複数のサウンドと混ぜたりすることができます。CMyReadFileクラスを拡張して、複数のファイル(PartA.wav、PartB.wav、PartC.wavなど)にアクセスできるようにし、読み取りメソッドをオーバーライドするだけでなく、次のようにできます。

return (s32)fread(buffer, 1, sizeToRead, File);

あなたは次のようなことをすることができます:

switch(CurrentSectionToPlay)
{
case A:
    return (s32)fread(buffer, 1, sizeToRead, FileA);
case B:
    return (s32)fread(buffer, 1, sizeToRead, FileB);
}

つまり、再生と停止を同期させる必要なく、曲がシームレスにセクションを変更します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.