一、通过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#播放音频的资料请关注代码网其它相关文章!
发表评论