Click here to Skip to main content
15,881,600 members
Articles / Programming Languages / C#
Article

Concatenating Wave Files Using C# 2005

Rate me:
Please Sign up or sign in to vote.
4.90/5 (41 votes)
10 Mar 2007CPOL2 min read 194.3K   5.2K   87   28
How to concatenate wave files in a single file

Introduction

The WAVE file format is a subset of Microsoft's RIFF specification for the storage of multimedia files. A RIFF file starts out with a file header followed by a sequence of data chunks. A WAVE file is often just a RIFF file with a single "WAVE" chunk which consists of two sub-chunks -- a "fmt" chunk specifying the data format and a "data" chunk containing the actual sample data. Call this form the "Canonical form".

Image 1

The main idea is to create only one header for all WAV files that you want to concatenate and then write data of each file in a single file.

Image 2

Wave file headers follow the standard RIFF file format structure. The first 8 bytes in the file are the standard RIFF chunk header which have a chunk ID of "RIFF" and a chunk size equal to the file size minus the 8 bytes used by the header.

So we need to know the total length of all files to define ChunkSize and read NumChannels, SampleRate and BitsPerSample.

C#
private void WaveHeaderIN(string spath)
        {
            FileStream fs = new FileStream(spath, FileMode.Open, FileAccess.Read);

            BinaryReader br = new BinaryReader(fs);
            length = (int)fs.Length - 8;
            fs.Position = 22;
            channels = br.ReadInt16();
            fs.Position = 24;
            samplerate = br.ReadInt32();
            fs.Position = 34;

            BitsPerSample = br.ReadInt16();
            DataLength = (int)fs.Length - 44;
            br.Close ();
            fs.Close();
        }

As we know channels are stored in the WAV header in byte number 22, we move the current position of the file to this location and the size of it is 2 bytes so we use br.ReadInt16() to read only 2 bytes and so on....

Construct the Header of Merged File

C#
private void WaveHeaderOUT(string sPath)
        {
            FileStream fs = new FileStream(sPath, FileMode.Create, FileAccess.Write );

            BinaryWriter bw = new BinaryWriter(fs);
            bw.Write(new char[4] { 'R', 'I', 'F', 'F' });

            bw.Write(length);

            bw.Write(new char[8] {'W','A','V','E','f','m','t',' '});

            bw.Write((int)16);

            bw.Write((short)1);
            bw.Write(channels);

            bw.Write(samplerate );

            bw.Write((int)(samplerate * ((BitsPerSample * channels) / 8)));

            bw.Write((short )((BitsPerSample * channels) / 8));

            bw.Write(BitsPerSample);

            bw.Write(new char[4] {'d','a','t','a'});
            bw.Write(DataLength);
            bw.Close();
            fs.Close();
        }

We must be careful when writing the header. If there is any small mistake, the merged file doesn't work, so we write "RIFF" as an array of char, not as string and use int type for storing 4 bytes and short type for storing 2 bytes.

Write Data of all Files in the Merged File

C#
public void Merge(string[] files, string outfile)
      {
          WaveIO wa_IN = new WaveIO();
          WaveIO wa_out = new WaveIO();

          wa_out.DataLength = 0;
          wa_out.length = 0;


          //Gather header data
          foreach (string path in files)
          {
              wa_IN.WaveHeaderIN(@path);
              wa_out.DataLength += wa_IN.DataLength;
              wa_out.length += wa_IN.length;

          }

          //Reconstruct new header
          wa_out.BitsPerSample = wa_IN.BitsPerSample;
          wa_out.channels = wa_IN.channels;
          wa_out.samplerate = wa_IN.samplerate;
          wa_out.WaveHeaderOUT(@outfile);

          foreach (string path in files)
          {
              FileStream fs = new FileStream(@path, FileMode.Open, FileAccess.Read);
              byte[] arrfile = new byte[fs.Length - 44];
              fs.Position = 44;
              fs.Read(arrfile, 0, arrfile.Length);
              fs.Close();

              FileStream fo =
                  new FileStream(@outfile, FileMode.Append, FileAccess.Write);
              BinaryWriter bw = new BinaryWriter(fo);
              bw.Write(arrfile);
              bw.Close();
              fo.Close();
          }
        }

First we need to calculate the total length and data length of all files and then specify the channels, SampleRate and BitsPerSample of the output file.The last thing is to start reading data that is stored after byte number 44 and append it to the merged file.

All we need to do is call the Merge method and specify the input files and output file.

C#
string[] files = new string[2] { @"C:\WINDOWS\Media\Windows XP Startup.wav",
                @"C:\WINDOWS\Media\Windows XP Shutdown.wav" };

WaveIO wa = new WaveIO();
wa.Merge(files,@"c:\oou.wav");

Play the Merged File

Visual Studio 2005 provides a new class to play sound. Therefore, we don't need an API or anything else.

C#
FileStream fs = new FileStream(@"c:\oou.wav", FileMode.Open,FileAccess.Read);
System.Media.SoundPlayer sp = new System.Media.SoundPlayer(fs);
sp.Play();
fs.Close();

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Egypt Egypt
Ehab M. M. Essa
Computer Science Department
Faculty of Computers and Information, Mansoura University, Egypt

Comments and Discussions

 
QuestionEditing small audio files , into a "song". Pin
iawiliams15-Sep-14 9:46
iawiliams15-Sep-14 9:46 
QuestionHola, necesito hablar con FocusedWolf por sus comentarios Pin
lepachec5-May-14 18:06
lepachec5-May-14 18:06 
Suggestionminor improvements needed Pin
Minh Danh Nguyen (ToughDev)1-Oct-11 4:24
Minh Danh Nguyen (ToughDev)1-Oct-11 4:24 
GeneralRe: minor improvements needed Pin
Yong-nam Kim19-Jul-15 19:10
Yong-nam Kim19-Jul-15 19:10 
GeneralRe: minor improvements needed Pin
Member 125705988-Jun-16 5:11
Member 125705988-Jun-16 5:11 
GeneralLicense Pin
thumb2231-Jan-11 3:10
thumb2231-Jan-11 3:10 
GeneralI have figured out a solution to the noise problem... Pin
Abhi2028-Aug-10 15:17
Abhi2028-Aug-10 15:17 
QuestionRe: I have figured out a solution to the noise problem... Pin
Member 1371643810-Dec-18 12:00
Member 1371643810-Dec-18 12:00 
QuestionHeavy distortion in output file [modified] Pin
golphknut17-Nov-09 8:33
golphknut17-Nov-09 8:33 
Generalvb.net: read, concat in mem, output to file or stream Pin
Milenko el Kebir23-Sep-09 0:37
Milenko el Kebir23-Sep-09 0:37 
GeneralAll in memory Pin
shem79-Mar-09 6:17
shem79-Mar-09 6:17 
QuestionThank & need haelp Pin
Member 286830623-Jan-09 6:56
Member 286830623-Jan-09 6:56 
QuestionStrange "clicks" ? Pin
japh13-May-08 10:12
japh13-May-08 10:12 
AnswerRe: Strange "clicks" ? Pin
thebeekeeper13-May-08 12:25
thebeekeeper13-May-08 12:25 
AnswerRe: Strange "clicks" ? Pin
wee_z_lee2-Oct-08 6:17
wee_z_lee2-Oct-08 6:17 
QuestionGetting weird background noise with a 8000hz, 1 channel, 64kbps file Pin
LosBear3-Apr-08 7:03
LosBear3-Apr-08 7:03 
AnswerRe: Getting weird background noise with a 8000hz, 1 channel, 64kbps file Pin
golphknut17-Nov-09 8:30
golphknut17-Nov-09 8:30 
Generalwave files Pin
c21127-Sep-07 18:54
c21127-Sep-07 18:54 
GeneralThanks Pin
mikhail_z21-Sep-07 10:24
mikhail_z21-Sep-07 10:24 
GeneralSimple Awesome.......! Pin
amiashu17-Jul-07 11:25
amiashu17-Jul-07 11:25 
JokeRefactored a bit :P [modified] Pin
FocusedWolf17-Jul-07 9:40
FocusedWolf17-Jul-07 9:40 
GeneralVery Inspiring Pin
Sujoy G15-Jul-07 18:30
Sujoy G15-Jul-07 18:30 
Generalsignal reduced Pin
akok011127-Mar-07 5:43
akok011127-Mar-07 5:43 
GeneralGreat thank you Pin
A.J.Bauer21-Mar-07 0:16
A.J.Bauer21-Mar-07 0:16 
GeneralRe: Great thank you Pin
A.J.Bauer21-Mar-07 2:58
A.J.Bauer21-Mar-07 2:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.