Как манипулировать байтами с помощью С# NAudio?

  • В настоящее время я могу: записывать данные с аудиовхода, генерировать wav-файл с этими данными на диске, воспроизводить wav-файл с диска.
  • Что я хочу сделать: взять необработанные байты, прочитанные через NAudio, преобразовать wav, определенные байты в mp3, воспроизвести mp3 (без записи чего-либо на диск).

Используемый код:

    public WaveIn waveSource = null;
    public WaveFileWriter waveFile = null;
    public List<byte> soundBytesList = new List<byte>();

    private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
    {
        if (waveFile != null)
            for (int i = 0; i < e.BytesRecorded; ++i)
                soundBytesList.Add(e.Buffer[i]);
            waveFile.Write(e.Buffer, 0, e.BytesRecorded);
            waveFile.Flush();
    }

    public void waveSource_RecordingStopped(object sender, StoppedEventArgs e)
    {
        if (waveSource != null)
        {
            waveSource.Dispose();
            waveSource = null;
        }
        if (waveFile != null)
        {
            waveFile.Dispose();
            waveFile = null;
        }
    }

    private void RecordButton_MouseDown(object sender, EventArgs e)
    {
        waveSource = new WaveIn();
        waveSource.WaveFormat = new WaveFormat(44100, 1);

        waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
        waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);

        waveFile = new WaveFileWriter("test.wav", waveSource.WaveFormat);

        waveSource.StartRecording();
    }

    private void RecordButton_MouseUp(object sender, EventArgs e)
    {
        waveSource.StopRecording();

        byte[] soundBytesArrayWAV = soundBytesList.ToArray();          
        byte[] outB = ConvertWavToMp3(soundBytesArrayWAV );
        File.WriteAllBytes("test.mp3", outB);
    }

        public byte[] ConvertWavToMp3(byte[] wavFile)
        {
            using (var retMs = new MemoryStream())
            using (var ms = new MemoryStream(wavFile))
            using (var rdr = new WaveFileReader(ms))
            using (var wtr = new LameMP3FileWriter(retMs, rdr.WaveFormat, 128))
            {
                rdr.CopyTo(wtr);
                wtr.Flush();
                return retMs.ToArray();
            }
        }

Проблема в том, что я получаю сообщение об ошибке в методе ConvertWavToMp3, в котором говорится, что предоставленный массив байтов (soundBytesArrayWAV) не имеет RIFF (заголовок, специфичный для wav). Я предполагаю, что я не правильно беру все байты в soundBytesList, потому что, если я загружаю все байты в память (с диска, написанного wav), преобразование работает нормально. Не могли бы вы дать мне руку?


person Marko    schedule 11.03.2019    source источник
comment
Вы только добавляете байты к soundBytesList в waveSource_DataAvailable. Мне непонятно, почему вы создаете WaveFileWriter с именем файла, если вы не хотите записывать файл - почему бы просто не использовать для этого MemoryStream, а затем в ConvertWavToMp3 просто установить положение этого MemoryStream на 0 перед его передачей в конструктор WaveFileReader? По сути, вы хотите, чтобы WaveFileReader видел все данные, которые записал WaveFileWriter...   -  person Jon Skeet    schedule 11.03.2019
comment
Ты прав, Джон! Я хочу обрабатывать данные, не записывая их в файл, как сейчас. Это был мой первоначальный код, поэтому он такой, какой он есть. Я хочу обновить его сейчас. Ваш подход звучит как то, что мне нужно. Не могли бы вы дать мне больше информации о том, как использовать этот MemoryStream в моем коде? Я новичок в этом, извините.   -  person Marko    schedule 11.03.2019
comment
Ну, вместо soundBytesList у вас будет поле MemoryStream. Вы должны создать поток в RecordButton_MouseDown и передать его в конструктор WaveFileWriter. Затем используйте его в RecordButton_MouseUp, после перемотки.   -  person Jon Skeet    schedule 11.03.2019
comment
О, это сработало! Не думал об использовании потока внутри конструктора записи. Спасибо, Джон! Вы можете опубликовать свое предложение в качестве ответа, и я подтвержу его, если хотите.   -  person Marko    schedule 11.03.2019
comment
Боюсь, мне потребовалось бы больше времени, чтобы написать подробно, чем у меня сейчас есть время, но вы всегда можете сделать это сами в качестве ответа.   -  person Jon Skeet    schedule 11.03.2019
comment
Конечно, спасибо! Я опубликую обновленный код.   -  person Marko    schedule 11.03.2019


Ответы (1)


Функциональный код, обновленный в соответствии с предложениями @Jon Skeet, выглядит следующим образом:

    public WaveIn waveSource = null;
    public WaveFileWriter waveFile = null;
    public MemoryStream memStream = null;

    private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
    {
        if (waveFile != null)
        {
            waveFile.Write(e.Buffer, 0, e.BytesRecorded);
            waveFile.Flush();
        }
    }

    public void waveSource_RecordingStopped(object sender, StoppedEventArgs e)
    {
        if (waveSource != null)
        {
            waveSource.Dispose();
            waveSource = null;
        }
        if (waveFile != null)
        {
            waveFile.Dispose();
            waveFile = null;
        }
    }

    private void RecordButton_MouseDown(object sender, EventArgs e)
    {
        waveSource = new WaveIn();
        waveSource.WaveFormat = new WaveFormat(44100, 1);

        waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
        waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);

        memStream = new MemoryStream();
        waveFile = new WaveFileWriter(memStream, waveSource.WaveFormat);

        waveSource.StartRecording();
    }

    private void RecordButton_MouseUp(object sender, EventArgs e)
    {
        waveSource.StopRecording();

        byte[] outB = memStream.ToArray();
        File.WriteAllBytes("test.mp3", outB);
    }
person Marko    schedule 11.03.2019
comment
Это просто создаст файл WAV с расширением .MP3, что, вероятно, не то, что вам нужно. - person Mark Heath; 15.03.2019
comment
Я забыл добавить метод преобразования в mp3 перед записью файла. Метод присутствует в описании. Тем не менее дело было не в этом. Дело в том, чтобы иметь возможность получить доступ к байтам из памяти. Дело, которое было решено. :) - person Marko; 28.03.2019