Search code examples
c#naudio

Normalize volume in a 32 bit PCM Wav with NAudio


Is there a way to normalize volume in a 32-bit wav file using NAudio?

If the volume is clipping, then I want a downward normalize and vice versa if the volume is too low.


Solution

  • There is no built-in feature, but if you use AudioFileReader you can examine the values of all samples to find the max absolute sample value. From this you can work out how much the original file can be amplified by without clipping.

    Then you can use the Volume property of AudioFileReader to amplify the audio, and then use WaveFileWriter.CreateWaveFile to write that out to a new (IEEE floating point) WAV file. WaveFileWriter.CreateWaveFile16 could be used if you wanted a 16 bit output after normalizing.

    Here's some very simple sample code

    var inPath = @"E:\Audio\wav\input.wav";
    var outPath = @"E:\Audio\wav\normalized.wav";
    float max = 0;
    
    using (var reader = new AudioFileReader(inPath))
    {
        // find the max peak
        float[] buffer = new float[reader.WaveFormat.SampleRate];
        int read;
        do
        {
            read = reader.Read(buffer, 0, buffer.Length);
            for (int n = 0; n < read; n++)
            {
                var abs = Math.Abs(buffer[n]);
                if (abs > max) max = abs;
            }
        } while (read > 0);
        Console.WriteLine($"Max sample value: {max}");
    
        if (max == 0 || max > 1.0f)
            throw new InvalidOperationException("File cannot be normalized");
    
        // rewind and amplify
        reader.Position = 0;
        reader.Volume = 1.0f / max;
    
        // write out to a new WAV file
        WaveFileWriter.CreateWaveFile(outPath, reader);
    }