7

我正在使用NAudio播放给定频率的正弦波,如博文 Playback of Sine Wave in NAudio 中所述。我只想让声音播放() x 毫秒,然后停止。

我尝试了thread.sleep,但声音立即停止。我尝试了一个计时器,但是当 WaveOut 被处理时,出现了一个跨线程异常。

我尝试了这段代码,但是当我调用 beep 时,程序冻结了。

public class Beep
{
    public Beep(int freq, int ms)
    {
        SineWaveProvider32 sineWaveProvider = new SineWaveProvider32();
        sineWaveProvider.Amplitude = 0.25f;
        sineWaveProvider.Frequency = freq;

        NAudio.Wave.WaveOut waveOut = new NAudio.Wave.WaveOut(WaveCallbackInfo.FunctionCallback());
        waveOut.Init(sineWaveProvider);
        waveOut.Play();
        Thread.Sleep(ms);
        waveOut.Stop();
        waveOut.Dispose();
    }
}

public class SineWaveProvider32 : NAudio.Wave.WaveProvider32
{
    int sample;

    public SineWaveProvider32()
    {
        Frequency = 1000;
        Amplitude = 0.25f; // Let's not hurt our ears
    }

    public float Frequency { get; set; }
    public float Amplitude { get; set; }

    public override int Read(float[] buffer, int offset, int sampleCount)
    {
        int sampleRate = WaveFormat.SampleRate;
        for (int n = 0; n < sampleCount; n++)
        {
            buffer[n + offset] = (float)(Amplitude * Math.Sin((2 * Math.PI * sample * Frequency) / sampleRate));
            sample++;
            if (sample >= sampleRate)
                sample = 0;
        }
   }
4

2 回答 2

4

SineWaveProvider32 类不需要无限期地提供音频。如果您希望哔声的最大持续时间为一秒(例如),那么对于单声道 44.1 kHz,您需要提供 44,100 个样本。当没有更多数据要提供时,Read 方法应该返回 0。

为了使您的 GUI 线程不阻塞,您需要摆脱 Thread.Sleep、waveOut.Stop 和 Dispose,而只需开始播放音频(您可能会发现窗口回调比函数更可靠)。

然后,当音频播放完毕后,您可以关闭并清理 WaveOut 对象。

于 2011-04-14T06:19:28.687 回答
0

查看博客文章将变量传递到 C# 中的新线程,了解如何将变量传递到另一个线程。

我认为您想要做的是创建一个播放声音的线程,创建一个计时器并启动线程。当计时器到期时,杀死线程,当线程关闭时,让它做所有的清理工作。

于 2011-03-30T11:42:39.140 回答