Results 1 to 21 of 21

Thread: [RESOLVED] How to check if wave file stopped playing

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Dec 2009
    Location
    Netherlands, Europe
    Posts
    21

    Resolved [RESOLVED] How to check if wave file stopped playing

    I'm playing a wave file using DirectX, this works great but how can I determin if the wave file has stopped playing?

    Code:
    Private Sub Command1_Click()
    Set dsToneBuffer = DS.CreateSoundBufferFromFile(App.Path & "\sound.wav", idesc)
    End Sub
    I want the program to take another action as soon as the file has been played. Any suggestions on how to do this?

  2. #2
    Fanatic Member
    Join Date
    Mar 2009
    Posts
    804

    Re: How to check if wave file stopped playing

    Not much help here since I know little about DirectX, however if you
    are using DirectX ONLY to play the sound, you can remove the reference
    to DX & just use the simple API method below

    Code:
    Option Explicit
    Private Const SND_ASYNC = &H1
    Private Const SND_SYNC = &H0
    Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
    
    Private Sub Form_Load()
     Call sndPlaySound("C:\SomePath\SomeWave.wav", SND_SYNC) 'hard coded
     ' As written, the debug statement below doesn't execute until the wave has
    '  finished playing.  If you change the above to SND_ASYNC the debug statement
    '  executes immediately, i. e. before the sound finishes
     Debug.Print "done"
    End Sub

  3. #3
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: How to check if wave file stopped playing

    Use a timer control. First measure the time it takes for the .Wav file to play and enable the timer when it starts. Check the elapsed time about every half second inside the timer and when the elapsed time is reached, stop the player control, disable the timer, and perform the next action.
    Last edited by Code Doc; Dec 28th, 2009 at 04:13 PM.
    Doctor Ed

  4. #4

    Thread Starter
    Junior Member
    Join Date
    Dec 2009
    Location
    Netherlands, Europe
    Posts
    21

    Re: How to check if wave file stopped playing

    Quote Originally Posted by Code Doc View Post
    Use a timer control. First measure the time it takes for the .Wav file to play and enable the timer when it starts. Check the elapsed time about every half second inside the timer and when the elapsed time is reached, stop the player control, disable the timer, and perform the next action.
    That makes sense Ed but the problem is that in my case the wave file can have a variable length, it’s a different one each time. Sot this won’t work.
    I’ll have another look at VBClassicRocks solution, it might work. I use DirectX only for sound.
    I have an external USB soundcard and even if the sound stopped playing the led light keeps flashing as if sound is still being produce. Only until I close the buffer or end the program it stops flashing.

    I’ll let you know the outcome. Thanks!

  5. #5
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: How to check if wave file stopped playing

    Quote Originally Posted by Floyd View Post
    That makes sense Ed but the problem is that in my case the wave file can have a variable length, it’s a different one each time. Sot this won’t work.
    I’ll have another look at VBClassicRocks solution, it might work. I use DirectX only for sound.
    I have an external USB soundcard and even if the sound stopped playing the led light keeps flashing as if sound is still being produce. Only until I close the buffer or end the program it stops flashing.

    I’ll let you know the outcome. Thanks!
    So, each .Wav file has a variable length? That's no problem. You read that length whenever the .Wav file is selected. That sets the time that the Timer control is enabled.

    The sound player control should be able to return the playing time of the track. If not, you might be able to look at the size of the .Wav file in bytes and use a simple mathematical formula to measure the expected length of the playing time. I have found that the file size is an excellent indicator.
    Doctor Ed

  6. #6
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: How to check if wave file stopped playing

    Quote Originally Posted by Floyd View Post
    I'm playing a wave file using DirectX, this works great but how can I determin if the wave file has stopped playing?
    I've never tried using DX to play wave files, but this seems to detect if the song is still playing or not.

    Code:
    Option Explicit
    Private DX As New DirectX8
    Private DS As DirectSound8
    Dim desc As DSBUFFERDESC
    Private sound As DirectSoundSecondaryBuffer8
    
    Private Sub Form_Load()
        Timer1.Enabled = False
    End Sub
    
    Private Sub Command1_Click() ' test play
        Set DX = New DirectX8
        Set DS = DX.DirectSoundCreate("")
        Set sound = DS.CreateSoundBufferFromFile("C:\TEST.WAV", desc)
        DS.SetCooperativeLevel Me.hWnd, DSSCL_NORMAL
        sound.Play DSBPLAY_DEFAULT
        Timer1.Interval = 100
        Timer1.Enabled = True
    End Sub
    
    Private Sub Timer1_Timer() ' is song still playing?
        If sound.GetStatus <> DSBSTATUS_PLAYING Then
            Timer1.Enabled = False
            Debug.Print "Song has ended."
        End If
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        Set sound = Nothing
        Set DX = Nothing
        Set DS = Nothing
    End Sub

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Dec 2009
    Location
    Netherlands, Europe
    Posts
    21

    Re: How to check if wave file stopped playing

    Quote Originally Posted by Code Doc View Post
    So, each .Wav file has a variable length? That's no problem. You read that length whenever the .Wav file is selected. That sets the time that the Timer control is enabled.
    ....
    Yes that is a good solution and I would get a pretty good estimate. But I think I've found an even better one; as long as the file is playing the status of the sound buffer appears to be set to DSBSTATUS_PLAYING

    Now I added a few Msgboxes, it turns out the wave file I am testing it with is about 17 seconds long.

    Code:
        TX3.BackColor = vbRed
    Set dsToneBuffer3 = DS.CreateSoundBufferFromFile(App.Path & "\test.wav", desc3)
        dsToneBuffer3.Play DSBPLAY_DEFAULT
        If dsToneBuffer3.GetStatus <> DSBSTATUS_PLAYING Then
        MsgBox "status is NOT playing"
        Else
        MsgBox "status is playing"
        End If
        Sleep 18000
        If dsToneBuffer3.GetStatus <> DSBSTATUS_PLAYING Then
        MsgBox "status is NOT playing"
        Else
        MsgBox "status is playing"
        End If
    At startup I get the message 'Status is playing' and after sleeping for 18 seconds the message 'Status is NOT playing' is shown.

    Just to get it working I would like to get the TX3 button from red back to white: TX3.BackColor = vbWhite

    So I need to get the Sleep 18000 command and everything below out. And add a routine that switches the button back to white as soon as the wave file has finished. As a VB newbie I don't know what would be the best way to do that. Can anybody guide me in the right direction?

  8. #8

    Thread Starter
    Junior Member
    Join Date
    Dec 2009
    Location
    Netherlands, Europe
    Posts
    21

    Re: How to check if wave file stopped playing

    I see that while I was typing the previous message Edgemeal already pointed out the DSBSTATUS_PLAYING of the sound buffer. Simulanious trouble shooting Thanks Edgemeal !

    I should probably use a while-do loop to check the status of the buffer, which ever way is least CPU time consuming.... Maybe half a second (Sleep 500) in the loop?

  9. #9
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: How to check if wave file stopped playing

    Again, use the timer control to do that. As soon as 18 seconds have expired, change the TX3 button color to vbWhite. Make sure that the style of the command button is set to graphical. Check this out:
    Code:
    Dim StartTime As Double, ElTime As Integer
    Private Sub Form_Load()
    StartTime = Now
    Timer1.Interval = 500 ' accurate to within 1/2 second
    End Sub
    
    Private Sub Timer1_Timer()
    ElTime = (Now - StartTime) * 86400
    If ElTime > 18 Then ' Playing time of .Wav file is 18 seconds, right Floyd?
        Command1.BackColor = vbWhite
        Timer1.Enabled =- False
    Else: Command1.BackColor = vbRed ' Sound file is through
    End If
    End Sub
    Doctor Ed

  10. #10
    PowerPoster CDRIVE's Avatar
    Join Date
    Jul 2007
    Posts
    2,620

    Re: How to check if wave file stopped playing

    Floyd, I would avoid using Sleep durations that long. It makes your app comatose for that period. Members have reported various undesirable affects, and have even reported crashes. If you want long durations, work your code into a Timer sub or use the code in the first link. Your app will still be responsive to you, it doesn't eat the CPU and won't cause weird instability.

    http://www.vbforums.com/showpost.php...12&postcount=8

    By the way, if you ever use the sndPlaySound API you should read this, as it was superseded by the PlaySound API. sndPlaySound was kept for backward compatibility.

    http://allapi.mentalis.org/apilist/sndPlaySound.shtml
    <--- Did someone help you? Please rate their post. The little green squares make us feel really smart!
    If topic has been resolved, please pull down the Thread Tools & mark it Resolved.


    Is VB consuming your life, and is that a bad thing??

  11. #11
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: How to check if wave file stopped playing

    I have to agree with CDrive on this issue. That's why I usually avoid long Sleep (ing) times.

    See my code for a workable option. Set a duration variable and check it within the timer control. Reset the starting time variable when you start the next track.
    Doctor Ed

  12. #12

    Thread Starter
    Junior Member
    Join Date
    Dec 2009
    Location
    Netherlands, Europe
    Posts
    21

    Re: How to check if wave file stopped playing

    Ok, I will avoid the Sleep fuction. I needed some Sleep (28800000) myself, but back again.
    To check if dsToneBuffer3.GetStatus = DSBSTATUS_PLAYING I tried a While Wend and also a Do while loop but somehow it doesn’t work.

    If I let it sleep for 18 seconds and do another check I get the message that dsToneBuffer3.GetStatus <> DSBSTATUS_PLAYING.
    Why doesn’t this work in a continuous loop? Any ideas?

  13. #13

    Thread Starter
    Junior Member
    Join Date
    Dec 2009
    Location
    Netherlands, Europe
    Posts
    21

    Re: How to check if wave file stopped playing

    Almost there but still one problem.
    What I mean is this, the button TX3 has a White background color at startup and it is set to graphic in the properties.

    When I run the program it is white as it should be. The code on Command3_Click is this

    Code:
    Private Sub Command3_Click()
        Set dsToneBuffer3 = DS.CreateSoundBufferFromFile(App.Path & "test.wav", desc3)
        dsToneBuffer3.Play DSBPLAY_DEFAULT
        TX3.BackColor = vbRed
        Dim i As Long
        For i = 1 To 20000
        Sleep 10
        If dsToneBuffer3.GetStatus <> DSBSTATUS_PLAYING Then
        i = 20000
        End If
        Next
        TX3.BackColor = vbBlue
        MsgBox "End of sequence"
    End sub
    Now what I would expect to happen is this: at startup the TX3 button is white. Clicking the button: the wave file plays and the TX3 button changes to red, when the sound finishes the TX3 button turns blue and the message ‘End of sequence’ appears.

    But what happens is this: The button is white. On click the wave file plays but the TX3 button remains white, when the sound has finished the TX3 button turns blue and the message ‘End of sequence’ is shown.

    Why does the color of the button change to red while the sound is playing? If I switch place blue/red the button will turn red at the end. It keeps skipping the first command, even if I put it in the loop.
    Is switching color of an object limited to 1 time per event?

  14. #14
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: How to check if wave file stopped playing

    Try adding a .Refresh after changing the color.

    Once you are in that loop nothing else can update unless you add a DoEvents after the Sleep call. Why not just use a timer?

    TX3.BackColor = vbRed
    TX3.Refresh

  15. #15
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: How to check if wave file stopped playing

    Quote Originally Posted by Edgemeal View Post
    Try adding a .Refresh after changing the color.

    Once you are in that loop nothing else can update unless you add a DoEvents after the Sleep call. Why not just use a timer?

    TX3.BackColor = vbRed
    TX3.Refresh
    Edge, that was what I was getting ready to post. The timer that we all recommended never got incorporated. Sleep calls also tend to give me the creeps.
    Doctor Ed

  16. #16
    PowerPoster CDRIVE's Avatar
    Join Date
    Jul 2007
    Posts
    2,620

    Re: How to check if wave file stopped playing

    I didn't say to avoid the Sleep function, it works well for short durations. Just use it as shown in the Pause Sub shown in the link. It uses it in 1mS slices but can create a very (stable) Pause into hrs, while still being totally responsive to user interaction such as a button click.

    This code provides a dramatic demonstration of Sleep vs Pause.

    In Module:
    Code:
    Option Explicit
    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    
    Public Sub Pause(ByVal Delay As Single)
       Delay = Timer + Delay
       If Delay > 86400 Then 'more than number of seconds in a day
          Delay = Delay - 86400
          Do
              DoEvents ' to process events.
              Sleep 1 ' to not eat cpu
          Loop Until Timer < 1
       End If
       Do
           DoEvents ' to process events.
           Sleep 1 ' to not eat cpu
       Loop While Delay > Timer
    End Sub
    In Form:
    Code:
    Option Explicit
    
    Private Sub Command1_Click()
       Command3.Enabled = False
       Command1.Enabled = False
       Command2.SetFocus
       Me.Caption = "Sleeping  for 10 sec"
       Sleep 10000
       MsgBox "Sleep timed out"
       Command3.Enabled = True
       Command1.Enabled = True
       Me.Show
    End Sub
    
    Private Sub Command2_Click()
       MsgBox "You clicked me"
       Me.Show
    End Sub
    
    Private Sub Command3_Click()
       Command1.Enabled = False
       Command3.Enabled = False
       Command2.SetFocus
       Me.Caption = "Pausing  for 10 sec."
       Pause 10
       MsgBox "Pause timed out"
       Command1.Enabled = True
       Command3.Enabled = True
    End Sub
    
    Private Sub Form_Load()
       Command1.Caption = "Sleep 10 sec"
       Command2.Caption = "Click Me!"
       Command3.Caption = "Pause 10 sec"
    End Sub
    Last edited by CDRIVE; Dec 29th, 2009 at 09:23 PM. Reason: Add Module code
    <--- Did someone help you? Please rate their post. The little green squares make us feel really smart!
    If topic has been resolved, please pull down the Thread Tools & mark it Resolved.


    Is VB consuming your life, and is that a bad thing??

  17. #17

    Thread Starter
    Junior Member
    Join Date
    Dec 2009
    Location
    Netherlands, Europe
    Posts
    21

    Re: How to check if wave file stopped playing

    Thanks a lot guys, the .Refresh did the trick, it works just like I would like it to. Great!!! I'll have another good look at the difference between Pause and Sleep Chris.

    How would you incorporate a timer in the code in post #13 Ed? If it is wise to avoid Sleep I will but I don't quite know how to do that. Please keep in mind that the wave file will have a variable length of somewhere between 1 and 60 seconds.
    Last edited by Floyd; Dec 29th, 2009 at 07:54 PM. Reason: last sentence added

  18. #18
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: How to check if wave file stopped playing

    Quote Originally Posted by Floyd View Post
    Thanks a lot guys, the .Refresh did the trick, it works just like I would like it to. Great!!! I'll have another good look at the difference between Pause and Sleep Chris.

    How would you incorporate a timer in the code in post #13 Ed? If it is wise to avoid Sleep I will but I don't quite know how to do that. Please keep in mind that the wave file will have a variable length of somewhere between 1 and 60 seconds.
    I already told you how to do that. Measure the playing time of the .Wav files in advance. Set the timer accordingly. You avoid Sleep by using the timer instead. Did you look at this code?
    Code:
    Dim StartTime As Double, ElTime As Integer
    Private Sub Form_Load()
    StartTime = Now
    Timer1.Interval = 500 ' accurate to within 1/2 second
    End Sub
    
    Private Sub Timer1_Timer()
    ElTime = (Now - StartTime) * 86400
    If ElTime > 18 Then ' Playing time of .Wav file is 18 seconds, right Floyd?
        Command1.BackColor = vbWhite
        Timer1.Enabled =- False
    Else: Command1.BackColor = vbRed ' Sound file is through
    End If
    End Sub
    Replace "18" with the playing time of the .Wav files that you have. That is all there is to it, and I know that it works.
    Doctor Ed

  19. #19
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: How to check if wave file stopped playing

    Unless I am missing something the OP is trying to do..., I don't see why you would need to know the playing length ahead of time, why not just check if it's still playing at an inrterval of say every 1/2 second or so using a timer?

    Code:
    Private Sub Command3_Click()    
        ' <snip code above>
        TX3.BackColor = vbRed
        Timer1.Interval = 500 ' check playing status every 1/2 sec.
        Timer1.Enabled = True ' enable timer    
    End Sub
    
    Private Sub Timer1_Timer()
        If dsToneBuffer3.GetStatus <> DSBSTATUS_PLAYING Then
            Timer1.Enabled = False ' stop checking playing status
            TX3.BackColor = vbBlue ' change button color to blue
            MsgBox "End of sequence" ' show msg.
        End If    
    End Sub

  20. #20
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: How to check if wave file stopped playing

    Edge, I agree that works if the control can reveal that the track is currently playing. Some player controls cannot but they can reveal the length of the playing time in advance, once the .Wav file is opened. Regardless of which one you use, a timer control solves the problem--either to track the status or signal the end the procedure in a timely fashion.

    Excellent post.
    Doctor Ed

  21. #21

    Thread Starter
    Junior Member
    Join Date
    Dec 2009
    Location
    Netherlands, Europe
    Posts
    21

    Re: How to check if wave file stopped playing

    The Timer solution turns out to work but just one problem. By using a timer for some unknown reason the TX3 does not turn red anymore, eventhough the command is set before the timer starts. Even when I put a .refresh right after. Solve one problem, create another

    But I understand the indea of the timer, maybe I will have another go at it later. For the time being I stick to my For-Sleep-Next loop.

    I think we can consider this thread 'How to check if a wave file stopped playing' as Resolved and I will mark it correspondingly.

    Short resume: check if the sound buffer still has the status DSBSTATUS_PLAYING
    In my case:
    Code:
        If dsToneBuffer.GetStatus <> DSBSTATUS_PLAYING Then
        MsgBox "File stopped playing"
        End If
    Thank you Edgemeal, Code Doc, CDRIVE, VBClassicRocks for your contributions!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width