如何使用NAudio播放嵌入资源中的WAV文件?
解决嵌入WAV到EXE并使用NAudio播放的问题
我来帮你搞定这个嵌入音频到EXE的播放问题——你之前遇到的慢放混响、结束爆音,基本都是因为资源流的处理方式不对,咱们一步步来解决:
第一步:正确设置WAV文件的嵌入属性
首先确保你的sound_1.wav被正确标记为嵌入资源:
- 在Visual Studio中,选中Resources文件夹里的
sound_1.wav - 在属性窗口里,把生成操作改成
Embedded Resource(默认可能是Resource,这两种资源的访问逻辑完全不同,一定要改) - 确认复制到输出目录设置为
不复制,因为我们要把它嵌入到EXE里,不需要单独输出
第二步:用NAudio读取嵌入资源流(关键!WaveFileReader支持Stream)
你之前误以为WaveFileReader只能接受字符串路径,但其实它有WaveFileReader(Stream stream)的重载!这才是嵌入资源播放的正确打开方式。
完整代码示例(WPF环境)
下面是一个可直接用的播放方法,包含了资源清理逻辑(解决爆音的核心):
using NAudio.Wave; using System.Reflection; using System.Windows; // 建议在窗口类中声明播放对象,方便管理生命周期 private WaveOutEvent? _audioPlayer; private WaveFileReader? _waveReader; private void PlayEmbeddedAudio() { // 1. 获取当前程序集(包含嵌入资源的EXE/DLL) var currentAssembly = Assembly.GetExecutingAssembly(); // 2. 嵌入资源的完整名称:格式是「项目命名空间.文件夹名.文件名」 // 比如你的项目命名空间是WpfAudioPlayer,资源在Resources文件夹,那就是WpfAudioPlayer.Resources.sound_1.wav var resourceFullName = "YourProjectNamespace.Resources.sound_1.wav"; // 3. 获取嵌入资源的流 using var resourceStream = currentAssembly.GetManifestResourceStream(resourceFullName); if (resourceStream == null) { MessageBox.Show("找不到嵌入的音频资源,请检查资源名称是否正确"); return; } // 4. 初始化播放器:注意不要用using包裹WaveFileReader,因为播放时需要流保持打开 _waveReader = new WaveFileReader(resourceStream); _audioPlayer = new WaveOutEvent(); _audioPlayer.Init(_waveReader); // 5. 绑定播放结束事件,清理资源(解决爆音的关键) _audioPlayer.PlaybackStopped += (sender, args) => { _waveReader?.Dispose(); _audioPlayer?.Dispose(); _waveReader = null; _audioPlayer = null; }; // 6. 开始播放 _audioPlayer.Play(); }
为什么你之前的方案会出问题?
- 慢放带混响:大概率是你把资源转成byte[]后用MemoryStream,但没有重置流的
Position到0,或者错误地处理了流的编码格式,导致NAudio读取的音频参数(采样率、通道数)不正确,播放速度就会异常。 - 结束时爆音:通常是因为播放结束后没有及时释放
WaveOut和WaveFileReader的资源,或者流被提前关闭,导致音频设备的缓冲数据没有正确清空,就会出现刺耳的爆音。
额外注意事项
- 如果你不确定资源的全名,可以用
currentAssembly.GetManifestResourceNames()打印所有嵌入资源的名称,对照着找正确的名字。 - 如果你需要更好的兼容性,可以用
WasapiOut代替WaveOutEvent,尤其是在Windows 10/11的WPF应用中,Wasapi的音频处理更稳定。 - 不要在UI线程执行长时间的音频操作,不过上面的代码里,播放是异步的,所以不会阻塞UI。
内容的提问来源于stack exchange,提问作者Matt McManis
相关产品推荐
相关产品推荐

