使用DirectX播放音频数据流
使用directX插件可以播放音频数据流
现在做一个测试项目,首先将信号发生器产生的正弦波(cw波)输入到语音编码器编码,再讲编码的数据用解码算法解码,解码输出的数据流就是cw波。这个过程主要目的为了测试解码算法是否能恢复cw波。暂时不考虑这个目的
项目流程
信号发生器(cw波)—->语音编码(encode)—–>解码算法(cw波)—->解码算法(cw波)——>写入到DirectX缓冲区 —->播放
本文是要实现用DirectX音频数据流,其实就是将音频数据流写到DirectX的缓冲区并播放,分为以下三步。
1.首先分析音频文件wav的格式,wav格式
2. 将音频数据流写到wav格式中data chunk
3. DirectX播放wav数据流。
代码如下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;
using System.IO;
namespace playwav
{
public partial class Form1 : Form
{
public const int SampleBitWidth = 16; //每个sample 包含 16bits
public const int SampleByteWidth = 16 >> 3;// 每个sample 包含 2个byte, 每帧包含160 sample
public const int SampleRate = 8000; //每秒采样8000个sample。每秒读取 8000*2 =16000bytes
BinaryWriter writer;
MemoryStream mes;
byte[] voice;
public Form1()
{
InitializeComponent();
}
private void buttonPlay_Click(object sender, EventArgs e)
{
write_wavfmt(9,1); //9*frame=9*160samples
BinaryReader stream = new BinaryReader(mse);
Stream a = stream.BaseStream;
Device dev = new Device();
dev.SetCooperativeLevel(this, CooperativeLevel.Normal);
SecondaryBuffer sec = new SecondaryBuffer(a,Convert.ToInt32(a.Length),dev);
sec.Play(0, BufferPlayFlags.Looping);
}
public void write_wavfmt(int framecount, int channelcount)
{
int datalength = framecount * 160 * 2 * channelcount; //每帧160sample =160*2bytes
int riffLength = datalength + 46;
voice = new byte[riffLength];
mes = new MemoryStream(voice);
writer = new BinaryWriter(mes);
//////////////wavfmt///////
this.writer.Write(ASCIIEncoding.ASCII.GetBytes("RIFF"));
this.writer.Write((int)riffLength);
this.writer.Write(ASCIIEncoding.ASCII.GetBytes("WAVEfmt"));
this.writer.Write((int)16);
this.writer.Write((short)1);
this.writer.Write((short)channelcount);
this.writer.Write((int)SampleRate);
this.writer.Write((int)SampleRate * SampleByteWidth * channelcount);//byteRate = SampleRate * SampleByteWidth
this.writer.Write((short)SampleBitWidth * channelcount);
this.writer.Write((short)SampleBitWidth);
this.writer.Write(ASCIIEncoding.ASCII.GetBytes("data"));
this.writer.Write((int)datalength);
byte[] data = Get_cw_Content(datalength);//读取cw音频数据。
this.writer.Write(data);
this.writer.BaseStream.Seek(0, SeekOrigin.Begin);
}
public byte[] Get_cw_Content(int datalength)
{
List<short> listData = new List<short>();
string cw_path2 = System.Environment.CurrentDirectory+ "\\tone.txt";
string read = string.Empty;
using (StreamReader sr = new StreamReader(cw_path2))
{
read = sr.ReadLine();
while (read != null)
{
listData.Add(Convert.ToInt16(read));
read = sr.ReadLine();
}
}
byte[] cw_data = new byte[datalength];
MemoryStream mestream = new MemoryStream(cw_data);
BinaryWriter bwriter = new BinaryWriter(mestream);
for (int i = 0; i < datalength/2; i++)
bwriter.Write(listData[i]);
bwriter.Close();
return cw_data;
}
}
}