NAudio 播放流、字节数组(非wav、mp3、aiff格式)
1. 问题
http或websocket通信返回的音频数据流,导出到音频文件,然后再用AudioFileReader
读取文件流,可以播放比较多格式的音频(例如:webm)。但是如果不创建临时文件,改如何直接播放流MemoryStream
?
2. 举例
- 1、返回的音频流是webm时,临时文件法可以正常播放,猜测可以分析读取文件流的方式,取消掉多余的步骤;
var filename = "./";
using (var audioFile = new AudioFileReader(filename))
using (var waveOut = new WaveOutEvent())
{
waveOut.Init(audioFile);
waveOut.Play();
while (waveOut.PlaybackState == PlaybackState.Playing)
Thread.Sleep(100);
}
- 2、查看
AudioFileReader
构造函数,其中CreateReaderStream
方法是成功播放wav、mp3、aiff这3类音频的关键,所以需要找到能MediaFoundationReader
相关联的类;
// 摘要:
// Creates the reader stream, supporting all filetypes in the core NAudio library,
// and ensuring we are in PCM format
//
// 参数:
// fileName:
// File Name
private void CreateReaderStream(string fileName)
{
if (fileName.EndsWith(".wav", StringComparison.OrdinalIgnoreCase))
{
readerStream = new WaveFileReader(fileName);
if (readerStream.WaveFormat.Encoding != WaveFormatEncoding.Pcm && readerStream.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat)
{
readerStream = WaveFormatConversionStream.CreatePcmStream(readerStream);
readerStream = new BlockAlignReductionStream(readerStream);
}
}
else if (fileName.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase))
{
if (Environment.OSVersion.Version.Major < 6)
{
readerStream = new Mp3FileReader(fileName);
}
else
{
readerStream = new MediaFoundationReader(fileName);
}
}
else if (fileName.EndsWith(".aiff", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".aif", StringComparison.OrdinalIgnoreCase))
{
readerStream = new AiffFileReader(fileName);
}
else
{
// 一切其他格式音频IO流读取方式
readerStream = new MediaFoundationReader(fileName);
}
}
- 3、借助vs代码智能提示,找到了
MediaFoundationReader
的子类StreamMediaFoundationReader
public class StreamMediaFoundationReader : MediaFoundationReader
{
private readonly Stream stream;
public StreamMediaFoundationReader(Stream stream, MediaFoundationReaderSettings settings = null)
{
this.stream = stream;
Init(settings);
}
// 省略
}
3. 代码修改
byte[] buffer;
using (var ms = new MemoryStream(buffer))
using (var media = new StreamMediaFoundationReader(ms))
using (var waveOut = new WaveOutEvent())
{
waveOut.Init(media);
waveOut.Play();
while (waveOut.PlaybackState == PlaybackState.Playing)
Thread.Sleep(100);
}