SoundPlayer和播放无缝连续的声音

时间:2012-08-23 23:25:45

标签: c# soundplayer

我尝试做的是播放循环wav,但具有特定的循环开始位置,如音乐模块文件中使用的样本(.it,s3m .mod等)。 SoundPlayer没有这个功能,所以我创建了两个单独的文件:原始wav和wav,开头切断到循环开始的位置。我想连续播放这两个文件,无缝,首先是带有PlaySync()的原始wav文件,然后是带有PlayLooping()的循环部分。

不幸的是,在PlaySync()第一个wav之后,它之间的拆分第二个中断,当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();
    }

当播放两个独立的不同声音时,这可能不明显,但在尝试拉出我想要的循环机制时非常明显。声音wavs是仪器样本,非常小(通常不超过0x1000字节)。

3 个答案:

答案 0 :(得分:0)

我对SoundPlayer一无所知,但可能会删除第3 + 4行,而是将第二波写入第一个流而不是创建新流。这样,您实际上可以向流中添加更多数据以供其播放。假设你可以比它更快地写它,你应该能够。如果MemoryStream允许同时读/写,我不确定我的头脑。我已经做了类似的事情,但手头没有代码,可能会略有不同。

另外,是Play()阻止吗?即在完成播放之前,下一行是否会运行。如果是这样,则暂停是第3行正在读取wav文件。所以你需要将.Play移动到另一个线程,这样你就可以在第一个wave播放时开始加载下一个wave。即使您发现无法写入第一个内存流,并且必须创建新的内存流,至少您将把wav文件加载到内存流中,并在第一次完成后立即开始播放。这将显着减少暂停。

考虑具有MP3播放列表的媒体播放器。当一个MP3即将完成时,媒体播放器通常会继续从磁盘加载下一个mp3并在第一个完成播放之前将其加载到内存中。

答案 1 :(得分: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();

修改

通过为每个要播放的声音创建一个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对象集合并根据需要播放它们?

希望这有帮助。

干杯!

答案 2 :(得分:0)

不要尝试连续播放多个SoundPlayer对象,而是尝试连接.wav文件,并将合并后的.wav文件加载到一个SoundPlayer对象中。

下载此WaveIO class,将其添加到您的项目中,然后尝试使用以下代码连续无缝播放多个声音:

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();