C#播放short或者byte类型的音频
作者:rbigbearr
这篇文章主要为大家详细介绍了如何使用C#实现播放short或者byte类型的音频,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
一、通过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#播放音频的资料请关注脚本之家其它相关文章!