|
-
Dec 28th, 2009, 02:49 AM
#1
Thread Starter
Junior Member
[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?
-
Dec 28th, 2009, 08:51 AM
#2
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
-
Dec 28th, 2009, 04:10 PM
#3
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
-
Dec 28th, 2009, 06:43 PM
#4
Thread Starter
Junior Member
Re: How to check if wave file stopped playing
 Originally Posted by Code Doc
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!
-
Dec 28th, 2009, 07:43 PM
#5
Re: How to check if wave file stopped playing
 Originally Posted by Floyd
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.
-
Dec 28th, 2009, 07:47 PM
#6
Re: How to check if wave file stopped playing
 Originally Posted by Floyd
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
-
Dec 28th, 2009, 08:01 PM
#7
Thread Starter
Junior Member
Re: How to check if wave file stopped playing
 Originally Posted by Code Doc
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?
-
Dec 28th, 2009, 08:13 PM
#8
Thread Starter
Junior Member
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?
-
Dec 28th, 2009, 08:38 PM
#9
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
-
Dec 28th, 2009, 09:00 PM
#10
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?? 
-
Dec 28th, 2009, 09:05 PM
#11
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.
-
Dec 29th, 2009, 11:15 AM
#12
Thread Starter
Junior Member
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?
-
Dec 29th, 2009, 05:15 PM
#13
Thread Starter
Junior Member
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?
-
Dec 29th, 2009, 05:57 PM
#14
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
-
Dec 29th, 2009, 06:04 PM
#15
Re: How to check if wave file stopped playing
 Originally Posted by Edgemeal
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.
-
Dec 29th, 2009, 06:06 PM
#16
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?? 
-
Dec 29th, 2009, 07:47 PM
#17
Thread Starter
Junior Member
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
-
Dec 29th, 2009, 08:08 PM
#18
Re: How to check if wave file stopped playing
 Originally Posted by Floyd
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.
-
Dec 29th, 2009, 08:21 PM
#19
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
-
Dec 29th, 2009, 08:51 PM
#20
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.
-
Dec 30th, 2009, 12:50 PM
#21
Thread Starter
Junior Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|