Discussion:
Loop sound and multiple sounds...
(too old to reply)
DMS
2007-05-04 16:12:42 UTC
Permalink
Using calls directly to winmm to play wav or mp3 sound files works
fine. I can get a sound file to loop and I can get multiple sounds to
play at the same time by providing an alias.

I am not talking about the MM control in VB6, I am talking about
direct calls to winmm

What I cannot get to work is to have both, I want to play a sound as a
loop, and provide an alias so that I can play other sound files at the
same time.

_D_a_l_e___S_c_h_u_l_t_z_
Mike Williams
2007-05-04 19:04:31 UTC
Permalink
Post by DMS
What I cannot get to work is to have both, I want to play
a sound as a loop, and provide an alias so that I can play
other sound files at the same time.
I'm not sure how to do it using winmm.dll but it can be done using
quartz.dll, which is the ActiveMovie type library. You do not need a
control on your Form and quartz.dll is already installed and
registered on almost all systems, so all you need to do is set a
reference to it using Project / References in the VB IDE. You should
see it in the references lists as ActiveMovie control type library,
but if not then Browse for it in Windows/System32. I'm fairly new to
this type library myself, and there is almost certainly a better way
of looping a sound with it than the method I am using in the following
example, but it works okay. You can loop one (or more) sounds and you
can simultaneously play lots of different sounds at the same time
(simultaneously at the same time! I think I've had too much
Budweiser!). Also, it will play other files as well as wav files,
including midi and mp3 files and also movie files. Anyway, set a
reference as explained above and try out the following code (on a Form
with two Command Buttons and a Timer). You'll obviously need to change
the hard coded sound files to some that exist on your own system.

Mike

Option Explicit
Dim Player1 As New FilgraphManager
Dim Position1 As IMediaPosition
Dim Player2 As New FilgraphManager
Dim Position2 As IMediaPosition
Dim Player3 As New FilgraphManager
Dim Position3 As IMediaPosition

Private Sub Form_Load()
Player1.RenderFile "c:\american pie.mp3"
Player2.RenderFile "c:\spice.wav"
Player3.RenderFile "c:\tada.wav"
Set Position1 = Player1
Set Position2 = Player2
Set Position3 = Player3
Timer1.Interval = 100
Player1.Run
End Sub

Private Sub Command1_Click()
Position2.CurrentPosition = 0
Player2.Run
End Sub

Private Sub Command2_Click()
Position3.CurrentPosition = 0
Player3.Run
End Sub

Private Sub Timer1_Timer()
If Position1.CurrentPosition >= Position1.Duration Then
Position1.CurrentPosition = 0
Player1.Run
End If
End Sub
Alfie [UK]
2007-05-04 21:22:58 UTC
Permalink
Post by DMS
Using calls directly to winmm to play wav or mp3 sound files works
fine. I can get a sound file to loop and I can get multiple sounds to
play at the same time by providing an alias.
I am not talking about the MM control in VB6, I am talking about
direct calls to winmm
What I cannot get to work is to have both, I want to play a sound as a
loop, and provide an alias so that I can play other sound files at the
same time.
You say you're using winmm directly, I presume with mciSendString ?
Sounds like you're almost there if you can loop and use aliases.

Start by loading all your sounds using Aliases...

ret = mciSendString("open track1.mp3 Type MPEGVideo Alias Track1", 0&,
0, 0)
ret = mciSendString("open track2.mp3 Type MPEGVideo Alias Track2", 0&,
0, 0)
ret = mciSendString("open track3.mp3 Type MPEGVideo Alias Track3", 0&,
0, 0)

...then play them simultaneously and looping with...

ret = mciSendString("play Track1 repeat", 0&, 0, 0)
ret = mciSendString("play Track2 repeat", 0&, 0, 0)
ret = mciSendString("play Track3 repeat", 0&, 0, 0)

You can mix'n'match looping and non-looping tracks, for instance
background music and sound effects, start them at different times, play
segments of a sound, etc, quite easily, it only starts becoming complex
if you need to know when a sound has finished playing as you will need
to sub-class the MM_MCINOTIFY message.
--
Alfie [UK]
<http://www.delphia.co.uk/>
The problem with the gene pool is that there is no lifeguard.
DMS
2007-05-05 20:01:13 UTC
Permalink
thanks...

I found though that when playing a wav file, adding the keyword
"repeat" causes the call to play the sound to fail.

I think the repeat only works with MpegVideo and thus mp3 but not .wav
files...

Dale
http://remotesign.mixmox.com
Alfie [UK]
2007-05-05 23:07:21 UTC
Permalink
Post by DMS
thanks...
I found though that when playing a wav file, adding the keyword
"repeat" causes the call to play the sound to fail.
I think the repeat only works with MpegVideo and thus mp3 but not .wav
files...
Good point, now I remember why I usually work with MP3s in MCI.

MCI Command Post (www.geocities.com/smigman.geo/mci/mci.html) seems to
be closed at the mo, which is unfortunate as there are a ton of good
examples on there.

If you're comfortable with subclassing then you can subclass the
MM_MCINOTIFY call, but if you're looping several WAVs with different
timings you'll need to write some sort of handler to decide which one
needs to be kicked off again when the message is received.

The second to last answer at this forum
http://www.xtremevbtalk.com/archive/index.php/t-38312.html shows
subclassing for a single WAV.

Another option would be to check the length of each file at load and set
them off with timers but you may get audio artifacts due to differences
in timing.

I might be able to put together some basic examples if you let me know
what you are actually trying to achieve, for instance how many
simultaneous sounds, do they always loop, do you need to switch sounds
after one has finished, etc ?
--
Alfie [UK]
<http://www.delphia.co.uk/>
I married my wife for her looks...but not the ones she's been giving me lately!
DMS
2007-05-07 15:16:49 UTC
Permalink
Post by Alfie [UK]
Post by DMS
thanks...
I found though that when playing a wav file, adding the keyword
"repeat" causes the call to play the sound to fail.
I think the repeat only works with MpegVideo and thus mp3 but not .wav
files...
Good point, now I remember why I usually work with MP3s in MCI.
MCI Command Post (www.geocities.com/smigman.geo/mci/mci.html) seems to
be closed at the mo, which is unfortunate as there are a ton of good
examples on there.
If you're comfortable with subclassing then you can subclass the
MM_MCINOTIFY call, but if you're looping several WAVs with different
timings you'll need to write some sort of handler to decide which one
needs to be kicked off again when the message is received.
The second to last answer at this forumhttp://www.xtremevbtalk.com/archive/index.php/t-38312.htmlshows
subclassing for a single WAV.
Another option would be to check the length of each file at load and set
them off with timers but you may get audio artifacts due to differences
in timing.
I might be able to put together some basic examples if you let me know
what you are actually trying to achieve, for instance how many
simultaneous sounds, do they always loop, do you need to switch sounds
after one has finished, etc ?
--
Alfie [UK]
<http://www.delphia.co.uk/>
I married my wife for her looks...but not the ones she's been giving me lately!
Hi Alfie,

Thanks. I am concered about timing issues, and my application is
already pretty complex. It recieves TCPIP messages over a network and
some of these messages are requests to play certain sound files. I
would like to havethe option of also having these messages request
that the sound file loops. So I cannot predict which sound files will
be used nor when the requests will come in. If I loop a sound I need
to be able to provide an alias so that it can also be stopped by a
later request. In addition to incoming requests, my app is also firing
the playing of hundreds of very small sound files.

I have seen some code that subclasses the windows messages etc to get
a call back when the sound has finished playing, so that one can play
it again. That is somewhat similar to what I have done in thepast with
the MCI player control but I worry that there will be a gap betwwen
the sound iterations if my code is already very busy.

I suspect I should simply back off the Windows limitation of not
allowing loops with .wav files and only support looping with mp3
files.. :-(

Dale
http://remotesign.mixmox.com
Alfie [UK]
2007-05-10 00:36:18 UTC
Permalink
Post by DMS
Thanks. I am concered about timing issues, and my application is
already pretty complex. It recieves TCPIP messages over a network and
some of these messages are requests to play certain sound files. I
would like to havethe option of also having these messages request
that the sound file loops. So I cannot predict which sound files will
be used nor when the requests will come in. If I loop a sound I need
to be able to provide an alias so that it can also be stopped by a
later request. In addition to incoming requests, my app is also firing
the playing of hundreds of very small sound files.
Hundreds ? The soundcard itself will be limited in how many simultaneous
sounds it can play without using a pre-mixer of some sort (based upon
the number of hardware and software buffers).

MCI handles mixing for you but is still limited by the hardware/driver
support which can both vary widely and report it's capabilities
incorrectly (for instance Creative Audigy cards report their max
hardware buffers but do not report unused buffers [returning max
buffers] as the driver recycles them itself internally).
Post by DMS
I have seen some code that subclasses the windows messages etc to get
a call back when the sound has finished playing, so that one can play
it again. That is somewhat similar to what I have done in thepast with
the MCI player control but I worry that there will be a gap betwwen
the sound iterations if my code is already very busy.
With MCI there are 2 options;

Subclass the MM_MCINOTIFY message that is called whenever a sound (that
was played via MCI with the notify flag set) ends

Use an individual timer (not a good idea) or timer manager to call loop
logic whenever a sound is expected to end

Either method might have problems with lots of sounds, I've only used
both with 8-12 sounds.

Method: Subclassing

When the MM_MCINOTIFY message is sent you to use some logic, typically a
loop, to check the status of all playing sounds to see if they have
ended. If you have lots of sounds, particularly if some end at the same
time, you may miss some as their status hits end after you have checked
it.

Method: Timer Manager

You create a linked list by time to play (derived from checking play
length on load), you run a single multimedia timer (due to it's higher
precision over standard timers) and check the linked list on timer
events to see if any sounds are expected to have ended at that point
(you can also them use a limited status check of only those sounds
expected to have finished to see if they have actually finished).
Depending upon your timer increment you may miss some.

-
The timer manager method can probably handle more sounds at once as it
either doesn't have to check all playing sounds or can ignore checking
sounds that are expected to have finished based upon timing (although
this itself may cause artifacts if sounds did not quite finish or the
timing is not tight enough).

Either method is going to have trouble if your code is doing a lot of
other work as well though. Both methods may cause problems if they steal
focus from your main 'thread'.
Post by DMS
I suspect I should simply back off the Windows limitation of not
allowing loops with .wav files and only support looping with mp3
files.. :-(
Method 3:That would be another option, and might actually be the better
option for your app from what you've said. You let MCI handle the
looping and you can still stop sounds as you like from elsewhere. I
think the overhead of either a message or timer handler might cause more
problems than issues it resolves if you're handling hundreds of sounds.

The only other option is DirectSound, which let's you ignore some of the
hardware limitations, but it's really going to end up using similar
methods.

I'll try to trim out some basic samples of each method (excluding
DirectSound) but I'm not sure how they'll scale as I've not used them
for large amounts of sounds before.
--
Alfie [UK]
<http://www.delphia.co.uk/>
Youth is wasted upon the young...all that energy and no experience :).
DMS
2007-05-11 02:55:37 UTC
Permalink
Many thanks Alfie - this is great sounding advice!

Dale
http://remotesign.mixmox.com (with sound!)

Loading...