开发工具:vs2019
点击Visual Studio 2019的工具->NuGet包管理器-》管理解决方案的NuGet的程序包-》浏览-》在搜索框中输入NAudio-》点击安装
我的数据是一组short类型的正弦波信号,存储在txt中,如下图所示:
通过C#读取文档并存储在short数组中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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类型就不需要执行下边操作)
1 2 3 |
// 将short[]音频数据转换为byte[]数据 byte[] byteData = new byte[audioData.Length * 2]; // short类型占2个字节 Buffer.BlockCopy(audioData, 0, byteData, 0, byteData.Length); |
主要是重写了Read这个函数,读到数据流末尾,就从开头读取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
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对象中,进行播放
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
// 创建内存流 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(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
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(); }
} } } |