当前位置: 首页 > 工具软件 > NAudio > 使用案例 >

NAudio 播放流、字节数组(非wav、mp3、aiff格式)

司空胤
2023-12-01

NAudio 播放流、字节数组(非wav、mp3、aiff格式)

1. 问题

http或websocket通信返回的音频数据流,导出到音频文件,然后再用AudioFileReader读取文件流,可以播放比较多格式的音频(例如:webm)。但是如果不创建临时文件,改如何直接播放流MemoryStream?

2. 举例

  • 1、返回的音频流是webm时,临时文件法可以正常播放,猜测可以分析读取文件流的方式,取消掉多余的步骤;
var filename = "./tmp.webm";
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);
	    }
 类似资料: