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;
}
}
}