Visual Basic使用NAudio实现指定输出设备循环播放提示音求助
NAudio 自定义输出设备+循环播放解决方案
实现思路:通过监听WaveOut的播放完成事件,每次播放结束后重置音频流的起始位置重新触发播放即可实现循环,完全兼容你现有的输出设备选择逻辑。
修改后完整可运行代码
' 首先将相关对象声明为类级变量,避免局部方法执行完被回收,事件触发时无法访问 Private Wave1 As NAudio.Wave.WaveOut Private data As IO.MemoryStream Private waveReader As NAudio.Wave.WaveFileReader Private isLooping As Boolean = True ' 用来控制是否继续循环的开关 Sub PlayLoopingSoundWithCustomDevice(MediaOutputDevice As String, audioFilePath As String) Dim xa() As Byte = IO.File.ReadAllBytes(audioFilePath) Wave1 = New NAudio.Wave.WaveOut() data = New IO.MemoryStream(xa) waveReader = New NAudio.Wave.WaveFileReader(data) ' 原有的输出设备选择逻辑保留 Dim deviceEnum = New MMDeviceEnumerator() Dim devices = deviceEnum.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active).ToList() Dim outputIndex As Integer = 0 For i = 0 To devices.Count - 1 If devices(i).ToString() = MediaOutputDevice Then outputIndex = i Exit For End If Next Wave1.DeviceNumber = outputIndex ' 订阅播放结束事件,触发时自动重播 AddHandler Wave1.PlaybackStopped, AddressOf OnPlaybackStopped Wave1.Init(waveReader) Wave1.Play() End Sub Private Sub OnPlaybackStopped(sender As Object, e As NAudio.Wave.StoppedEventArgs) ' 只有循环开关打开时才自动重播,排除主动调用Stop的情况 If isLooping Then ' 重置音频读取流的位置到开头 waveReader.Position = 0 Wave1.Play() End If End Sub ' 停止循环播放的方法 Sub StopLoopingSound() isLooping = False RemoveHandler Wave1.PlaybackStopped, AddressOf OnPlaybackStopped Wave1.Stop() ' 释放资源 waveReader.Dispose() data.Dispose() Wave1.Dispose() End Sub
核心注意事项
- 原代码单次播放后
WaveFileReader的流位置会移动到末尾,重播前必须将Position属性重置为0才能读取到音频内容 - 播放相关对象不要声明为方法内的局部变量,否则方法执行完成后会被垃圾回收,导致播放结束事件无法触发
- 新增的
isLooping开关用来区分是播放自然结束还是主动停止,避免主动调用停止后又自动重播 - 如果遇到设备选择不匹配的问题,可以将
WaveOut替换为WasapiOut,直接传入枚举到的MMDevice对象,不用手动匹配索引,准确率更高,修改参考如下:' 替换原来的Wave1声明和DeviceNumber赋值部分即可 Dim Wave1 As New NAudio.Wave.WasapiOut(devices(outputIndex), NAudio.Wave.AudioClientShareMode.Shared, 100)
内容的提问来源于stack exchange,提问作者Mirba
相关产品推荐
相关产品推荐

