This project has moved. For the latest updates, please go here.

Naudio Through a windows service

Feb 17, 2010 at 10:59 AM
Edited Feb 17, 2010 at 11:01 AM

Hi I have built two apps, one is a windows form which plays a wav file (This works fine). The Second is a windows service which plays a wav file. The second is using the same code as the windows form however some wav files it doesnt play at all and others it seems to speed up and only play about 1 second of the file...... Does anyone have any ideas?

Cheers
Chris

 

Imports NAudio.Wave

Public

Class AudioServer
Private newwave As New
NAudio.Wave.WaveOut
Private inputstream As
NAudio.Wave.WaveChannel32
Public Event OnSample As EventHandler(Of
SampleEventArgs)
Protected Overrides Sub OnStart(ByVal args() As String
)
Play("C:\doh.wav")
End Sub
 Private Sub Play(ByVal Filename As String)
        CreateInputStream(Filename)
        newwave.Init(inputstream)
        If newwave IsNot Nothing AndAlso inputstream IsNot Nothing AndAlso newwave.PlaybackState <> PlaybackState.Playing Then
            newwave.Play()
            newwave.Dispose()
        End If


    End Sub
    Private Shared Function OpenWavStream(ByVal fileName As String) As WaveChannel32
        Dim inputStream As WaveChannel32
        Dim readerStream As WaveStream = New WaveFileReader(fileName)
        If readerStream.WaveFormat.Encoding <> WaveFormatEncoding.Pcm Then
            readerStream = WaveFormatConversionStream.CreatePcmStream(readerStream)
            readerStream = New BlockAlignReductionStream(readerStream)
        End If
        If readerStream.WaveFormat.BitsPerSample <> 16 Then
            Dim format = New WaveFormat(readerStream.WaveFormat.SampleRate, 16, readerStream.WaveFormat.Channels)
            readerStream = New WaveFormatConversionStream(format, readerStream)
        End If
        inputStream = New WaveChannel32(readerStream)
        Return inputStream
    End Function
    Private Sub CreateInputStream(ByVal fileName As String)
        If fileName.EndsWith(".wav") Then
            inputStream = OpenWavStream(fileName)
        ElseIf fileName.EndsWith(".mp3") Then
            inputStream = OpenMp3Stream(fileName)
        Else
            Throw New InvalidOperationException("Unsupported extension")
        End If
        'AddHandler inputStream.Sample, AddressOf inputStream_Sample
    End Sub
    Private Sub inputStream_Sample(ByVal sender As Object, ByVal e As SampleEventArgs)
        RaiseEvent OnSample(Me, e)
    End Sub
    Private Shared Function OpenMp3Stream(ByVal fileName As String) As WaveChannel32
        Dim inputStream As WaveChannel32
        Dim mp3Reader As WaveStream = New Mp3FileReader(fileName)
        Dim pcmStream As WaveStream = WaveFormatConversionStream.CreatePcmStream(mp3Reader)
        Dim blockAlignedStream As WaveStream = New BlockAlignReductionStream(pcmStream)
        inputStream = New WaveChannel32(blockAlignedStream)
        Return inputStream
    End Function
End Class

Editor
Feb 18, 2010 at 8:39 PM

How far have you got debugging this?

I suspect that you would have found everything works up until the point where you are playing the wave file? Or is it failing when you define the WaveOut?

Normally you need to provide a HWND (Window Handle) for WaveOut to work, I haven't looked through the latest version of NAudio to see how this is working now but from the code you have provided you aren't specifying one, which I would suspect is your issue when you are running this from a service as a service doesn’t display a window for you to get a handle from.

If your using Windows 7 try using core audio rather than WaveOut as per this post on Stack Overflow:

http://stackoverflow.com/questions/2143439/play-wave-file-from-a-windows-service-c

 ~DSebJ

Feb 18, 2010 at 9:27 PM

Hi,
     I did manage to get this work in the end it was to do with the wasapi module. Here is the code, hopfully it will help someone.

Imports NAudio.Wave
Imports NAudio.CoreAudioApi
Imports Microsoft.Win32

Public Class AudioServer
    Private newwave As NAudio.Wave.WasapiOut
    Private inputstream As NAudio.Wave.WaveChannel32
    Public Event OnSample As EventHandler(Of SampleEventArgs)
    Private AudioServerKey As RegistryKey = Registry.LocalMachine.OpenSubKey("Software\AudioServer", True)
    Private AudioServerCommandsKey As RegistryKey = Registry.LocalMachine.OpenSubKey("Software\AudioServer\Commands", True)
    Private checkAudioThread As System.Threading.Thread
    Private ActiveCheckAudio As Boolean = True
    Private PlayThread As System.Threading.Thread

    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.
        checkAudioThread = New System.Threading.Thread(AddressOf CheckAudio)
        ActiveCheckAudio = True
        checkAudioThread.Start()
      
    End Sub

    Protected Overrides Sub OnStop()
        ' Add code here to perform any tear-down necessary to stop your service.
        ActiveCheckAudio = False
    End Sub
    Private Sub CheckAudio()
        Do While ActiveCheckAudio
            If AudioServerKey.GetValue("Play") <> AudioServerKey.GetValue("LastPlay") Then
                AudioServerKey.SetValue("LastPlay", AudioServerKey.GetValue("Play"))
                Play(AudioServerKey.GetValue("Play"))
            End If
            If AudioServerKey.GetValue("CommandPlay") <> "" Then
                Play(AudioServerCommandsKey.GetValue(AudioServerKey.GetValue("CommandPlay")))
                AudioServerKey.SetValue("CommandPlay", "")
            End If
            System.Threading.Thread.Sleep(200)
        Loop
    End Sub
    Private Sub Play(ByVal Filename As String)
        CreateInputStream(Filename)
        newwave = New NAudio.Wave.WasapiOut(AudioClientShareMode.Shared, False, 300) ' This was the Key to the whole thing.
        newwave.Init(inputstream)
        If newwave IsNot Nothing AndAlso inputstream IsNot Nothing AndAlso newwave.PlaybackState <> PlaybackState.Playing Then
            newwave.Play()
            Dim newplaythread As New System.Threading.Thread(AddressOf playingthread)
            newplaythread.Start()
        End If
    End Sub
    Private Sub playingthread()
        Dim looping As Boolean = True
        Do While looping
            If inputstream.Position > inputstream.Length Then
                newwave.Stop()
                newwave.Dispose()
                inputstream.Dispose()
                looping = False
            End If
        Loop
    End Sub
    Private Shared Function OpenWavStream(ByVal fileName As String) As WaveChannel32
        Dim inputStream As WaveChannel32
        Dim readerStream As WaveStream = New WaveFileReader(fileName)
        If readerStream.WaveFormat.Encoding <> WaveFormatEncoding.Pcm Then
            readerStream = WaveFormatConversionStream.CreatePcmStream(readerStream)
            readerStream = New BlockAlignReductionStream(readerStream)
        End If
        If readerStream.WaveFormat.BitsPerSample <> 16 Then
            Dim format = New WaveFormat(readerStream.WaveFormat.SampleRate, 16, readerStream.WaveFormat.Channels)
            readerStream = New WaveFormatConversionStream(format, readerStream)
        End If
        inputStream = New WaveChannel32(readerStream)
        Return inputStream
    End Function
    Private Sub CreateInputStream(ByVal fileName As String)
        If fileName.EndsWith(".wav") Then
            inputStream = OpenWavStream(fileName)
        ElseIf fileName.EndsWith(".mp3") Then
            inputStream = OpenMp3Stream(fileName)
        Else
            Throw New InvalidOperationException("Unsupported extension")
        End If
        AddHandler inputStream.Sample, AddressOf inputStream_Sample
    End Sub
    Private Sub inputStream_Sample(ByVal sender As Object, ByVal e As SampleEventArgs)
        RaiseEvent OnSample(Me, e)
    End Sub
    Private Shared Function OpenMp3Stream(ByVal fileName As String) As WaveChannel32
        Dim inputStream As WaveChannel32
        Dim mp3Reader As WaveStream = New Mp3FileReader(fileName)
        Dim pcmStream As WaveStream = WaveFormatConversionStream.CreatePcmStream(mp3Reader)
        Dim blockAlignedStream As WaveStream = New BlockAlignReductionStream(pcmStream)
        inputStream = New WaveChannel32(blockAlignedStream)
        Return inputStream
    End Function
End Class