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

 

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