using CommonLib.IO; using CommonLib.IO.File; using CommonLib.LOG; using DataCollectionSystem; using NWaves.Audio; using NWaves.Transforms; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.Remoting.Channels; using System.Text; using System.Threading.Tasks; using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar; using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox; namespace CommonLib.WavFile { public class WaveFile { /// ERROR MESSAGE /// const string ERRFILENOTEXITS = "File is Not Exits."; const string ERRFILEISNOTWAVE = "File is not Wava."; private int carNO = 0; private int channel = 0; private DateTime StartTime = DateTime.Now; public string SaveFileName { get; private set; } /// /// Wave Hander information /// public EventHandler EventCloseFile; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct HeaderType { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] riff; /*RIFF类资源文件头部 4byte*/ public uint file_len; /*文件长度4byte*/ // 文件总大小减去8字节 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] wave; /*"WAVE"标志4byte*/ //"WAVE"标识符 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] 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 SampleRate; /*采样频率4byte*/ public uint trans_speed; /*音频数据传送速率4byte 每秒的字节数,等于采样率乘以声道数乘以每个采样点的字节数*/ public ushort dataBlock; /*数据块的调整数(按字节算的)2byte*/// 数据块对齐单位(每个采样需要的字节数) public ushort sample_bits; /*样本的数据位数(8/16) 2byte*/ // 每个采样点的位数 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] data; /*数据标记符"data" 4byte*/ public uint wav_len; /*语音数据的长度 4byte*/ public HeaderType(uint len,uint freq= 0x3E8) { riff = Encoding.ASCII.GetBytes("RIFF");//RIFF wave = Encoding.ASCII.GetBytes("WAVE");//WAVE fmt = Encoding.ASCII.GetBytes("fmt ");//fmt data = Encoding.ASCII.GetBytes("data"); ;//data NI1 = 0x10; format_type = 0x01; Channels = 0x01; SampleRate = freq ; dataBlock = 0x02;// /*数据块的调整数(按字节算的)2byte*/ sample_bits = (ushort)(2*8 ); /*样本的数据位数(8/16) 2byte*/ trans_speed = freq * Channels * sample_bits / 8; /*音频数据传送速率4byte*/ //32000 wav_len = len-44; this.file_len = len; } } private HeaderType wavHander; //定义一个头结构体 private byte[] buff = new byte[44]; //header byte private byte[] databuff = new byte[0x200]; //data byte /// /// SavePointCnt/perSavePointCnt /// private int SavePointCnt = 0; private int perSavePointCnt = 0; private int InPointsCnt = 0; public WaveFile(uint len, uint freq = 0x1F40) { wavHander = new HeaderType(len, freq); InitBuffer(); } private void InitBuffer() { 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.SampleRate);/*采样频率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); } /// /// 读取WAVE文件,包括文件头和数据部分 /// /// 文件路径 /// 读取成功返回真 public bool readWav(string filepath) { Boolean bResult = false; String fileName = filepath;//保存文件名 if (File.Exists(fileName) == false)//文件不存在 { throw new Exception(ERRFILENOTEXITS); } try { //只读方式打开文件 using (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];//分配内存 file.Read(databuff, 0, databuff.Length);//读取文件数据去数据 bResult = true; } } catch (Exception ex) { LogStorage.Logs.Add(LogLevel.Error, ex.Message + "\n" + ex.StackTrace); } finally { } return bResult; } public bool writeWav(string filepath) { Boolean bResult = false; String fileName = filepath;//保存文件名 try { string dir = Path.GetDirectoryName(fileName); if(!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } //只读方式打开文件 using (FileStream file = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { Byte[] HeaderBytes = null; wavHander.file_len = (uint)(44+ databuff.Length-8); saveHeader(out HeaderBytes); file.Write(HeaderBytes, 0, HeaderBytes.Length); file.Write(databuff, 0, databuff.Length);//读取文件数据去数据 bResult = true; } } catch (Exception ex) { LogStorage.Logs.Add(LogLevel.Error, ex.Message + "\n" + ex.StackTrace); } finally { } return bResult; } public Boolean SetWavePoints( double[,] points) { Boolean bReuslt = false; try { wavHander.Channels = (ushort)points.GetLength(0); int pointCnt =points.GetLength(1); this.wavHander.sample_bits = 0x10; uint pointWidth = (uint)wavHander.sample_bits / 8; UInt32 ByteCnt = this.wavHander.wav_len = (UInt32)(pointCnt * wavHander.Channels * wavHander.sample_bits / 8); databuff = new byte[ByteCnt]; // for (uint i = 0; i < pointCnt; i++) { for (int j = 0; j < wavHander.Channels; j++) { short value = (short)points[j, i]; Byte[] bytes = BitConverter.GetBytes(value); Array.Copy(bytes, 0, databuff, (i * pointWidth + j), bytes.Length); } } bReuslt = true; } catch(Exception ex) { LogStorage.Logs.Add(LogLevel.Error, ex.Message + "\n" + ex.StackTrace); } return bReuslt; } public Boolean GetWavePoints(out double[,] points) { uint pointWidth = 0; Boolean bReuslt = false; points = null; // StringBuilder sb = new StringBuilder(); if ((this.databuff!=null)&&(this.databuff.Length > 0)) { if (this.wavHander.Channels > 0) { int datalen = this.databuff.Length; int channels = this.wavHander.Channels ; pointWidth = (UInt32)this.wavHander.sample_bits /8; uint pointCnt = this.wavHander.wav_len / pointWidth / this.wavHander.Channels; points = new double[this.wavHander.Channels, pointCnt]; for (uint i = 0; i < pointCnt; i++) { for (int j = 0; j < wavHander.Channels; j++) { int v = System.BitConverter.ToInt16(databuff, (int)(i * pointWidth + j)); points[ j,i] = v; // sb.Append(v.ToString()); //sb.Append("\r\n"); } } // string s = sb.ToString(); // File.WriteAllText("wav.csv",s); } bReuslt = true; } return bReuslt; } /// /// 把文件头数组信息保存到结构体中 /// /// 文件头数组 /// 保存成功返回真 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.SampleRate = 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; } void saveHeader(out byte[] headerBytes) { int headerSize = Marshal.SizeOf(wavHander); headerBytes = new byte[headerSize]; IntPtr headerPtr = Marshal.AllocHGlobal(headerSize); Marshal.StructureToPtr(wavHander, headerPtr, false); Marshal.Copy(headerPtr, headerBytes, 0, headerSize); Marshal.FreeHGlobal(headerPtr); } public string GetWaveFilePath(int carNO, int channel) { string strCardNO = carNO.ToString(); string strChannel = channel.ToString(); string WaveFilePath = MainForm.configValue.WaveFilePath; string FullFileName = string.Format(WaveFilePath, strCardNO, channel, DateTime.Now.ToString("yyyy-MM-dd-HHmmss")); string dir = Path.GetDirectoryName(FullFileName); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } return FullFileName; } public void Init_Write_Stream(int vcardNo, int vchannel) { this.carNO = vcardNo + 1; this.channel = vchannel + 1; SaveFileName = GetWaveFilePath(carNO, channel); LogStorage.Logs.Add(LogLevel.Trace, string.Format("{0}#板卡通道{1}初始化写入wav文件!", carNO, channel)); } private void DoEventCloseFile() { string SaveFileName = this.SaveFileName; string FileDir = Path.GetDirectoryName(SaveFileName); string FileExt = Path.GetExtension(SaveFileName); //删除旧文件 List allFiles = CommonFile.GetAllFilesInDirectory(FileDir, "*" + FileExt); double maxdays = MainForm.configValue.maxSaveDay; foreach (var file in allFiles) { TimeSpan timediff = DateTime.Now - file.LastWriteTime; double days = timediff.TotalDays; if (days > maxdays) { File.Delete(file.FullName); } } } public void FillBuffer() { } public void CloseFile() { DoEventCloseFile(); } List Listdoubles= new List(); /// /// 将数据填充到数组里,等数量达到后写入到文件 /// /// public void FillBuffer(double[] doubles) { try { InPointsCnt += doubles.Length; if (InPointsCnt <= SavePointCnt) { //添加到points里 Listdoubles.AddRange(doubles); } if (InPointsCnt >= perSavePointCnt) { int len = Listdoubles.Count(); var doublesArray = Listdoubles.ToArray(); double[,] points = new double[1, len]; for (int i = 0; i < len; i++) { points[0, i] = doublesArray[i]; } this.SetWavePoints(points); this.writeWav(this.SaveFileName); SaveFileName = GetWaveFilePath(carNO, channel); //保存文件 InPointsCnt = 0; Listdoubles.Clear(); } } catch(Exception ex) { LogStorage.Logs.Add(LogLevel.Error, ex.Message + ex.StackTrace); } } /// /// 每perSavePointCnt点数中保存SavePointCnt数量 /// /// /// public void SetPointCnt(int SavePointCnt,int perSavePointCnt) { this.SavePointCnt = SavePointCnt; this.perSavePointCnt = perSavePointCnt; } } }