您的位置:首页 > 编程语言 > C#

wav格式与PCM格式的关系,pcm格式数据播放设置参数解析

2017-12-05 10:44 387 查看
其实PCM格式数据加上一系列的数据头就成为了 Wav格式数据,数据部分是一样的

项目工程在我的下载里面 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 c# wav 音频播放