wav->pcm pcm->wav c#代碼:c#
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace wavtopcm { public partial class Form1 : Form { public Form1() { InitializeComponent(); InitialStruct(); } /// <summary> /// ERROR MESSAGE /// </summary> const string ERRFILENOTEXITS = "File is Not Exits."; const string ERRFILEISNOTWAVE = "File is not Wava."; /// <summary> /// Wave Hander information /// </summary> struct HeaderType { public byte[] riff; /*RIFF類資源文件頭部 4byte*/ public uint file_len; /*文件長度4byte*/ public byte[] wave; /*"WAVE"標誌4byte*/ public byte[] fmt; /*"fmt"標誌4byte*/ public uint NI1; /*過渡字節4byte*/ public ushort format_type; /*格式類別(10H爲PCM形式的聲音數據)2byte*/ public ushort Channels; /*Channels 1 = 單聲道; 2 = 立體聲2byte*/ public uint frequency; /*採樣頻率4byte*/ public uint trans_speed; /*音頻數據傳送速率4byte*/ public ushort dataBlock; /*數據塊的調整數(按字節算的)2byte*/ public ushort sample_bits; /*樣本的數據位數(8/16) 2byte*/ public byte[] data; /*數據標記符"data" 4byte*/ public uint wav_len; /*語音數據的長度 4byte*/ } private HeaderType wavHander; //定義一個頭結構體 private byte[] buff = new byte[44]; //header byte private byte[] databuff; //data byte /// <summary> /// 初始化結構體中的數組長度,分配內存 /// </summary> private void InitialStruct() { wavHander.riff = new byte[4];//RIFF wavHander.wave = new byte[4];//WAVE wavHander.fmt = new byte[4];//fmt wavHander.data = new byte[4];//data } /// <summary> /// 讀取PCM中數據, /// </summary> /// <param name="filepath">文件路徑</param> /// <returns>讀取成功返回真</returns> private bool readPcm(string filepath) { String fileName = filepath;//臨時保存文件名 if (File.Exists(fileName) == false)//文件不存在 { throw new Exception(ERRFILENOTEXITS); } //自讀方式打開 FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None); if (file == null)//打開成功 { file.Close();//關閉文件 throw new Exception(ERRFILEISNOTWAVE); } int filelen =(int) file.Length;//獲取文件長度 databuff = new byte[filelen+44];//分配 內存 file.Read(databuff, 44, filelen);//讀取文件,保存在內存中 file.Close();//關閉文件 return true; } /// <summary> /// 爲PCM文件構建文件頭,準備轉換爲WAV文件 /// </summary> /// <returns>構建成功返回真</returns> private bool InitHeader() { wavHander.riff = Encoding.ASCII.GetBytes("RIFF"); /*RIFF類資源文件頭部 4byte*/ wavHander.file_len=(uint) (databuff.Length); /*文件長度4byte*/ wavHander.wave=Encoding.ASCII.GetBytes("WAVE"); /*"WAVE"標誌4byte*/ wavHander.fmt=Encoding.ASCII.GetBytes("fmt "); /*"fmt"標誌4byte*/ wavHander.NI1 =0x10; /*過渡字節4byte*/ wavHander.format_type = 0x01; /*格式類別(10H爲PCM形式的聲音數據)2byte*/ wavHander.Channels = 0x01; /*Channels 1 = 單聲道; 2 = 立體聲2byte*/ wavHander.frequency = 0x1F40; /*採樣頻率4byte*/ wavHander.trans_speed = 0x3E80; /*音頻數據傳送速率4byte*/ wavHander.dataBlock = 0x02; /*數據塊的調整數(按字節算的)2byte*/ wavHander.sample_bits = 0x10; /*樣本的數據位數(8/16) 2byte*/ wavHander.data = Encoding.ASCII.GetBytes("data"); /*數據標記符"data" 4byte*/ wavHander.wav_len =(uint) (databuff.Length-44); /*語音數據的長度 4byte*/ byte[] byt2;//臨時變量 ,保存2位的整數 byte[] byt4;//臨時變量, 保存4位的整數 Encoding.ASCII.GetBytes(Encoding.ASCII.GetString(wavHander.riff),0,4,databuff,0);/*RIFF類資源文件頭部 4byte*/ byt4 = BitConverter.GetBytes(wavHander.file_len); /*文件長度4byte*/ Array.Copy(byt4, 0, databuff, 4, 4); Encoding.ASCII.GetBytes(Encoding.ASCII.GetString(wavHander.wave), 0, 4, databuff, 8);/*"WAVE"標誌4byte*/ Encoding.ASCII.GetBytes(Encoding.ASCII.GetString(wavHander.fmt), 0, 4, databuff, 12);/*"fmt"標誌4byte*/ byt4 = BitConverter.GetBytes(wavHander.NI1);/*過渡字節4byte*/ Array.Copy(byt4, 0, databuff,16,4); byt2 = BitConverter.GetBytes(wavHander.format_type);/*格式類別(10H爲PCM形式的聲音數據)2byte*/ Array.Copy(byt2, 0, databuff, 20,2); byt2 = BitConverter.GetBytes(wavHander.Channels);/*Channels 1 = 單聲道; 2 = 立體聲2byte*/ Array.Copy(byt2, 0, databuff, 22, 2); byt4 = BitConverter.GetBytes(wavHander.frequency);/*採樣頻率4byte*/ Array.Copy(byt4, 0, databuff, 24, 4); byt4 = BitConverter.GetBytes(wavHander.trans_speed);/*音頻數據傳送速率4byte*/ Array.Copy(byt4, 0, databuff, 28, 4); byt2 = BitConverter.GetBytes(wavHander.dataBlock);/*數據塊的調整數(按字節算的)2byte*/ Array.Copy(byt2, 0, databuff, 32, 2); byt2 = BitConverter.GetBytes(wavHander.sample_bits);/*樣本的數據位數(8/16) 2byte*/ Array.Copy(byt2, 0, databuff, 34, 2); Encoding.ASCII.GetBytes(Encoding.ASCII.GetString(wavHander.data), 0, 4, databuff, 36);/*數據標記符"data" 4byte*/ byt4 = BitConverter.GetBytes(wavHander.wav_len); /*語音數據的長度 4byte*/ Array.Copy(byt4, 0, databuff, 40, 4); return true; } /// <summary> /// 讀取WAVE文件,包括文件頭和數據部分 /// </summary> /// <param name="filepath">文件路徑</param> /// <returns>讀取成功返回真</returns> private bool readWav(string filepath) { String fileName = filepath;//保存文件名 if (File.Exists(fileName)==false)//文件不存在 { throw new Exception(ERRFILENOTEXITS); } //只讀方式打開文件 FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None); if ( file==null || file.Length<44) //長度少於44,或者打開失敗 { file.Close();// throw new Exception(ERRFILEISNOTWAVE); } file.Read(buff, 0, 44);//讀取文件頭 if (fixedData(buff) == false)//按位置保存文件頭信息到結構體中 throw new Exception(ERRFILEISNOTWAVE); databuff=new byte[wavHander.wav_len];//分配內存 try { file.Read(databuff, 0, databuff.Length);//讀取文件數據去數據 return true; } catch { return false; } finally { file.Close();//關閉文件 } } /// <summary> /// 把文件頭數組信息保存到結構體中 /// </summary> /// <param name="pbuff">文件頭數組</param> /// <returns>保存成功返回真</returns> bool fixedData ( byte[] pbuff) { Array.Copy(pbuff,0,wavHander.riff,0,4) ;// if (Encoding.ASCII.GetString(wavHander.riff) != "RIFF")//肯定文件是WAVA類型 return false; wavHander.file_len=BitConverter.ToUInt32(pbuff,4); Array.Copy(pbuff,8,wavHander.wave,0,4) ; Array.Copy(pbuff,12,wavHander.fmt,0,4) ; wavHander.NI1 = BitConverter.ToUInt32(pbuff, 16); wavHander.format_type=BitConverter.ToUInt16(pbuff,20); wavHander.Channels=BitConverter.ToUInt16(pbuff,22); wavHander.frequency=BitConverter.ToUInt32(pbuff,24); wavHander.trans_speed=BitConverter.ToUInt32(pbuff,28); wavHander.dataBlock=BitConverter.ToUInt16(pbuff,32); wavHander.sample_bits=BitConverter.ToUInt16(pbuff,34); Array.Copy(pbuff,36,wavHander.data,0,4); wavHander.wav_len=BitConverter.ToUInt32(pbuff,40); return true; } /// <summary> /// 獲取待轉換的文件名 /button1 && button3 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { Button b = (Button)sender; if (b.Name == "button1") txtWav2Pcm_wav.Text = getOpenFileName("WAV"); else txtPcm2Wav_pcm.Text = getOpenFileName("PCM"); } /// <summary> /// 打開對話框,獲取被打開的文件路徑 /// </summary> /// <param name="type">WAV && PCM</param> /// <returns>文件名</returns> private string getOpenFileName(string type) { openFileDialog1.InitialDirectory = "c://";//初始路徑 openFileDialog1.Title = "";//初始文件名爲空 if (type == "WAV")//WAV文件被打開 openFileDialog1.Filter = "all file|*.*|wav|*.wav"; else openFileDialog1.Filter = "all file|*.*|pcm|*.pcm"; openFileDialog1.FilterIndex = 2; if (openFileDialog1.ShowDialog() == DialogResult.OK) return openFileDialog1.FileName; else return ""; } private string getSaveFileName(string type) { saveFileDialog1.InitialDirectory = "c://";//初始路徑 saveFileDialog1.Title = "";//初始文件名 if (type == "WAV")//WAV文件被保存 saveFileDialog1.Filter = "all file|*.*|wav|*.wav"; else saveFileDialog1.Filter = "all file|*.*|pcm|*.pcm"; saveFileDialog1.FilterIndex = 2; if (saveFileDialog1.ShowDialog() == DialogResult.OK) return saveFileDialog1.FileName; else return ""; } /// <summary> /// 獲取文件被保存的名 button2&& button4 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { Button b = (Button)sender; if (b.Name == "button2") txtWav2Pcm_pcm.Text = getSaveFileName("PCM"); else txtPcm2Wav_wav.Text = getSaveFileName("WAV"); } /// <summary> /// wav->pcm /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnWav2Pcm_Click(object sender, EventArgs e) { try { if (readWav(txtWav2Pcm_wav.Text) == true) { WriteFile(txtWav2Pcm_pcm.Text, databuff); lstMessage.Items.Add("PCM文件轉換成功!" + System.DateTime.Now.ToString()); } } catch(Exception ex) { lstMessage.Items.Add(ex.Message); } } /// <summary> /// 寫文件操做 /// </summary> /// <param name="filename">文件路徑</param> /// <param name="pbuff">文件數據</param> private void WriteFile(string filename,byte[] pbuff) { if (File.Exists(filename) == true) File.Delete(filename); FileStream sw=File.OpenWrite(filename); if (pbuff != null && sw != null) { sw.Write(pbuff, 0, pbuff.Length); sw.Close(); } } /// <summary> /// pcm->wav /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnPcm2Wav_Click(object sender, EventArgs e) { try { if (readPcm(txtPcm2Wav_pcm.Text) && InitHeader()) { WriteFile(txtPcm2Wav_wav.Text, databuff); lstMessage.Items.Add("WAVA文件轉換成功!" + System.DateTime.Now.ToString()); } } catch (Exception ex) { lstMessage.Items.Add(ex.Message); } } } }