NAudio записывает образец за образцом в файл
Я создаю приложение, которое записывает звук с микрофона в файл (.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();
}
}
}
РЕДАКТИРОВАТЬ: я могу записать аудио успешно, если я удаляю селективные, если и просто добавить строки, проблема, конечно, в том, что тогда я не могу записать или нет в соответствии с амплитудой звука:
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]);
}
}
Спасибо.
2 ответа
Ваш подход по существу отбрасывает все сэмплы около пересечения нуля, независимо от того, громкий ли звук в это время или нет. Это искажает сигнал и ускоряет его, поскольку звуковые сигналы обычно имеют большое количество пересечений нуля каждую секунду.
Вместо этого вам нужно измерить максимальный объем всех сэмплов за короткий промежуток времени (как долго это зависит от вас, но вы могли бы делать 1 секунду за один раз). Если в течение этого времени какой-либо сэмпл громче указанного минимального значения, вы записываете весь блок.
Вторая проблема с вашим кодом заключается в том, что вы на самом деле не создаете файл MP3. WaveFileWriter создает WAV-файл. Измените свое имя файла, чтобы оно заканчивалось на WAV, и послушайте его, чтобы услышать результаты вашей записи. Затем вам нужно будет преобразовать в MP3 в качестве второго шага после записи. (У меня есть статья о том, как конвертировать между форматами здесь).
Вы должны сравнить абсолютное значение образца, так как образцы подписаны.
if (Abs(sample32) > 0.02) //0.02~0.03
{
writer.WriteSample(sample);
}