NAudio播放音频后读取缓冲区为零,播放前正常的原因及重置疑问
问题分析与解决方案
哎,这个NAudio的坑我之前踩过!你遇到的问题本质是WaveFileReader(或者你用的其他音频读取类)是基于只读向前流实现的——当你调用播放代码时,播放组件会把流的位置一直读到末尾,等你之后再调用audioFile.Read()时,流已经处于末尾位置,自然读不到任何有效数据,返回的缓冲区全是0。
确实需要重置流位置!
虽然很多基础示例没提这个操作,但这是流操作的基本逻辑——任何向前只读流在读取到末尾后,都需要手动重置位置才能重新读取。对你的场景来说,解决步骤很简单:
- 确保播放已经停止(如果用的是WaveOut/MediaFoundationPlayer这类组件,要调用
Stop()或者等待PlaybackStopped事件触发) - 调用
audioFile.Position = 0;把流的指针重置到文件开头
修改后的代码示例
给你调整一下你的代码片段,关键位置加上重置逻辑:
using System; using NAudio.Wave; namespace NAudioTest { class TestPlayer { static void Main(string[] args) { string infileName = "你的音频文件路径.wav"; using (var audioFile = new WaveFileReader(infileName)) using (var waveOut = new WaveOutEvent()) { // 播放逻辑 waveOut.Init(audioFile); waveOut.Play(); // 注意:实际项目里不要用Sleep等待播放完成,建议监听PlaybackStopped事件 System.Threading.Thread.Sleep((int)audioFile.TotalTime.TotalMilliseconds + 100); waveOut.Stop(); // 核心操作:重置流位置到开头 audioFile.Position = 0; // 现在再读取缓冲区就正常了 int numSamples = audioFile.WaveFormat.SampleRate * audioFile.WaveFormat.Channels; float[] buffer = new float[numSamples]; int readCount = audioFile.Read(buffer, 0, numSamples); // 后续的编辑、写入文件操作... } } } }
为什么示例里没提?
大多NAudio基础示例都是单一场景:要么只做播放,要么只做读取编辑写入,很少覆盖“同一个流先播放再读取”的复合场景,所以这个细节容易被忽略。但只要记住音频读取类本质是流操作,就很容易想到要重置位置啦。
内容的提问来源于stack exchange,提问作者AlexS
相关产品推荐
相关产品推荐

