wav格式与PCM格式的关系,pcm格式数据播放设置参数解析
2017-12-05 10:44
387 查看
其实PCM格式数据加上一系列的数据头就成为了 Wav格式数据,数据部分是一样的
项目工程在我的下载里面 http://download.csdn.net/download/wangchao712217/10145696
播放pcm格式 的代码
需要三个dll 动态连接库 audio.dll kennel32.dll WINMM.DLL,这三个文件请注意其要与程序配置X64,X86相匹配,否者会出现试图加载格式不正确的程序 ,我已测试过,可以运行。
调用代码的参数设置如下,
项目工程在我的下载里面 http://download.csdn.net/download/wangchao712217/10145696
项目工程在我的下载里面 http://download.csdn.net/download/wangchao712217/10145696
public class WaveOpeater { private byte[] riff; //4 private byte[] riffSize; //4 private byte[] waveID; //4 private byte[] fmtID; //4 private byte[] notDefinition; //4 private byte[] waveType; //2 private byte[] channel; //2 private byte[] sample; //4 private byte[] send; //4 private byte[] blockAjust; //2 private byte[] bitNum; //2 private byte[] unknown; //2 private byte[] dataID; //4 private byte[] dataLength; //4 short[] data; private string longFileName; public string LongFileName { get { return longFileName; } } public string ShortFileName { get { int pos = LongFileName.LastIndexOf("\\"); return LongFileName.Substring(pos + 1); } } public short[] Data { get { return data; } set { data = value; } } public string Riff { get { return Encoding.Default.GetString(riff); } set { riff = Encoding.Default.GetBytes(value); } } public uint RiffSize { get { return BitConverter.ToUInt32(riffSize, 0); } set { riffSize = BitConverter.GetBytes(value); } } public string WaveID { get { return Encoding.Default.GetString(waveID); } set { waveID = Encoding.Default.GetBytes(value); } } public string FmtID { get { return Encoding.Default.GetString(fmtID); } set { fmtID = Encoding.Default.GetBytes(value); } } public int NotDefinition { get { return BitConverter.ToInt32(notDefinition, 0); } set { notDefinition = BitConverter.GetBytes(value); } } public short WaveType { get { return BitConverter.ToInt16(waveType, 0); } set { waveType = BitConverter.GetBytes(value); } } public ushort Channel { get { return BitConverter.ToUInt16(channel, 0); } set { channel = BitConverter.GetBytes(value); } } public uint Sample { get { return BitConverter.ToUInt32(sample, 0); } set { sample = BitConverter.GetBytes(value); } } public uint Send { get { return BitConverter.ToUInt32(send, 0); } set { send = BitConverter.GetBytes(value); } } public ushort BlockAjust { get { return BitConverter.ToUInt16(blockAjust, 0); } set { blockAjust = BitConverter.GetBytes(value); } } public ushort BitNum { get { return BitConverter.ToUInt16(bitNum, 0); } set { bitNum = BitConverter.GetBytes(value); } } public ushort Unknown { get { if (unknown == null) { return 1; } else return BitConverter.ToUInt16(unknown, 0); } set { unknown = BitConverter.GetBytes(value); } } public string DataID { get { return Encoding.Default.GetString(dataID); } set { dataID = Encoding.Default.GetBytes(value); } } public uint DataLength { get { return BitConverter.ToUInt32(dataLength, 0); } set { dataLength = BitConverter.GetBytes(value); } } public WaveOpeater() { } FileStream fs; String m_filepath; BinaryReader bread; public void InitWave(string filepath) { m_filepath = filepath; try { riff = new byte[4]; riffSize = new byte[4]; waveID = new byte[4]; fmtID = new byte[4]; notDefinition = new byte[4]; waveType = new byte[2]; channel = new byte[2]; sample = new byte[4]; send = new byte[4]; blockAjust = new byte[2]; bitNum = new byte[2]; unknown = new byte[2]; dataID = new byte[4]; //52 dataLength = new byte[4]; //56个字节 if (File.Exists(filepath)) { fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); bread = new BinaryReader(fs); riff = bread.ReadBytes(4); riffSize = bread.ReadBytes(4); waveID = bread.ReadBytes(4); fmtID = bread.ReadBytes(4); notDefinition = bread.ReadBytes(4); waveType = bread.ReadBytes(2); channel = bread.ReadBytes(2); sample = bread.ReadBytes(4); send = bread.ReadBytes(4); blockAjust = bread.ReadBytes(2); bitNum = bread.ReadBytes(2); if (notDefinition.Length>0&& BitConverter.ToUInt32(notDefinition, 0) == 18) { unknown = bread.ReadBytes(2); } dataID = bread.ReadBytes(4); } } catch (System.Exception ex) { Console.Write(ex.Message); } } int DataCount = 3200 ; int DataCountByte = 6400; int preIndex = 0; int Curent = 0; public byte[] GetCurrentData() { Curent = GetDataAmount(); // Curent = amount; if (preIndex == Curent) { System.Threading.Thread.Sleep(10); return null; } // Debug.Write("当前读取到的音频数据帧号" + Curent); preIndex = Curent; if (Curent > 1) { long offset = 0; offset = 44 + (Curent - 1) * DataCountByte;//44字节的头 ,加上数据块的便偏移 fs.Seek(offset, SeekOrigin.Begin); byte[] data2 = new byte[DataCountByte]; bread.Read(data2, 0, DataCountByte); return data2; } else { return null; } } public byte[] GetAudioSegment() { Curent = GetDataAmount(); // Curent = amount; if (preIndex == Curent) { System.Threading.Thread.Sleep(10); return null; } if ((Curent - preIndex)>20|| preIndex> Curent) { preIndex = Curent; return null; } if ( Curent> preIndex) { long offset = 0; offset = 44 + (preIndex) * DataCountByte;//44字节的头 ,加上数据块的便偏移 fs.Seek(offset, SeekOrigin.Begin); int readLength = (Curent - preIndex) * DataCountByte; byte[] data2 = new byte[readLength]; bread.Read(data2, 0, readLength); preIndex = Curent; return data2; } else { return null; } } private short[] ByteArrayToShortArray(Byte[] shortarr) { short[] arrs = new short[shortarr.Length/2]; for (int i = 0; i < shortarr.Length/2; i++) { arrs[i]=System.BitConverter.ToInt16(shortarr, i*2); } return arrs; } private int GetDataAmount() { longFileName = m_filepath; System.IO.FileInfo f = new FileInfo(m_filepath); long fileLength = f.Length; long _dataLength = fileLength - 44; dataLength = BitConverter.GetBytes(_dataLength); int number =(int) DataLength / DataCountByte; return number; } public void Close() { if (fs!=null) { bread.Close(); fs.Close(); } } private short[] GetData(uint begin, uint end) { if ((end - begin) >= Data.Length) return Data; else { uint temp = end - begin + 1; short[] dataTemp = new short[temp]; uint j = begin; for (int i = 0; i < temp; i++) { dataTemp[i] = Data[j];//读入2字节有符号整数 j++; } return dataTemp; } } /// <summary> /// 生成wav文件到系统 /// </summary> /// <param name="fileName">要保存的文件名</param> /// <returns></returns> public bool bulidWave(string fileName) { try { FileInfo fi = new FileInfo(fileName); if (fi.Exists) fi.Delete(); FileStream fs = new FileStream(fileName, FileMode.CreateNew); BinaryWriter bwriter = new BinaryWriter(fs); bwriter.Seek(0, SeekOrigin.Begin); bwriter.Write(Encoding.Default.GetBytes(this.Riff)); //不可以直接写入string类型的字符串,字符串会有串结束符,比原来的bytes多一个字节 bwriter.Write(this.RiffSize); bwriter.Write(Encoding.Default.GetBytes(this.WaveID)); bwriter.Write(Encoding.Default.GetBytes(this.FmtID)); bwriter.Write(this.NotDefinition); bwriter.Write(this.WaveType); bwriter.Write(this.Channel); bwriter.Write(this.Sample); bwriter.Write(this.Send); bwriter.Write(this.BlockAjust); bwriter.Write(this.BitNum); if (this.Unknown != 0) bwriter.Write(this.Unknown); bwriter.Write(Encoding.Default.GetBytes(this.DataID)); bwriter.Write(this.DataLength); for (int i = 0; i < this.Data.Length; i++) { bwriter.Write(this.Data[i]); } bwriter.Flush(); fs.Close(); bwriter.Close(); fi = null; return true; } catch (System.Exception ex) { Console.Write(ex.Message); return false; } } public bool CheckStatus() { return true; } }
播放pcm格式 的代码
需要三个dll 动态连接库 audio.dll kennel32.dll WINMM.DLL,这三个文件请注意其要与程序配置X64,X86相匹配,否者会出现试图加载格式不正确的程序 ,我已测试过,可以运行。
public class AudioOutOperator { private static List<int> IDS; private static int m_CurentID; private int m_ID; private static object m_IDLocker; private object m_Locker; private uint m_Port; public AudioOutOperator() { m_IDLocker = new object(); IDS = new List<int>(); m_CurentID = -1; } public AudioOutOperator(uint _Port) { this.m_Locker = new object(); this.m_Port = 0; this.m_ID = 0; this.m_Port = _Port; this.m_ID = CreateID(); } public static int CreateID() { lock (m_IDLocker) { m_CurentID++; if (m_CurentID >= 0x3e8) { m_CurentID = 0; } while (IDS.Contains(m_CurentID)) { m_CurentID++; if (m_CurentID >= 0x3e8) { m_CurentID = 0; } } IDS.Add(m_CurentID); return m_CurentID; } } public static AudioOutOperator CreateInstance(uint _Port) { return new AudioOutOperator(_Port); } public void PlayAudio(AudioOutData _Audio) { // object CS$2$0000; // Monitor.Enter(CS$2$0000 = this.m_Locker); try { AudioFormat _AudioFormat = AudioFormat.CreateInstance(_Audio); IntPtr _PtrFormat = StructToPtr(typeof(AudioFormat), _AudioFormat); IntPtr _PtrData = ArrayToPtr(_Audio.Data); SendAudioData(this.m_ID, this.m_Port, _PtrFormat, _PtrData, _Audio.Data.Length); Marshal.FreeHGlobal(_PtrFormat); Marshal.FreeHGlobal(_PtrData); } catch (System.Exception ex) { throw ex; } finally { // Monitor.Exit(CS$2$0000); } } [DllImport("Audio.dll")] private static extern int SendAudioData(int _ID, uint _Port, IntPtr _FORMAT, IntPtr _Data, int Len); public void StopAudio() { try { IDS.Remove(this.m_ID); StopPlay(this.m_ID); } catch { } } [DllImport("Audio.dll")] private static extern int StopPlay(int _ID); private static IntPtr ArrayToPtr(byte[] _Data) { if (_Data == null) { return new IntPtr(); } IntPtr _adress = Marshal.AllocHGlobal(_Data.Length); Marshal.Copy(_Data, 0, _adress, _Data.Length); return _adress; } public static IntPtr StructToPtr(Type _Type, object _Obj) { IntPtr _Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(_Type)); Marshal.StructureToPtr(_Obj, _Ptr, true); return _Ptr; } } public struct AudioOutData { public ushort wFormatTag; // format type public ushort nChannels; // number of channels (i.e. mono, stereo...) public uint nSamplesPerSec; // sample rate public uint nAvgBytesPerSec; // for buffer estimation public ushort nBlockAlign; // block size of data public ushort wBitsPerSample; // Number of bits per sample of mono data public ushort cbSize; // The count in bytes of the size of extra information (after cbSize) public byte[] Data; } public struct AudioFormat { [MarshalAs(UnmanagedType.U4)] public uint nSampleRate; [MarshalAs(UnmanagedType.U2)] public ushort nBitsPerSample; [MarshalAs(UnmanagedType.U2)] public ushort nNoOfChannels; [MarshalAs(UnmanagedType.U4)] public uint nRateInBytesPerSec; [MarshalAs(UnmanagedType.U1)] public byte cFrameLen; public static AudioFormat CreateInstance(AudioOutData _Audio) { return new AudioFormat { nRateInBytesPerSec = _Audio.nAvgBytesPerSec, nNoOfChannels = _Audio.nChannels, nSampleRate = _Audio.nSamplesPerSec, nBitsPerSample = _Audio.wBitsPerSample, cFrameLen = (byte)_Audio.nBlockAlign }; } public static AudioOutData CreateAudioData(AudioFormat _AudioFormat) { return new AudioOutData { nAvgBytesPerSec = _AudioFormat.nRateInBytesPerSec, nChannels = _AudioFormat.nNoOfChannels, nSamplesPerSec = _AudioFormat.nSampleRate, wBitsPerSample = _AudioFormat.nBitsPerSample, nBlockAlign = _AudioFormat.cFrameLen }; } }
调用代码的参数设置如下,
AudioOutOperator audioData2 = new AudioOutOperator(); AudioOutData test = new AudioOutData(); test.nSamplesPerSec = 32000; test.nChannels = 1; test.Data = buffer;//buffer为数组,音频数据 test.nAvgBytesPerSec = test.nSamplesPerSec / 16; test.nBlockAlign = 6400; test.wBitsPerSample = 16; audioData2.PlayAudio(test);
项目工程在我的下载里面 http://download.csdn.net/download/wangchao712217/10145696
相关文章推荐
- PCM转WAV格式 Wav数据格式的44个字节头部信息汇总
- caffe 实战系列:proto文件格式以及含义解析:如何定义网络,如何设置网络参数(以AlexNet为例)
- C#双串口采集光照度与温度和湿度 数据保存在mysql 参数自动保存 解析格式十六进制收发
- wave文件(*.wav)格式、PCM数据格式, goldwave 可以播放pcm raw audio
- ffmpeg命令转音乐为wav格式,wav格式与PCM数据相互转换,ffplay播放PCM数据
- caffe 实战系列:proto文件格式以及含义解析:如何定义网络,如何设置网络参数(以AlexNet为例) 2016.3.30
- 用NFS挂载时参数解析及uboot设置
- java解析json格式数据
- iOS开发之JSON格式数据的生成与解析
- windows2003 iis中播放flv格式的视频设置
- POI对Excel单元格的格式的设置参数
- GridView中,数据格式的设置种类
- FFMPEG学习----使用SDL播放PCM数据
- window API播放pcm格式音频文件,函数waveOutOpen等
- curl模拟数据请求,在header头中设置自定义的参数
- JavaScript解析JSON格式的数据
- ASP.NET设置数据格式与String.Format使用总结
- Codeigniter3.0项目分页-数据分页中url地址有多个参数时的分页设置
- java解析json格式数据
- iOS >> POST 上传数据(文件压缩)>>表单上传 (如何设置form格式)