首页 > 解决方案 > 每转一圈用 NAudio 播放波形

问题描述

我正在尝试使用 NAudio 播放字节缓冲区。我为该任务创建了一个 winforms 应用程序。

在此处输入图像描述

但是当我随后播放声音(使用 Math.sin 创建)时,每次播放的音量都会越来越低。为什么?

using System;
using System.Windows.Forms;
using NAudio.Wave;

namespace beeper
{
    public partial class Form1 : Form
    {
        byte[] bytes;
        const int sampling_freq = 44100;

        public Form1()
        {
            InitializeComponent();

            double freq = 1000;
            var seconds = 0.5;
            
            var length = (int)(seconds * sampling_freq);
            bytes = new byte[length];

            for (var i = 0; i < length; i++)
            {
                var offset = 80 * Math.Sin(i * freq / sampling_freq * Math.PI * 2);

                bytes[i] = (byte)(128 + offset);
            }
        }

        private void btnBeep_Click(object sender, EventArgs e)
        {
            var format = new WaveFormat(sampling_freq, 8, 1);
            var provider = new BufferedWaveProvider(format);
            provider.AddSamples(bytes, 0, bytes.Length);

            var wo = new WaveOut();
            wo.Init(provider);
            wo.Play();
        }
    }
}

大胆录音

在此处输入图像描述

难怪在查看这个以某种奇怪方式偏移和失真的波形时听起来会像这样。我寻找一种模式,但我真的找不到。

https://github.com/naudio/NAudio/issues/729

标签: c#naudio

解决方案


每次单击播放按钮时,您都会添加一个全新的播放频道。如果您不关闭这些通道,那么它们将继续播放静音,因此您最终会得到多个静音通道与一个活动声音混合,从而为您提供您所看到的结果。您按下按钮的次数越多,输出就越安静。

您需要在提示音完成后关闭频道(使用计时器或类似工具)或创建一个频道并重复使用它:

    private BufferedWaveProvider provider;
    private WaveOut waveOut;
    
    private void btnBeep_Click(object sender, EventArgs e)
    {
        if (waveOut == null)
        {
            var format = new WaveFormat(sampling_freq, 8, 1);
            provider = new BufferedWaveProvider(format);
            waveOut = new WaveOut();
            waveOut.Init(provider);
            waveOut.Play();
        }
        
        provider.ClearBuffer();
        provider.AddSamples(bytes, 0, bytes.Length);
    }

调用ClearBuffer会删除任何剩余的缓冲样本,因此重复点击按钮不仅会使整个输出堆栈排队。如果你想播放多个重叠的音调,你需要做多个通道或自己处理混音。

如果您确实想要重叠,我建议您检查一下MixingWaveProvider32。就目前而言,它有点受限制,但您应该能够按原样使用它(使用适当的转换示例提供程序)。


推荐阅读