1

私がやろうとしているのは、ループwavを再生することですが、音楽モジュールファイル(.it、s3m、.modなど)で使用されるサンプルのような特定のループ開始位置を使用します。SoundPlayerにはこの機能がないため、元のwavとループの開始位置までカットオフされたwavの2つの別々のファイルを作成しました。2つのファイルをシームレスに連続して再生したいのですが、最初に元のwavファイルをPlaySync()で再生し、次にループセクションをPlayLooping()で再生します。

残念ながら、最初のwavをPlaySync()した後、PlayLooping()がループwavの再生を開始すると、その間に一瞬の中断があります。

    private static void PlayThread(SoundPlayer soundPlayer, byte[] wav, byte[] loop)
    {
        MemoryStream stream1 = new MemoryStream(wav);
        MemoryStream stream2 = new MemoryStream(loop);
        soundPlayer.Stream = stream1;
        soundPlayer.PlaySync();
        // here is where the split second interruption occurs
        soundPlayer.Stream = stream2;
        soundPlayer.PlayLooping();
    }

これは、2つの別々のサウンドを再生する場合は目立たない場合がありますが、必要なループメカニズムを解除しようとすると非常に目立ちます。音波は楽器のサンプルであり、非常に小さい(通常は0x1000バイト以下)。

4

3 に答える 3

1

複数のSoundPlayerオブジェクトを連続して再生するのではなく、.wavファイルをその場で連結し、マージされた.wavファイルを1つのSoundPlayerオブジェクトにロードしてみてください。

このWaveIOクラスをダウンロードしてプロジェクトに追加し、複数のサウンドを連続してシームレスに再生する次のコードを試してください。

string[] files = new string[3] { @"filepath1.wav", @"filepath2.wav", @"filepath3.wav" };

WaveIO wa = new WaveIO();
wa.Merge(files, @"tempfile.wav");

System.Media.SoundPlayer sp = new System.Media.SoundPlayer(@"tempfile.wav");
sp.Play();
于 2013-02-02T14:24:32.130 に答える
0

SoundPlayer については何も知りませんが、おそらく 3 行と 4 行を削除し、新しいストリームを作成する代わりに、2 番目のウェーブを最初のストリームに書き込みます。そうすれば、本質的に、再生するためにストリームにデータを追加することになります。再生できるよりも速く書き込むことができると仮定すると、再生できるはずです。MemoryStream が同時読み取り/書き込みを許可するかどうかは、頭の中でわかりません。私は似たようなことをしましたが、手元にコードがなく、わずかに異なっていた可能性があります。

また、Play() はブロックされていますか? つまり、再生が完了するまで次の行は実行されません。その場合、一時停止は 3 行目で wav ファイルを読み込んでいるときです。したがって、最初のウェーブの再生中に次のウェーブのロードを開始できるように、.Play を別のスレッドに移動する必要があります。最初のメモリ ストリームに書き込むことができず、新しいメモリ ストリームを作成する必要がある場合でも、少なくとも wav ファイルがメモリ ストリームにロードされ、最初のメモリ ストリームが終了するとすぐに再生できるようになります。これにより、一時停止が大幅に短縮されます。

MP3 のプレイリストを持つメディア配信者を考えてみましょう。1 つの MP3 が終了間近になると、メディア プレーヤーは通常、最初の mp3 の再生が終了する前に、ディスクから次の mp3 をロードしてメモリにロードします。

于 2012-08-23T23:53:59.463 に答える
0

私のテストは次のようになります。

        string sMediaPath = @"C:\Windows\Media";
        SoundPlayer soundPlayer = new SoundPlayer();

        soundPlayer.Stream = File.OpenRead(Path.Combine(sMediaPath, "chimes.wav"));
        soundPlayer.PlaySync();

        soundPlayer.Stream = File.OpenRead(Path.Combine(sMediaPath, "chord.wav"));
        soundPlayer.PlaySync();

このテストは、ファイル間で突然停止することなく、ご要望どおりに機能することがわかりました。これは他の理由が原因である可能性がありますが、ファイル自体に関係している可能性が最も高いです

  • ビット レート: ファイルのサンプリング レートは?
  • 音声ファイルはインターリーブ (ステレオ) されていますか?
  • サウンドファイルのサイズは?

おそらく、サウンドを再生する前にプリロードすることで違いが生じるのではないでしょうか?

        string sMediaPath = @"C:\Windows\Media";
        SoundPlayer soundPlayer = new SoundPlayer();

        List<Stream> oSoundStreams = new List<Stream>();
        oSoundStreams.Add(File.OpenRead(Path.Combine(sMediaPath, "chimes.wav")));
        oSoundStreams.Add(File.OpenRead(Path.Combine(sMediaPath, "chord.wav")));

        soundPlayer.Stream = oSoundStreams[0];
        soundPlayer.PlaySync();

        soundPlayer.Stream = oSoundStreams[1];
        soundPlayer.PlaySync();

編集:

再生するサウンドごとに 1 つの SoundPlayer オブジェクトを作成することで、発生している短いギャップを解消できるようです。

        string sMediaPath = @"C:\Users\Foogle\Desktop\";
        SoundPlayer soundPlayer1 = new SoundPlayer();
        SoundPlayer soundPlayer2 = new SoundPlayer();

        soundPlayer1.Stream = File.OpenRead(Path.Combine(sMediaPath, "W.wav"));
        soundPlayer1.Load();

        soundPlayer2.Stream = File.OpenRead(Path.Combine(sMediaPath, "P.wav"));
        soundPlayer2.Load();

        for (int i = 0; i < 10; i++)
        {
            soundPlayer1.PlaySync();
            soundPlayer2.PlaySync();
        }

おそらく、SoundPlayer オブジェクトのコレクションを作成し、必要に応じてそれらを再生できますか?

お役に立てれば。

乾杯!

于 2012-08-24T00:26:14.023 に答える