指定在NAudio中使用WaveTone()创建的声音(音调)的持续时间

时间:2013-07-27 16:56:08

标签: c# naudio

我想以指定的音量和频率播放声音(音调),但希望播放的持续时间为2秒。

我的代码类似于此处提供的代码。

            double freq, volume;
            WaveTone tone = new WaveTone(freq, volume);
            stream = new BlockAlignReductionStream(tone);
            output = new DirectSoundOut();
            output.Init(stream);
            output.Play();

我尝试在上面的DirectSoundOut()中使用延迟,但它没有按预期工作。我必须为每次播放动态更改频率和音量。

我需要知道音调播放的确切时间。

1 个答案:

答案 0 :(得分:0)

WaveTone类(假设您正在使用我刚刚用Google搜索过的那个)可能会提供源源不断的数据。如果要将输出限制为特定持续时间,则需要将特定数量的数据加载到另一个缓冲区/流中,或修改WaveTone类以停止在持续时间内生成数据。

这样的事情:

class WaveTone : WaveStream
{
    readonly WaveFormat Format;
    public readonly double Frequency;
    public readonly double Amplitude;
    public readonly double Duration;

    readonly long streamLength;

    long pos;

    const double timeIncr = 1 / 44100.0;
    readonly double sinMult;

    public WaveTone(double freq, double amp)
        : this(freq, amp, 0)
    { }

    public WaveTone(double freq, double amp, double dur)
    {
        Format = new WaveFormat(44100, 16, 1);
        Frequency = freq;
        Amplitude = Math.Min(1, Math.Max(0, amp));
        Duration = dur;

        streamLength = Duration == 0 ? long.MaxValue : (long)(44100 * 2 * Duration);

        pos = 0;

        sinMult = Math.PI * 2 * Frequency;
    }

    public override WaveFormat WaveFormat
    {
        get { return Format; }
    }

    public override long Length
    {
        get { return streamLength; }
    }

    public override long Position
    {
        get { return pos; }
        set { pos = value; }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (pos >= streamLength)
            return 0;
        int nSamples = count / 2;
        if ((pos + nSamples * 2) > streamLength)
            nSamples = (int)(streamLength - pos) / 2;

        double time = pos / (44100 * 2.0);
        int rc = 0;
        for (int i = 0; i < nSamples; i++, time += timeIncr, ++rc, pos += 2)
        {
            double val = Amplitude * Math.Sin(sinMult * time);
            short sval = (short)(Math.Round(val * (short.MaxValue - 1)));
            buffer[offset + i * 2] = (byte)(sval & 0xFF);
            buffer[offset + i * 2 + 1] = (byte)((sval >> 8) & 0xFF);
        }

        return rc * 2;
    }
}
相关问题