using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Train.wav2pcm
{
public partial class frmMain : Form
{
/// <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
public frmMain()
{
InitializeComponent();
InitialStruct();
}
/// <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);
}
}
}
}