0
  • I am currently able to: record data from audio input, generate wav file with that data on the disk, play the wav from the disk.
  • What I want to accomplish: take the raw bytes read through NAudio, convert the wav, specific bytes to mp3, play the mp3 (without writing anything on disk).

Code used:

    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();
            }
        }

The problem is that I get an error on the ConvertWavToMp3 method which says that the provided byte array (soundBytesArrayWAV) has no RIFF (wav specific header). My guess would be that I do not take correctly all the bytes in soundBytesList, because if I load all the bytes into memory (from the disk written wav), the conversion works fine. Can you please give me a hand?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Marko
  • 407
  • 1
  • 7
  • 19
  • 2
    You're only adding bytes to `soundBytesList` in `waveSource_DataAvailable`. It's not clear to me why you're creating a `WaveFileWriter` with a filename if you don't want to write a file - why not just use a `MemoryStream` for that, then in `ConvertWavToMp3` just set the position of that `MemoryStream` to 0 before passing it into the `WaveFileReader` constructor? Basically you want `WaveFileReader` to see all the data that `WaveFileWriter` wrote... – Jon Skeet Mar 11 '19 at 09:13
  • You are right, Jon! I want to handle the data without writing it in a file, like I do now. This was my initial code, that's why it is like it is. I want to update it now. Your approach sounds like the thing that I need. Can you please give me some more information about how should that MemoryStream be used in my code? I'm new to this, sorry. – Marko Mar 11 '19 at 09:16
  • 1
    Well instead of having `soundBytesList`, you'd have a `MemoryStream` field. You'd create the stream in `RecordButton_MouseDown` and pass that into the `WaveFileWriter` constructor. Then use it in `RecordButton_MouseUp`, after "rewinding". – Jon Skeet Mar 11 '19 at 09:28
  • Oh, It worked! Didn't think about using the stream inside the writer constructor. Thank you, Jon! You can post your suggestion as an answer and I'll validate it, if you want. – Marko Mar 11 '19 at 09:46
  • I'm afraid it would take me longer to write up in detail than I have time available now - but you could always do so yourself as an answer. – Jon Skeet Mar 11 '19 at 09:54
  • Sure, thanks! I'll post the updated code. – Marko Mar 11 '19 at 09:55

1 Answers1

1

The functional code updated according to @Jon Skeet suggestions is the following:

    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);
    }
Marko
  • 407
  • 1
  • 7
  • 19
  • This will just make a WAV file with a .MP3 extension which is probably not what you want – Mark Heath Mar 15 '19 at 16:51
  • I forgot to add the convert to mp3 method before the file writing. The method is present in the description. Nevertheless, this was not the point. The point is to be able to reach the bytes from the memory. Thing which was solved. :) – Marko Mar 28 '19 at 11:47