Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Stopping _SNDPLAYCOPY ?Possible?
#1
_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.
There are two ways to write error-free programs; only the third one works.
QB64 Tutorial
Reply
#2
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?
Reply
#3
(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.
There are two ways to write error-free programs; only the third one works.
QB64 Tutorial
Reply
#4
Why wouldn't we use handles for this?
Tread on those who tread on you

Reply
#5
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. Wink
Reply
#6
(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. Wink
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.
There are two ways to write error-free programs; only the third one works.
QB64 Tutorial
Reply
#7
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.
Fake News + Phony Politicians = Real Problems

Reply
#8
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.
Reply
#9
(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. Wink
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?
Reply
#10
(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. Wink
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.
There are two ways to write error-free programs; only the third one works.
QB64 Tutorial
Reply




Users browsing this thread: 18 Guest(s)