http://naudio.codeplex.com/
El programa en cuestión puede reproducir y detener varios sonidos simultáneamente, en bucle y con distinto volumen para cada uno, y ya lo único que me falta, es que pueda reproducir cada uno por un dispositivo diferente.
La documentación sobre este asunto se encuentra aquí: http://mark-dot-net.blogspot.com.es/2011/05/naudio-audio-output-devices.html, pero como siempre, no encuentro códigos de ejemplo para copiar y probar.
Código fuente de una versión reducida de mi programa:
Código vb:
Ver original
Imports NAudio.Wave Public Class Form1 Public Class LoopStream Inherits WaveStream Private sourceStream As WaveStream Public Sub New(sourceStream As WaveStream) Me.sourceStream = sourceStream Me.EnableLooping = True End Sub Public Property EnableLooping() As Boolean Get Return m_EnableLooping End Get Set(value As Boolean) m_EnableLooping = value End Set End Property Private m_EnableLooping As Boolean Public Overrides ReadOnly Property WaveFormat() As WaveFormat Get Return sourceStream.WaveFormat End Get End Property Public Overrides ReadOnly Property Length() As Long Get Return sourceStream.Length End Get End Property Public Overrides Property Position() As Long Get Return sourceStream.Position End Get Set(value As Long) sourceStream.Position = value End Set End Property Public Overrides Function Read(buffer As Byte(), offset As Integer, count As Integer) As Integer Dim totalBytesRead As Integer = 0 While totalBytesRead < count Dim bytesRead As Integer = sourceStream.Read(buffer, offset + totalBytesRead, count - totalBytesRead) If bytesRead = 0 Then If sourceStream.Position = 0 OrElse Not EnableLooping Then ' something wrong with the source stream Exit While End If ' loop sourceStream.Position = 0 End If totalBytesRead += bytesRead End While Return totalBytesRead End Function End Class Dim Noise As WaveOut Dim NoiseReader As AudioFileReader Dim Hum2010 As WaveOut Dim Hum2010Reader As AudioFileReader Private Sub PlayButton1_Click(sender As Object, e As EventArgs) Handles PlayButton1.Click If PlayButton1.Text = "Reproducir" Then Hum2010Reader = New AudioFileReader(Application.StartupPath & "\media\2010Hum.wav") Dim looping As New LoopStream(Hum2010Reader) ' Hum2010 = New WaveOut() Hum2010.Init(looping) Hum2010Reader.Volume = Val(T2010Volume.Value) / 10 Hum2010.Play() PlayButton1.Text = "Detener" Else PlayButton1.Text = "Reproducir" If Hum2010 IsNot Nothing Then Hum2010.Stop() End If End If End Sub Private Sub PlayButton2_Click(sender As Object, e As EventArgs) Handles PlayButton2.Click If PlayButton2.Text = "Reproducir" Then NoiseReader = New AudioFileReader(Application.StartupPath & "\media\Noise.wav") Dim looping As New LoopStream(NoiseReader) ' Noise = New WaveOut() Noise.Init(looping) NoiseReader.Volume = Val(NoiseVolume.Value) / 10 Noise.Play() PlayButton2.Text = "Detener" Else PlayButton2.Text = "Reproducir" If Noise IsNot Nothing Then Noise.Stop() End If End If End Sub Private Sub T2010Volume_Scroll(sender As Object, e As EventArgs) Handles T2010Volume.Scroll Hum2010Reader.Volume = Val(T2010Volume.Value) / 10 End Sub Private Sub NoiseVolume_Scroll(sender As Object, e As EventArgs) Handles NoiseVolume.Scroll NoiseReader.Volume = Val(NoiseVolume.Value) / 10 End Sub End Class
Enlace al proyecto de ejemplo: https://www.dropbox.com/s/weo3oxera2trk9n/Pruebas2.zip
Edito: Por lo que veo, poniendo Noise.DeviceNumber = 2 antes de Noise.Init(looping), usa mi segunda salida de audio, que se llama Audio digital (S/PFID). Por lo que mi pregunta pasa a ser, ¿cómo hago un combobox que liste todas las salidas de audio y que se aplique la seleccionada?
Edito2: Solucionado de esta forma:
Código vb:
Ver original
Private Sub InitialiseDeviceCombo() For deviceId As Integer = 0 To WaveOut.DeviceCount - 1 Dim capabilities = WaveOut.GetCapabilities(deviceId) Sonido2OutDevice.Items.Add([String].Format("Device {0} ({1})", deviceId, capabilities.ProductName)) Next If Sonido2OutDevice.Items.Count > 0 Then Sonido2OutDevice.SelectedIndex = 0 End If End Sub
Con ese código, le añado a un combobox la lista de salidas de audio, y al botón de reproducir, le añado Noise.DeviceNumber = Sonido2OutDevice.SelectedIndex justo antes de Noise.Init(looping) y ya suena exactamente por donde debería sonar.