一、通过nuget安装naudio包
开发工具:vs2019
点击visual studio 2019的工具->nuget包管理器-》管理解决方案的nuget的程序包-》浏览-》在搜索框中输入naudio-》点击安装
二、获取short类型或者byte类型的音频数据
我的数据是一组short类型的正弦波信号,存储在txt中,如下图所示:
通过c#读取文档并存储在short数组中
string filepath = "20500left.txt"; // txt文件路径 short[] audiodata = new short[48000 * 2]; //双声道数据 int index = 0; // 读取txt文档并按逗号分割文本 using (streamreader reader = new streamreader(filepath)) { string line; while ((line = reader.readline()) != null) { string[] parts = line.split(','); foreach (string part in parts) { //console.writeline(part); audiodata[index] = convert.toint16(part); index++; } } }
将short变为byte类型的数据(如果本身你的音频数据就是byte类型就不需要执行下边操作)
// 将short[]音频数据转换为byte[]数据 byte[] bytedata = new byte[audiodata.length * 2]; // short类型占2个字节 buffer.blockcopy(audiodata, 0, bytedata, 0, bytedata.length);
三、循环播放自己的音频数据,重写wavestream类
主要是重写了read这个函数,读到数据流末尾,就从开头读取。
class loopingwavestream : wavestream { private wavestream sourcestream; public loopingwavestream(wavestream sourcestream) { this.sourcestream = sourcestream; } public override waveformat waveformat => sourcestream.waveformat; public override long length => sourcestream.length; public override long position { get => sourcestream.position; set => sourcestream.position = value; } public override int read(byte[] buffer, int offset, int count) { int bytesread = 0; while (bytesread < count) { int read = sourcestream.read(buffer, offset + bytesread, count - bytesread); if (read == 0) { // 如果读取到末尾,重新从头开始读取 sourcestream.position = 0; } bytesread += read; } return bytesread; } }
将上边的byte类型的数据转换为stream类型,并填入waveout对象中,进行播放
// 创建内存流 using (memorystream stream = new memorystream(bytedata)) { // 从内存流中创建rawsourcewavestream //采样率设置为48000,位深设置位16位,通道为双声道 rawsourcewavestream rawstream = new rawsourcewavestream(stream, new waveformat(48000, 16, 2)); loopingwavestream loopingwavestream=new loopingwavestream(rawstream); // 使用waveoutevent播放音频数据 waveout waveout = new waveout(); waveout.init(loopingwavestream);//想要循环播放 //waveout.init(rawstream); //不想要循环播放 waveout.play(); //下边两种方式的循环播放会有爆音,不采用。 //waveout.playbackstopped += (sender, e) => // { // if (waveout.playbackstate == playbackstate.stopped) // { // rawstream.position = 0; // waveout.play(); // } // }; //while (waveout.playbackstate == playbackstate.playing) //{ // if (rawstream.position >= rawstream.length) // { // rawstream.position = 0; // //console.writeline("audio stream reached the end."); // //break; // } //} console.writeline("press enter to stop playback."); console.readline(); //阻塞线程 waveout.stop(); //停止播放 waveout.dispose(); }
四、完整代码
using naudio.wave; using system; using system.collections.generic; using system.io; using system.linq; using system.media; using system.text; using system.threading.tasks; namespace 播放short { class loopingwavestream : wavestream { private wavestream sourcestream; public loopingwavestream(wavestream sourcestream) { this.sourcestream = sourcestream; } public override waveformat waveformat => sourcestream.waveformat; public override long length => sourcestream.length; public override long position { get => sourcestream.position; set => sourcestream.position = value; } public override int read(byte[] buffer, int offset, int count) { int bytesread = 0; while (bytesread < count) { int read = sourcestream.read(buffer, offset + bytesread, count - bytesread); if (read == 0) { // 如果读取到末尾,重新从头开始读取 sourcestream.position = 0; } bytesread += read; } return bytesread; } } class program { static void main(string[] args) { console.writeline("开始"); string filepath = "20500left.txt"; // txt文件路径 short[] audiodata = new short[48000 * 2]; //双声道数据 int index = 0; // 读取txt文档并按逗号分割文本 using (streamreader reader = new streamreader(filepath)) { string line; while ((line = reader.readline()) != null) { string[] parts = line.split(','); foreach (string part in parts) { //console.writeline(part); audiodata[index] = convert.toint16(part); index++; } } } // 将short[]音频数据转换为byte[]数据 byte[] bytedata = new byte[audiodata.length * 2]; // short类型占2个字节 buffer.blockcopy(audiodata, 0, bytedata, 0, bytedata.length); //方式1/// // 创建内存流 using (memorystream stream = new memorystream(bytedata)) { // 从内存流中创建rawsourcewavestream //采样率设置为48000,位深设置位16位,通道为双声道 rawsourcewavestream rawstream = new rawsourcewavestream(stream, new waveformat(48000, 16, 2)); loopingwavestream loopingwavestream=new loopingwavestream(rawstream); // 使用waveoutevent播放音频数据 waveout waveout = new waveout(); waveout.init(loopingwavestream);//想要循环播放 //waveout.init(rawstream); //不想要循环播放 waveout.play(); //下边两种方式的循环播放会有爆音,不采用。 //waveout.playbackstopped += (sender, e) => // { // if (waveout.playbackstate == playbackstate.stopped) // { // rawstream.position = 0; // waveout.play(); // } // }; //while (waveout.playbackstate == playbackstate.playing) //{ // if (rawstream.position >= rawstream.length) // { // rawstream.position = 0; // //console.writeline("audio stream reached the end."); // //break; // } //} console.writeline("press enter to stop playback."); console.readline(); //阻塞线程 waveout.stop(); //停止播放 waveout.dispose(); } } } }
以上就是c#播放short或者byte类型的音频的详细内容,更多关于c#播放音频的资料请关注代码网其它相关文章!
发表评论