Search code examples
c#.netnaudio

NAudio - individual samples access & modification


I would like to use NAudio for reading, modification and writing waves. Is there any direct access for getting and setting individual samples of wave files in this library. For example, I would like to open a wav file, then I would like to get values of fifth samples on all channels as a floats. I would also like to know weather there is a way how to change these 5th samples and after that how can I save this modified outcome. Can you please help and show me, how this can be performed. I hadn't find any documentation so far, is there any? Thank you.


Solution

  • Yes, NAudio is designed to give you access to the individual audio samples. However, there are lots of different audio formats (bit depths, compression types etc), so there is no one universal way to do this. The WaveFileReader class will give you access to the raw byte data. You can then convert each pair of bytes into 16 bit samples yourself, or take advantage of some of the NAudio helper classes to allow you to more easily work directly with 16 bit audio (assuming your audio is 16 bit). Then you use the WaveFileWriter class to write your modified audio back out to disk.

    Alternatively if you want to deal with audio as floats, you can use the new AudioFileReader class implements ISampleProvider, which makes it very easy to examine the value of each sample as a float as it comes through the Read method. You would create your own ISampleProvider whose Read method reads from the source AudioFileReader and examines and modifies the audio:

    var reader = new AudioFileReader();
    var mySampleProvider = new MySampleProvider(reader);
    WaveFileWriter.CreateWaveFile(mySampleProvider, "example.wav");
    
    ...
    class MySampleProvider: ISampleProvider
    {
        private readonly ISampleProvider source;
    
        public MySampleProvider(ISampleProvider source)
        {
            this.source = source;
        }
    
        public int Read(float[] buffer, int offset, int count)
        {
            int samplesRead = source.Read(buffer, offset, count);
            // TODO: examine and optionally change the contents of buffer
            return samplesRead;
        }
    
        public WaveFormat WaveFormat
        {
            get { return source.WaveFormat; }
        }
    }