mackron / miniaudio

Audio playback and capture library written in C, in a single source file.
https://miniaud.io
Other
4.07k stars 361 forks source link

It is not possible to receive sound end callback when sound is stopped with a fade. #719

Open Oldes opened 1 year ago

Oldes commented 1 year ago

It looks that ma_sound_end_proc callback is not fired when sound it stopped with a fade using ma_sound_stop_with_fade_in_pcm_frames

DEBUG: WASAPI backend is disabled.
DEBUG: DirectSound backend is disabled.
DEBUG: WinMM backend is disabled.
DEBUG: Attempting to initialize Core Audio backend...
DEBUG: System Architecture:
DEBUG:   Endian: LE
DEBUG:   SSE2:   NO
DEBUG:   AVX2:   NO
DEBUG:   NEON:   YES
INFO: [Core Audio]
INFO:   MacBook Air Speakers (Playback)
INFO:     Format:      32-bit IEEE Floating Point -> 32-bit IEEE Floating Point
INFO:     Channels:    2 -> 2
INFO:     Sample Rate: 44100 -> 44100
INFO:     Buffer Size: 441*3 (1323)
INFO:     Conversion:
INFO:       Pre Format Conversion:  NO
INFO:       Post Format Conversion: NO
INFO:       Channel Routing:        NO
INFO:       Resampling:             NO
INFO:       Passthrough:            YES
INFO:       Channel Map In:         {CHANNEL_FRONT_LEFT CHANNEL_FRONT_RIGHT}
INFO:       Channel Map Out:        {CHANNEL_FRONT_LEFT CHANNEL_FRONT_RIGHT}
Oldes commented 1 year ago

I guess that it is because the sound is stopped before reaching its end. Would it be possible to have a callback when sound is being stopped?

mackron commented 1 year ago

I didn't think a stop callback would be needed because since you just passed the details into the ma_sound_stop_with_fade_in_pcm_frames() function don't you already know when the sound is being stopped?

Oldes commented 1 year ago

Practically it would be quite complicated to deal with the time used in ma_sound_stop_with_fade_in_pcm_frames.

Maybe I should explain, why I wanted it. I am working on an integration of your lib to Rebol (scripting language). So far the sound is initialised in a memory, which is managed by Rebol. Rebol is using GC. When the sound handle is not referenced, it may be released. On release I call ma_sound_uninit.

Its is ok, when used in (Rebol) code like this, because there is the song reference:

song: play/stream %my-song.mp3

But when user would use just:

play/stream %my-song.mp3

there is no reference to the sound and when GC would be evaluated, the sound would be uninitialised and so not audible anymore. Trying to resolve this situation, I lock the Rebol sound handle when the sound is started (so it would not be GCed) and unlock when it is stopped. It is working except the case when the sound is stopped with the tween. It could be simulated in Rebol in code like:

stop/fade play/stream %my-song.mp3 0:0:10 ;; the song is faded out in 10s

In such a case the end callback is not fired and the handle is locked even when the song is not used and referenced anymore. I am aware that it is an edge case, but it is possible.

mackron commented 1 year ago

I'm not necessarily against this or anything. But there's a problem - I've changed the API for sound notification stuff in the dev-0.12 branch and I don't want to be adding this to 0.11.x only to break the API when I get 0.12 out. So if I do this, it won't be in before I release 0.12 which might be a ways away (no time frame).

I'll leave this open and mark it as a feature request.

Oldes commented 1 year ago

I think it is ok.. when playing a little bit more with your library, I think that having the stop callback would not be enough anyway... I must do a little bit more advanced memory management to deal with miniaudio resources... for example I must have some connection between ma_sound and data sources like ma_noise and so on. I also need some time to figure it out.