Search code examples
c#naudio

Encode MemoryStream directly to MP3 using NAudio


I'm trying to use one of the methods below of the NAudio nuget package:

MediaFoundationEncoder.EncodeToMp3(new RawSourceWaveStream(_audioStream, _audioWriter.WaveFormat), "Test.mp3", 320000);

using (var reader = new WaveFileReader(_audioStream))
{
    MediaFoundationEncoder.EncodeToMp3(reader, "Test.mp3", 320000);
}

This should encode the wav stream directly to mp3. Well it does, but the result only consists of noise.

When I save the same MemoryStream(WaveFileWriter) with

File.WriteAllBytes("Test.wav", _audioStream.ToArray());
MediaFoundationEncoder.EncodeToMp3(new WaveFileReader("Test.wav"), "Test.mp3", 320000);

the created wav file is fine and I can use this wav file to encode it to mp3. But I want to avoid saving the wav file first.

Is there a way to encode the stream directly to mp3 without only getting noise? I have no clue why the one method works and the other isn't. Google didn't help me as well. So maybe you guys have any idea.

Thanks for your effort.

Further infos:
.NET Core 3.0 Windows Application
NAudio Nuget Package (Version: 1.9.0)

Complete class:

using NAudio.MediaFoundation;
using NAudio.Wave;
using System;
using System.IO;

namespace Recorder.NAudio
{
    public class Recorder
    {
        private WasapiLoopbackCapture _audioCapture;
        private WaveFileWriter _audioWriter;
        private MemoryStream _audioStream;

        public bool IsRecording { get; private set; }

        public Recorder()
        {
            MediaFoundationApi.Startup();
        }

        public void Init()
        {
            _audioCapture = new WasapiLoopbackCapture();

            _audioStream = new MemoryStream(1024);
            _audioWriter = new WaveFileWriter(_audioStream, new WaveFormat(44100, 24, 2));

            _audioCapture.DataAvailable += DataReceived;
            _audioCapture.RecordingStopped += RecordingStopped;
        }

        private void RecordingStopped(object sender, StoppedEventArgs e)
        {
            _audioCapture.DataAvailable -= DataReceived;
            _audioCapture.RecordingStopped -= RecordingStopped;

            _audioCapture.Dispose();
            _audioCapture = null;
            _audioWriter.Flush();
            _audioStream.Flush();

            _audioStream.Position = 0;

            //This works the mp3 file is fine, but I want to avoid the workaround of first saving a wav file to my hard drive
            File.WriteAllBytes("Test.wav", _audioStream.ToArray());
            MediaFoundationEncoder.EncodeToMp3(new WaveFileReader("Test.wav"), "Test.mp3", 320000);

            //Try 1: This doesn't work the mp3 file consists only of noise
            MediaFoundationEncoder.EncodeToMp3(new RawSourceWaveStream(_audioStream, _audioWriter.WaveFormat), "Test.mp3", 320000);

            //Try 2: This doesn't work the mp3 file consists only of noise
            using (var reader = new WaveFileReader(_audioStream))
            {
                MediaFoundationEncoder.EncodeToMp3(reader, "Test.mp3", 320000);
            }

            _audioWriter.Close();
            _audioWriter.Dispose();
            _audioWriter = null;
            _audioStream.Close();
            _audioStream.Dispose();
            _audioStream = null;

            GC.Collect();
        }

        private void DataReceived(object sender, WaveInEventArgs e)
        {
            _audioWriter.Write(e.Buffer, 0, e.BytesRecorded);
        }

        public void Start()
        {
            Init();

            _audioCapture.StartRecording();
            IsRecording = true;
        }

        public void Stop()
        {
            _audioCapture.StopRecording();
            IsRecording = false;
        }
    }
}

Solution

  • I found a solution. When I change constructor of the WaveFileWriter to this:

    _audioWriter = new WaveFileWriter(_audioStream, _audioCapture.WaveFormat);
    

    And then change the audio settings of my device in the windows sound settings dialog to:
    2 Channels, 24 Bit, 44100Hz instead of 2 Channels, 24 Bit, 96000Hz it works for some reason...