合併WAVE文件

WAVE文件格式是微軟RIFF規範的一個實例(用來存儲多媒體文件),RIFF文件頭由連續的chunk組成。WAVE文件是由一個大的"WAVE" chunk組成,這個大的chunk由一個”fmt”chunk和一個”data”chunk組成。

標準WAVE文件格式

 

 

 

這篇的目的是把多個WAVE文件合成爲一個只有一個文件頭,並把每個數據合併起來的文件。

 

WAVE的文件頭符合標準的RIFF文件結構。頭8字節由chunk ID”RIFF”chunk size組成。

所以我們需知道合成後文件的chunk sizenumchannelssampleratebitspersample

代碼:

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();

        }

numchannels位於 WAVE文件第22位開始,並且有2字節。所以我們可以在第22位使用br.ReadInt16()來讀取到channels中。其它一樣。

合成文件的頭結構

代碼:

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();

        }

注意寫文件頭時要小心些。如果有些差錯,合成文件就沒法運行了。所以這裏我們用一組char類型來寫“RIFF“,而不是string。使用int類型存儲4個字節,使用short存儲2字節。

把所有文件的數據寫進合成文件中

  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();

            }

          }

  首先我們得先計算輸出文件總長度和所有文件的數據長度,然後指定輸出文件的channelssampleratebitspersample,最後一件事情就是讀取所有文件的數據存儲到合成文件的44位後

   現在我們需要做的就是調用Merge方法,並指定輸入和輸出文件。

代碼:

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");

播放合成文件:

Visual Studio 2005提供給我們一個播放聲音的類,因此我們不需要API和其它的東東.

代碼:

FileStream fs = new FileStream(@"c:/oou.wav", FileMode.Open,FileAccess.Read);

System.Media.SoundPlayer sp = new System.Media.SoundPlayer(fs);

sp.Play();

fs.Close();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章