Insert silence to beginning of audio file and save as new file

Apr 1, 2013 at 5:25 AM
Hi,

I'm trying to insert silence into the beginning of an audio file, then save that file as a new audio file. I'm using the Mp3FileReader to read the input file, but can't figure out how to insert silence at the beginning of the file and save it. I've seen some references to using WaveOffsetStream or OffsetSampleProvider, but can't figure out how to use them. Any pointers/sample code would be greatly appreciated.

Thanks,
Alan
Coordinator
Apr 1, 2013 at 11:21 AM
you have to convert to PCM first, and then re-encode as MP3 if you need MP3. So write zeroes into a WaveFileWriter until you have the desired amount of silence (use AverageBytesPerSecond from the Mp3FileReader's WaveFormat to know how many to write), and then read everything out of your Mp3FileReader into the WaveFileWriter after that. Once you've done that, you'll have a WAV file that you can re-encode as MP3.
Apr 1, 2013 at 2:12 PM
Another option if you are just adding silence to the beginning of a MP3 file (and nothing more): Add empty frames to the "beginning" of the MP3 file. There are some caveats to it, though:

1) Adding a frame to a MPEG1 Layer III file will add 1152 samples (regardless how many channels; don't divide by channel count).
2) The new frames have to come after the ID3v2 tag and the RIFF header (if it exists; if it does, you'll also have to update the chunk sizes).
3) If there is a VBR tag (either form): Put your frames after the VBR tag. You can use minimum-bitrate frames here. Make sure to update the VBR tag.
4) Otherwise, put your frames at the beginning of the audio data. Your "empty" frame header should be almost identical to the first "real" audio frame's header.

Any frames you add should consist of a 32-bit frame header and no less than 20 bytes of 0's. Pad to the frame size (there are plenty of references for MP3 frame header parsing & frame length calculation...).
Apr 2, 2013 at 7:46 PM
Thanks for the quick replies. Mark, love NAudio, great library!

For reference, here's basically what I ended up doing, thanks for the pointers. If you see any problems, please comment.

-Alan
            int silence = 5000;  // silence to add in ms
            string mp3Url = "http://freedownloads.last.fm/download/494669779/Calgary.mp3";
            string outfile = "newfile.wav";
            WaveStream waveStream = new Mp3FileReader(mp3Url);
            using (WaveFileWriter waveFileWriter = new WaveFileWriter(outfile, waveStream.WaveFormat))
            {

                int avgBytesPerMillisecond = waveStream.WaveFormat.AverageBytesPerSecond / 1000;
                var silenceArraySize = avgBytesPerMillisecond * silence;
                byte[] silenceArray = new byte[silenceArraySize];
                waveFileWriter.Write(silenceArray, 0, silenceArray.Length);
                byte[] songArray = new byte[waveStream.Length];
                int numSamples = waveStream.Read(songArray, 0, songArray.Length);
                waveFileWriter.Write(songArray, 0, numSamples);
            }
Coordinator
Apr 4, 2013 at 7:32 AM
that's right, although be very careful that your silenceArray is always a multiple of the BlockAlign of the target WaveFormat.