C#播放short或者byte類型的音頻
一、通過(guò)Nuget安裝NAudio包
開(kāi)發(fā)工具:vs2019
點(diǎn)擊Visual Studio 2019的工具->NuGet包管理器-》管理解決方案的NuGet的程序包-》瀏覽-》在搜索框中輸入NAudio-》點(diǎn)擊安裝

二、獲取short類型或者byte類型的音頻數(shù)據(jù)
我的數(shù)據(jù)是一組short類型的正弦波信號(hào),存儲(chǔ)在txt中,如下圖所示:

通過(guò)C#讀取文檔并存儲(chǔ)在short數(shù)組中
string filePath = "20500Left.txt"; // txt文件路徑
short[] audioData = new short[48000 * 2]; //雙聲道數(shù)據(jù)
int index = 0;
// 讀取txt文檔并按逗號(hào)分割文本
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變?yōu)閎yte類型的數(shù)據(jù)(如果本身你的音頻數(shù)據(jù)就是byte類型就不需要執(zhí)行下邊操作)
// 將short[]音頻數(shù)據(jù)轉(zhuǎn)換為byte[]數(shù)據(jù) byte[] byteData = new byte[audioData.Length * 2]; // short類型占2個(gè)字節(jié) Buffer.BlockCopy(audioData, 0, byteData, 0, byteData.Length);
三、循環(huán)播放自己的音頻數(shù)據(jù),重寫WaveStream類
主要是重寫了Read這個(gè)函數(shù),讀到數(shù)據(jù)流末尾,就從開(kāi)頭讀取。
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)
{
// 如果讀取到末尾,重新從頭開(kāi)始讀取
sourceStream.Position = 0;
}
bytesRead += read;
}
return bytesRead;
}
}將上邊的byte類型的數(shù)據(jù)轉(zhuǎn)換為Stream類型,并填入WaveOut對(duì)象中,進(jìn)行播放
// 創(chuàng)建內(nèi)存流
using (MemoryStream stream = new MemoryStream(byteData))
{
// 從內(nèi)存流中創(chuàng)建RawSourceWaveStream //采樣率設(shè)置為48000,位深設(shè)置位16位,通道為雙聲道
RawSourceWaveStream rawStream = new RawSourceWaveStream(stream, new WaveFormat(48000, 16, 2));
LoopingWaveStream loopingWaveStream=new LoopingWaveStream(rawStream);
// 使用WaveOutEvent播放音頻數(shù)據(jù)
WaveOut waveOut = new WaveOut();
waveOut.Init(loopingWaveStream);//想要循環(huán)播放
//waveOut.Init(rawStream); //不想要循環(huán)播放
waveOut.Play();
//下邊兩種方式的循環(huán)播放會(huì)有爆音,不采用。
//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)
{
// 如果讀取到末尾,重新從頭開(kāi)始讀取
sourceStream.Position = 0;
}
bytesRead += read;
}
return bytesRead;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("開(kāi)始");
string filePath = "20500Left.txt"; // txt文件路徑
short[] audioData = new short[48000 * 2]; //雙聲道數(shù)據(jù)
int index = 0;
// 讀取txt文檔并按逗號(hào)分割文本
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[]音頻數(shù)據(jù)轉(zhuǎn)換為byte[]數(shù)據(jù)
byte[] byteData = new byte[audioData.Length * 2]; // short類型占2個(gè)字節(jié)
Buffer.BlockCopy(audioData, 0, byteData, 0, byteData.Length);
//方式1///
// 創(chuàng)建內(nèi)存流
using (MemoryStream stream = new MemoryStream(byteData))
{
// 從內(nèi)存流中創(chuàng)建RawSourceWaveStream //采樣率設(shè)置為48000,位深設(shè)置位16位,通道為雙聲道
RawSourceWaveStream rawStream = new RawSourceWaveStream(stream, new WaveFormat(48000, 16, 2));
LoopingWaveStream loopingWaveStream=new LoopingWaveStream(rawStream);
// 使用WaveOutEvent播放音頻數(shù)據(jù)
WaveOut waveOut = new WaveOut();
waveOut.Init(loopingWaveStream);//想要循環(huán)播放
//waveOut.Init(rawStream); //不想要循環(huán)播放
waveOut.Play();
//下邊兩種方式的循環(huán)播放會(huì)有爆音,不采用。
//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類型的音頻的詳細(xì)內(nèi)容,更多關(guān)于C#播放音頻的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Unity Blend Tree動(dòng)畫混合樹(shù)使用入門教程
這篇文章主要為大家詳細(xì)介紹了Unity Blend Tree動(dòng)畫混合樹(shù)使用入門教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
C#記一次http協(xié)議multipart/form-data的boundary問(wèn)題
這篇文章主要介紹了C#記一次http協(xié)議multipart/form-data的boundary問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
C#設(shè)計(jì)模式編程中運(yùn)用適配器模式結(jié)構(gòu)實(shí)戰(zhàn)演練
這篇文章主要介紹了C#設(shè)計(jì)模式編程中運(yùn)用適配器模式結(jié)構(gòu)實(shí)戰(zhàn)演練,并總結(jié)了適配器模式的優(yōu)缺點(diǎn)和適用場(chǎng)景以及.NET框架中的應(yīng)用,需要的朋友可以參考下2016-02-02
C#使用CEFSharp獲取動(dòng)態(tài)網(wǎng)頁(yè)源碼的演示步驟
CEFSharp是一個(gè)用C#編寫的庫(kù),它是Chromium Embedded Framework (CEF) 的.NET封裝和擴(kuò)展,CEF允許開(kāi)發(fā)者在自己的應(yīng)用程序中嵌入一個(gè)功能強(qiáng)大的HTML渲染引擎,從而能夠呈現(xiàn)網(wǎng)頁(yè)內(nèi)容,本文介紹了C#如何使用CEFSharp獲取動(dòng)態(tài)網(wǎng)頁(yè)源碼,需要的朋友可以參考下2024-08-08
C#結(jié)合JavaScript實(shí)現(xiàn)上傳視頻到騰訊云點(diǎn)播平臺(tái)的操作方法
這篇文章主要介紹了C#結(jié)合JavaScript實(shí)現(xiàn)上傳視頻到騰訊云點(diǎn)播平臺(tái),上傳視頻功能,主要要解決兩個(gè)問(wèn)題,一是在服務(wù)端通過(guò)C#生成簽名和SDKID,二是在客戶端通過(guò)JavaScript上傳視頻到騰訊云點(diǎn)播服務(wù)器,感興趣的朋友跟隨小編一起看看吧2023-11-11
C#連接Informix數(shù)據(jù)庫(kù)的問(wèn)題
這篇文章主要介紹了C#連接Informix數(shù)據(jù)庫(kù)的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的工作或?qū)W習(xí)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03

