SoundPlayer.PlaySync 过早停止

发布于 2024-10-12 06:23:32 字数 1772 浏览 1 评论 0原文

我想在 gui 线程上同步播放 wav 文件,但我对 PlaySync 的调用提前返回(并且过早停止播放)。 wav 文件长度为 2-3 分钟。

这是我的代码的样子:

        //in gui code (event handler)
        //play first audio file
        JE_SP.playSound("example1.wav");

        //do a few other statements
        doSomethingUnrelated();

        //play another audio file
        JE_SP.playSound("example2.wav");

    //library method written by me, called in gui code, but located in another assembly
    public static int playSound(string wavFile, bool synchronous = true,
        bool debug = true, string logFile = "", int loadTimeout = FIVE_MINUTES_IN_MS)
    {
        SoundPlayer sp = new SoundPlayer();
        sp.LoadTimeout = loadTimeout;
        sp.SoundLocation = wavFile;
        sp.Load();

        switch (synchronous)
        {
            case true:
                sp.PlaySync();
                break;
            case false:
                sp.Play();
                break;
        }

        if (debug)
        {
            string writeMe = "JE_SP: \r\n\tSoundLocation = " + sp.SoundLocation
                + "\r\n\t" + "Synchronous = " + synchronous.ToString();
            JE_Log.logMessage(writeMe);
        }

        sp.Dispose();
        sp = null;

        return 0;
    }

我想到的一些事情是加载超时,在另一个线程上播放音频,然后通过强制 gui 线程等待声音文件的持续时间来手动“冻结”gui。我尝试延长加载超时,但这没有任何作用。

我不太确定在不使用非我/Microsoft 的人编写的代码的情况下获取 wav 文件的持续时间的最佳方法是什么。我想这可以计算出来,因为我知道文件大小,并且所有编码属性(比特率、采样率、样本大小等)在我打算播放的所有文件中都是一致的。有人可以详细说明如何使用此信息计算 wav 文件的持续时间吗?也就是说,如果没有人知道为什么 PlaySync 会提前返回。

编辑:

注意:不久前我在 VB 6 中遇到了类似的问题,但那是由超时引起的,我不怀疑这在这里​​是一个问题。较短(< 1 分钟)的文件似乎播放得很好,因此我可能决定手动编辑较长的文件,然后通过多次调用单独播放它们。

附加信息:我注意到同一个文件在同一时间一致停止。这些文件是使用 Audacity 创建的。 PlaySync 是否可能期望文件的某种编码与我 Audacity 生成的文件不同?

I want to play a wav file synchronously on the gui thread, but my call to PlaySync is returning early (and prematurely stopping playback). The wav file is 2-3 minutes.

Here's what my code looks like:

        //in gui code (event handler)
        //play first audio file
        JE_SP.playSound("example1.wav");

        //do a few other statements
        doSomethingUnrelated();

        //play another audio file
        JE_SP.playSound("example2.wav");

    //library method written by me, called in gui code, but located in another assembly
    public static int playSound(string wavFile, bool synchronous = true,
        bool debug = true, string logFile = "", int loadTimeout = FIVE_MINUTES_IN_MS)
    {
        SoundPlayer sp = new SoundPlayer();
        sp.LoadTimeout = loadTimeout;
        sp.SoundLocation = wavFile;
        sp.Load();

        switch (synchronous)
        {
            case true:
                sp.PlaySync();
                break;
            case false:
                sp.Play();
                break;
        }

        if (debug)
        {
            string writeMe = "JE_SP: \r\n\tSoundLocation = " + sp.SoundLocation
                + "\r\n\t" + "Synchronous = " + synchronous.ToString();
            JE_Log.logMessage(writeMe);
        }

        sp.Dispose();
        sp = null;

        return 0;
    }

Some things I've thought of are the load timeout, and playing the audio on another thread and then manually 'freeze' the gui by forcing the gui thread to wait for the duration of the sound file. I tried lengthening the load timeout, but that did nothing.

I'm not quite sure what the best way to get the duration of a wav file is without using code written by somebody who isn't me/Microsoft. I suppose this can be calculated since I know the file size, and all of the encoding properties (bitrate, sample rate, sample size, etc) are consistent across all files I intend to play. Can somebody elaborate on how to calculate the duration of a wav file using this info? That is, if nobody has an idea about why PlaySync is returning early.

Edits:

Of Note: I encountered a similar problem in VB 6 a while ago, but that was caused by a timeout, which I don't suspect to be a problem here. Shorter (< 1min) files seem to play fine, so I might decide to manually edit the longer files down, then play them separately with multiple calls.

Additional Info: I noticed that the same file stops consistently at the same time. The files were created using Audacity. Would it be possible that PlaySync is expecting a certain encoding of the files that differs from what I had Audacity produce?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

糖粟与秋泊 2024-10-19 06:23:32

为了防止其他人在同步播放大型 wav 文件时遇到问题,这里有一个我编写的方法,它使用 WMP 作为替代方案:

public static int playSoundWMP(string soundFile, bool synchronous = true)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();

        wmp.URL = soundFile;
        wmp.controls.play();

        Thread.Yield();

        while (wmp.playState == WMPLib.WMPPlayState.wmppsTransitioning)
        {
            Application.DoEvents();
            Thread.Yield();
        }

        int duration = Convert.ToInt32(wmp.currentMedia.duration * 1000);
        double waitTime = wmp.currentMedia.duration;

        if (synchronous)
        {
            Thread.Sleep(duration);
        }

        long elapsed = sw.ElapsedMilliseconds;
        sw.Stop();
        sw = null;

        return (int) wmp.currentMedia.duration * 1000;
    }

此方法使用 WMP 来播放音频文件而不是 SoundPlayer 类,因此它可以播放更大的 wav文件更可靠...

Just in case anybody else runs into problems with playing a large wav file synchronously, here is a method I wrote which uses WMP as an alternative:

public static int playSoundWMP(string soundFile, bool synchronous = true)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();

        wmp.URL = soundFile;
        wmp.controls.play();

        Thread.Yield();

        while (wmp.playState == WMPLib.WMPPlayState.wmppsTransitioning)
        {
            Application.DoEvents();
            Thread.Yield();
        }

        int duration = Convert.ToInt32(wmp.currentMedia.duration * 1000);
        double waitTime = wmp.currentMedia.duration;

        if (synchronous)
        {
            Thread.Sleep(duration);
        }

        long elapsed = sw.ElapsedMilliseconds;
        sw.Stop();
        sw = null;

        return (int) wmp.currentMedia.duration * 1000;
    }

This method uses WMP to play an audio file instead of the SoundPlayer class, so it can play larger wav files more reliably...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文