Запись звука с помощью NAudio отключает меня

Я записываю звук, чтобы отправить его, чтобы отправить его в Google речь в текст, но когда я делаю звук с помощью naudio, он записывает меня только 5 секунд, а оттуда запись прекращается. Копирую код на C#, первый раз пользуюсь этим API, но не знаю, почему он меня врубает, если он должен останавливать запись при нажатии на кнопку сохранения, приложение представляет собой простую форму с 2-мя кнопками, один для записи, а другой для остановки.

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private BufferedWaveProvider bwp;
        WaveIn waveIn;
        WaveOut waveOut;
        WaveFileWriter writer;
        WaveFileReader reader;
        string output = "audio.raw";
        public Form1()
        {
            InitializeComponent();
            waveOut = new WaveOut();
            waveIn = new WaveIn();

            waveIn.DataAvailable += new EventHandler<WaveInEventArgs>(waveIn_DataAvailable);
            waveIn.WaveFormat = new NAudio.Wave.WaveFormat(16000, 1);
            bwp = new BufferedWaveProvider(waveIn.WaveFormat);
            bwp.DiscardOnBufferOverflow = true;

            btnRecordVoice.Enabled = true;
            btnSave.Enabled = false;
            //btnSpeechInfo.Enabled = false;
        }

        private void btnRecordVoice_Click(object sender, EventArgs e)
        {
            if (NAudio.Wave.WaveIn.DeviceCount < 1)
            {
                Console.WriteLine("No se encuentra un microfono!");
                return;
            }

            waveIn.StartRecording();

            btnRecordVoice.Enabled = false;
            btnSave.Enabled = true;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            waveIn.StopRecording();

            if (File.Exists("audio.raw"))
                File.Delete("audio.raw");

            writer = new WaveFileWriter(output, waveIn.WaveFormat);

            btnRecordVoice.Enabled = false;
            btnSave.Enabled = false;

            byte[] buffer = new byte[bwp.BufferLength];
            int offset = 0;
            int count = bwp.BufferLength;

            var read = bwp.Read(buffer, offset, count);
            if (count > 0)
            {
                writer.Write(buffer, offset, read);
            }

            waveIn.Dispose();
            waveIn = null;
            writer.Close();
            writer = null;

            reader = new WaveFileReader("audio.raw"); // (new MemoryStream(bytes));
            waveOut.Init(reader);
            waveOut.PlaybackStopped += new EventHandler<StoppedEventArgs>(waveOut_PlaybackStopped);
            waveOut.Play();
        }

        void waveIn_DataAvailable(object sender, WaveInEventArgs e)
        {
            bwp.AddSamples(e.Buffer, 0, e.BytesRecorded);

        }

        private void waveOut_PlaybackStopped(object sender, StoppedEventArgs e)
        {
            waveOut.Stop();
            reader.Close();
            reader = null;
        }
    }
}

person Mauricio    schedule 29.03.2020    source источник
comment
Stack Overflow доступен только на английском языке. Я отредактировал ваш вопрос с помощью Google Translate, пожалуйста, проверьте его, чтобы убедиться, что все в порядке   -  person stuartd    schedule 30.03.2020
comment
Код в btnSave_Click() для копирования из BufferedWaveProvider в WaveFileWriter... нечетный. Вы сохраняете результат bwp.Read() в read, но затем проверяете count, который был параметром (верхняя граница) bwp.Read(). Кроме того, как правило, эти методы Read(byte[], int, int) не гарантируют чтение всех запрошенных данных, поэтому вам нужен цикл, а не if. Попробуйте что-нибудь вроде int read; while ((read = bwp.Read(buffer, 0, buffer.Length)) > 0) { writer.Write(buffer, 0, read); }.   -  person Lance U. Matthews    schedule 30.03.2020


Ответы (1)


Вы получаете 5-секундный аудиоклип не только потому, что делаете однократное BufferLength чтение из BufferedWaveProvider...

int count = bwp.BufferLength;

var read = bwp.Read(buffer, offset, count);

... и 5 секунд — это значение по умолчанию этого свойства, но потому что BufferedWaveProvider использует кольцевой буфер, так что BufferLength — это все доступные ему данные.

Что сработало для меня, так это пропустить BufferedWaveProvider и записать новые данные в WaveFileWriter, как только они станут доступны...

void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
    writer.Write(e.Buffer, 0, e.BytesRecorded);
}

Чтобы поддержать это изменение, обработчики событий кнопок изменяются на следующие...

private void btnRecordVoice_Click(object sender, EventArgs e)
{
    if (NAudio.Wave.WaveIn.DeviceCount < 1)
    {
        Console.WriteLine("No se encuentra un microfono!");
        return;
    }

    writer = new WaveFileWriter(output, waveIn.WaveFormat);
    waveIn.StartRecording();

    btnRecordVoice.Enabled = false;
    btnSave.Enabled = true;
}

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

    btnRecordVoice.Enabled = false;
    btnSave.Enabled = false;

    reader = new WaveFileReader("audio.raw"); // (new MemoryStream(bytes));
    waveOut.Init(reader);
    waveOut.PlaybackStopped += new EventHandler<StoppedEventArgs>(waveOut_PlaybackStopped);
    waveOut.Play();
}

Похоже, что это тот же подход, что и в Запись файла WAV в WinForms приложение с WaveIn.

person Lance U. Matthews    schedule 30.03.2020