使用 NAudio 流式传输非 PCM 原始音频

发布于 2024-11-15 17:02:17 字数 1420 浏览 3 评论 0原文

我一心想与 NAudio 合作,所以请告诉我是否有办法解决这个问题。我有来自串行设备的流式原始音频,我正在尝试通过 WaveOut 播放该音频。

尝试 1:

'Constants 8000, 1, 8000 * 1, 1, 8
Dim CustomWaveOutFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, SampleRate, Channels, AverageBPS, BlockAlign, BitsPerSample)    
Dim rawStream = New RawSourceWaveStream(VoicePort.BaseStream, CustomWaveOutFormat)

'Run in background
Dim waveOut = New WaveOut(WaveCallbackInfo.FunctionCallback())

'Play stream
waveOut.Init(rawStream)
waveOut.Play()

这段代码可以工作,但有一个小问题 - 实际的音频流不是原始 PCM,而是原始 MuLaw。它的压扩就像奶酪刨丝器上的贝多芬第五交响曲一样。如果我将 WaveFormat 更改为 WaveFormatEncoding.MuLaw,我会收到错误格式异常,因为它是原始音频并且没有 RIFF 标头。

因此,我开始将其转换为 PCM:

尝试 2:

Dim reader = New MuLawWaveStream(VoicePort.BaseStream, SampleRate, Channels)
Dim pcmStream = WaveFormatConversionStream.CreatePcmStream(reader)
Dim waveOutStream = New BlockAlignReductionStream(pcmStream)

waveOut.Init(waveOutStream)

这里,CreatePcmStream 尝试获取流的长度(即使 CanSeek = false)并失败。

尝试 3

waveOutStream = New BufferedWaveProvider(WaveFormat.CreateMuLawFormat(SampleRate, Channels))
*add samples when OnDataReceived()*

它似乎也因缺少标题而受到影响。

我希望在这一切中我错过了一些小事。该设备仅在使用时传输音频,否则不会接收任何数据 - 由 (1) 处理的情况。

I'm hell bent on making this work with NAudio, so please tell me if there's a way around this. I have streaming raw audio coming in from a serial device, which I'm trying to play through WaveOut.

Attempt 1:

'Constants 8000, 1, 8000 * 1, 1, 8
Dim CustomWaveOutFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, SampleRate, Channels, AverageBPS, BlockAlign, BitsPerSample)    
Dim rawStream = New RawSourceWaveStream(VoicePort.BaseStream, CustomWaveOutFormat)

'Run in background
Dim waveOut = New WaveOut(WaveCallbackInfo.FunctionCallback())

'Play stream
waveOut.Init(rawStream)
waveOut.Play()

This code works, but there's a tiny problem - the actual audio stream isn't raw PCM, it's raw MuLaw. It plays out the companding like a Beethoven's 5th on cheese-grater. If I change the WaveFormat to WaveFormatEncoding.MuLaw, I get a bad format exception because it's raw audio and there are no RIFF headers.

So I moved over to converting it to PCM:

Attempt 2:

Dim reader = New MuLawWaveStream(VoicePort.BaseStream, SampleRate, Channels)
Dim pcmStream = WaveFormatConversionStream.CreatePcmStream(reader)
Dim waveOutStream = New BlockAlignReductionStream(pcmStream)

waveOut.Init(waveOutStream)

Here, CreatePcmStream tries to get the length of the stream (even though CanSeek = false) and fails.

Attempt 3

waveOutStream = New BufferedWaveProvider(WaveFormat.CreateMuLawFormat(SampleRate, Channels))
*add samples when OnDataReceived()*

It too seems to suffer from lack of having a header.

I'm hoping there's something minor I missed in all of this. The device only streams audio when in use, and no data is received otherwise - a case which is handled by (1).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏末 2024-11-22 17:02:17

为了使尝试(1)起作用,您的RawSourceWaveStream应该指定数据真正采用的格式。然后只需使用另一个WaveFormatConversionStream.CreatePcmStream,将rawStream作为输入:

Dim muLawStream = New RawSourceWaveStream(VoicePort.BaseStream, WaveFormat.CreateMuLawFormat(SampleRate, Channels))
Dim pcmStream = WaveFormatConversionStream.CreatePcmStream(muLawStream);

尝试(2)实际上非常接近工作。您只需使 MuLawStream.Length 返回 0。您所做的事情不需要它。 BlockAlignReductionStream 也与 mu-law 无关,因为 mu-law 块对齐为 1。

尝试 (3) 应该可行。不知道你说的没有标题是什么意思?

在 NAudio 中,您正在构建音频数据管道。管道中的每个阶段可以有不同的格式。您的音频以 Mu-law 格式开始,然后转换为 PCM,然后就可以播放了。即使您的设备已停止提供音频数据,您也可以使用缓冲的 WaveProvider 来继续播放。

编辑 我应该补充一点,NAudio 中的 IWaveProvider 接口是一个简化的 WaveStream。它只有一个格式和一个 Read 方法,对于长度未知且无法重新定位的情况很有用。

To make attempt (1) work, your RawSourceWaveStream should specify the format that the data really is in. Then just use another WaveFormatConversionStream.CreatePcmStream, taking rawStream as the input:

Dim muLawStream = New RawSourceWaveStream(VoicePort.BaseStream, WaveFormat.CreateMuLawFormat(SampleRate, Channels))
Dim pcmStream = WaveFormatConversionStream.CreatePcmStream(muLawStream);

Attempt (2) is actually very close to working. You just need to make MuLawStream.Length return 0. You don't need it for what you are doing. BlockAlignReductionStream is irrelevant to mu-law as well since mu law block align is 1.

Attempt (3) should work. I don't know what you mean by lack of a header?

In NAudio you are building a pipeline of audio data. Each stage in the pipeline can have a different format. Your audio starts off in Mu-law, then gets converted to PCM, then can be played. A buffered WaveProvider is used for you want playback to continue even though your device has stopped providing audio data.

Edit I should add that the IWaveProvider interface in NAudio is a simplified WaveStream. It has only a format and a Read method, and is useful for situations where Length is unknown and repositioning is not possible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文