3

我正在构建一个将麦克风中的音频记录到文件(.mp3)的应用程序。我希望我的应用程序仅在检测到足够高的幅度时才将数据写入文件。我在尝试保存所选数据时遇到问题。我得到的只是快速失真,甚至与录制的内容相差甚远。

这是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NAudio.Wave;

namespace NAudio_Testing
{
    public partial class Form1 : Form
    {
        int counter = 0;
        int passed = 0;
        private BufferedWaveProvider bufferedWaveProvider;
        WaveIn waveIn;
        WaveFileWriter writer;
        string output = "C:/Users/klein/AppData/Roaming/Microsoft/Windows/gravacao.mp3";
        public Form1()
        {
            InitializeComponent();
            waveIn = new WaveIn();
            writer = new WaveFileWriter(output, waveIn.WaveFormat);

            waveIn.DataAvailable += new EventHandler<WaveInEventArgs>(new_dataAvailable);

            bufferedWaveProvider = new BufferedWaveProvider(waveIn.WaveFormat);
            bufferedWaveProvider.DiscardOnBufferOverflow = true;
            waveIn.StartRecording();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            timer1.Interval = 1000;
            timer1.Start();
        }

        void new_dataAvailable(object sender, WaveInEventArgs e)
        {
            for (int i = 0; i < e.BytesRecorded; i+=2)
            {
                short sample = (short)((e.Buffer[i + 1] << 8) | e.Buffer[i + 0]);
                float sample32 = sample / 32768f;
                if (sample32 > 0.02) //0.02~0.03
                {
                    writer.WriteSample(sample);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            waveIn.StopRecording();
            waveIn.Dispose();
            waveIn = null;
            writer.Close();
            writer = null;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            textBox1.Text = counter++.ToString();
        }

    }
}

编辑:如果我删除选择性 if 并添加行,我能够成功录制音频,问题当然是我无法根据音频的幅度录制或不录制:

writer.WriteByte(e.Buffer[i + 0]);
writer.WriteByte(e.Buffer[i + 1]);

像这样:

void new_dataAvailable(object sender, WaveInEventArgs e)
    {
        for (int i = 0; i < e.BytesRecorded; i+=2)
        {
            short sample = (short)((e.Buffer[i + 1] << 8) | e.Buffer[i + 0]);
            float sample32 = sample / 32768f;

            writer.WriteByte(e.Buffer[i + 0]);
            writer.WriteByte(e.Buffer[i + 1]);

        }
    }

谢谢你。

4

2 回答 2

6

您的方法本质上是丢弃过零附近的所有样本,无论当时的整体音频是否响亮。它会扭曲信号并加速它,因为音频信号通常每秒都有很多过零。

相反,您需要在短时间内测量所有样本的最大体积(多长时间取决于您,但您可以一次测量 1 秒)。如果在此期间任何样本的声音大于指定的最小值,那么您记录整个块。

您的代码的第二个问题是您实际上并没有创建 MP3 文件。WaveFileWriter 创建一个 WAV 文件。将您的文件名更改为以 WAV 结尾,然后收听以听取录音的结果。然后,您需要在录制后转换为 MP3 作为第二步。(我有一篇关于如何在此处转换格式的文章)。

于 2013-01-18T07:08:08.767 回答
1

您应该比较样本的绝对值,因为样本是有符号的。

 if (Abs(sample32) > 0.02) //0.02~0.03
   {
      writer.WriteSample(sample);
   }
于 2016-12-19T19:23:21.050 回答