Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
_SNDPLAYCOPY is very handy for repeating a sound needed from multiple sources (sprites, etc..) at the same time, such as multiple gunshots or other sounds from various sources. However, there is no way to stop sounds initiated with _SNDPLAYCOPY that I'm aware of.
Perhaps another sound command such as:
_SNDSTOPCOPY could be considered by the developers?
I realize I can use _SNDCOPY to create a new handle and concurrently play it. However, one would need to keep track of all those handle copies and then cycle through them all with _SNDSTOP. Take a game like Robotron 2084 that has hundreds of sprites creating many identical sounds and you'll see where I'm going here.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 2,700
Threads: 327
Joined: Apr 2022
Reputation:
217
Not to say it's a bad idea or anything, but how the heck would one implement it?
Let's say me hero has a zappy gun. I load the "pew pew" sound file.
I fire off three zaps.
_SNDPLAYCOPY "pew pew"
_SNDPLAYCOPY "pew pew"
_SNDPLAYCOPY "pew pew"
Now, the second one hits the enemy. How would _SNDSTOPCOPY know to stop that second "pew pew" and not the first or third? Wouldn't it need a handle to specify which sound to actually stop?
And if it does, then wouldn't it basically be the exact same as _SNDCOPY?
How could you ever specify which copy to stop, without a handle, and if you have a handle, why wouldn't the existing commands already handle the issue?
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
08-07-2024, 04:57 AM
(This post was last modified: 08-07-2024, 04:58 AM by TerryRitchie.)
(08-07-2024, 12:58 AM)SMcNeill Wrote: Not to say it's a bad idea or anything, but how the heck would one implement it?
Let's say me hero has a zappy gun. I load the "pew pew" sound file.
I fire off three zaps.
_SNDPLAYCOPY "pew pew"
_SNDPLAYCOPY "pew pew"
_SNDPLAYCOPY "pew pew"
Now, the second one hits the enemy. How would _SNDSTOPCOPY know to stop that second "pew pew" and not the first or third? Wouldn't it need a handle to specify which sound to actually stop?
And if it does, then wouldn't it basically be the exact same as _SNDCOPY?
How could you ever specify which copy to stop, without a handle, and if you have a handle, why wouldn't the existing commands already handle the issue? I'm suggesting that _SNDSTOPCOPY would stop all copies of a sound playing at once. Yeah, I agree, managing which copy to stop would be just the same as manually keeping track of sound copy handles using _SNDCOPY.
What I'm running into is when a level of a game has been completed, for example, all of those copies of sound keep right on humming along with no way to instantly stop them. I try to keep these sound bites very short, a second or less, but even with that it's still difficult to time everything just right for a smooth transition to the next level. If a sound bite is over a second and gets copied a few times then it's completely unmanageable.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 734
Threads: 30
Joined: Apr 2022
Reputation:
43
Why wouldn't we use handles for this?
Tread on those who tread on you
Posts: 372
Threads: 23
Joined: May 2022
Reputation:
56
I think _SNDSTOPCOPIES may be a good idea. A fair amount of complexity is involved in getting this done on the BASIC side using arrays, _SNDCOPY & _SNDCLOSE. There is no way to stop and dispose of copies until it finishes playing. Also, the C++ side implementation is trivial.
Maybe we can have this in 3.15 when we make more audio-specific improvements.
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
08-07-2024, 03:14 PM
(This post was last modified: 08-07-2024, 03:15 PM by TerryRitchie.)
(08-07-2024, 02:48 PM)a740g Wrote: I think _SNDSTOPCOPIES may be a good idea. A fair amount of complexity is involved in getting this done on the BASIC side using arrays, _SNDCOPY & _SNDCLOSE. There is no way to stop and dispose of copies until it finishes playing. Also, the C++ side implementation is trivial.
Maybe we can have this in 3.15 when we make more audio-specific improvements. Thank you for considering this.
Oh yeah, that's right, as you point out _SNDCOPY will make another instance in RAM than needs to be removed with _SNDCLOSE. More overhead that I didn't consider.
(08-07-2024, 11:17 AM)SpriggsySpriggs Wrote: Why wouldn't we use handles for this? _SNDPLAYCOPY doesn't return a handle but instead handles all sound management internally.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 2,180
Threads: 222
Joined: Apr 2022
Reputation:
104
I looked into this four or five years ago, and everyone who says it is no easy task, especially to be done the right way, with handles, is absolutely correct. The only Mickey Mouse way around it is to have a second QB64 routine running the sound, that the primary routine kills as soon as you want the sound to stop. You can run that second instance invisible with _screenhide. I haven't tried this method I'm suggesting, but in theory it should work, unless the sound was magically able to complete itself when the app gets killed, which I doubt, but I'm not certain. Now the timing for such a construct might be a bit wacky. I wouldn't rely on SHELL to start the music, but would rather SHELL the second program open at the start, and either communicate with TCP/IP or a continuously monitored database to start the music. Shell with TASKKILL is pretty fast and direct at killing an app, so hopefully not much lag in getting the music to stop.
Pete
- My 2-cents and a big bag of 8066 chips.
Shoot first and shoot people who ask questions, later.
Posts: 303
Threads: 10
Joined: Apr 2022
Reputation:
44
I haven't tested this code, but wouldn't something like this work?
Code: (Select All)
ReDim HandleCache(20) As Long
Sub PlaySound (handle As Long)
For i = 1 to UBOUND(HandleCache)
If HandleCache(i) <= 0 _OrElse Not _SndPlaying(HandleCache(i)) Then
_SndClose HandleCache(i)
HandleCache(i) = _SndCopy(handle)
_SndPlay HandleCache(i)
Exit Sub
End If
Next
ReDim HandleCache(UBOUND(HandleCache + 1)) As Long
HandleCache(UBOUND(HandleCache)) = _SndCopy(handle)
_SndPlay HandleCache(UBOUND(HandleCache))
End Sub
Sub KillSounds ()
For i = 1 to Ubound(HandleCache)
If HandleCache(i) > 0 Then
_SndClose HandleCache(i)
HandleCache(i) = -1
End If
Next
End Sub
And then you just replace the `_SndPlayCopy` calls with `PlaySound` calls and call `KillSounds` when you're done. It's not super pretty but it doesn't seem all that bad overall.
Posts: 733
Threads: 103
Joined: Apr 2022
Reputation:
14
(08-07-2024, 03:14 PM)TerryRitchie Wrote: (08-07-2024, 02:48 PM)a740g Wrote: I think _SNDSTOPCOPIES may be a good idea. A fair amount of complexity is involved in getting this done on the BASIC side using arrays, _SNDCOPY & _SNDCLOSE. There is no way to stop and dispose of copies until it finishes playing. Also, the C++ side implementation is trivial.
Maybe we can have this in 3.15 when we make more audio-specific improvements. Thank you for considering this.
Oh yeah, that's right, as you point out _SNDCOPY will make another instance in RAM than needs to be removed with _SNDCLOSE. More overhead that I didn't consider.
(08-07-2024, 11:17 AM)SpriggsySpriggs Wrote: Why wouldn't we use handles for this? _SNDPLAYCOPY doesn't return a handle but instead handles all sound management internally. Is it possible to tweak _SNDPLAYCOPY to return a handle?
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
(08-07-2024, 05:57 PM)madscijr Wrote: (08-07-2024, 03:14 PM)TerryRitchie Wrote: (08-07-2024, 02:48 PM)a740g Wrote: I think _SNDSTOPCOPIES may be a good idea. A fair amount of complexity is involved in getting this done on the BASIC side using arrays, _SNDCOPY & _SNDCLOSE. There is no way to stop and dispose of copies until it finishes playing. Also, the C++ side implementation is trivial.
Maybe we can have this in 3.15 when we make more audio-specific improvements. Thank you for considering this.
Oh yeah, that's right, as you point out _SNDCOPY will make another instance in RAM than needs to be removed with _SNDCLOSE. More overhead that I didn't consider.
(08-07-2024, 11:17 AM)SpriggsySpriggs Wrote: Why wouldn't we use handles for this? _SNDPLAYCOPY doesn't return a handle but instead handles all sound management internally. Is it possible to tweak _SNDPLAYCOPY to return a handle? You would still need to manage all those returned handles with an array.
_SNDPLAYCOPY internally copies a new instance of the sound, plays it, then removes the new instance. The grunt work is already being handled by _SNDPLAYCOPY since it needs to keep track of all those new handles. A new command such as _SNDSTOPCOPIES could simply use that internal list created by _SNDPLAYCOPY to stop all the copied associated handles.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
|