Search code examples
c#c#-4.0wavnaudiolame

How to manipulate bytes with C# NAudio?


  • 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?


Solution

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