BASS_FX_DX8_REVERB and stopping playback

Started by Couin,

Couin

Hi :)

I'm trying to reproduce in a small test project, the problem here, but like I mentionned, it reveals another question.

If I stop the playback before the end of file, the reverb stops too.

Is it possible to keep reverb running to process the sound after stop?
BASS_ATTRIB_TAIL flag is already set.

Thanks :)

Ian @ un4seen

If you're only playing one stream on the device (or multiple streams with reverb enabled on all of them) then you could apply the reverb effect to the device output instead of individual stream(s). Like this:

devstream = BASS_StreamCreate(0, 0, 0, STREAMPROC_DEVICE, 0); // get device stream
reverbfx = BASS_ChannelSetFX(devstream, BASS_FX_DX8_REVERB, 0); // set reverb on it

If you're playing the stream(s) through a mixer then you could similarly set the reverb effect on the mixer, and set the BASS_MIXER_NONSTOP flag on it to keep it going after its sources stop.

Couin

Hi Ian :)

Thanks for answer.

But I apply reverb only for one or few streams (jingles) and not others.
Applying reverb on the output device or mixer would make all streams (jingles) reverbing.

Ian @ un4seen

In that case, another possibility is to just mute the stream via BASS_ATTRIB_VOLDSP instead of stopping it:

BASS_ChannelSetAttribute(handle, BASS_ATTRIB_VOLDSP, 0);

Assuming the reverb effect has a lower "priority" setting than BASS_ATTRIB_VOLDSP_PRIORITY, that means the stream's data is silenced and then the reverb is applied.

Couin

Is it possible with BASS_ChannelSlideAttribute(channel, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1, fadeoutvalue); for example ?
Because if I take back my code, I use this to fade out jingles with individual  fade out duration (fadeoutvalue).

Ian @ un4seen

If fading-out the reverb (and original sound) will be fine then you could indeed use BASS_ChannelSlideAttribute and BASS_ATTRIB_VOL. Otherwise, BASS_ATTRIB_VOL won't do what you want because it's applied after the reverb. BASS_ATTRIB_VOLDSP can be applied before the reverb, leaving the reverb unaffected.

Couin

Hmm, I understand better :)
I will see what I can do with this.

Couin

Hi :)

I changed some code, so, when I want to "stop" a jingle, it compares the fadeout duration with reverb duration.
If reverb duration is superior to fadeout duration, I use the BASS_ATTRIB_VOLDSP method. Else, I use the  BASS_ChannelSlideAttribute and BASS_ATTRIB_VOL method.

When BASS_ATTRIB_VOLDSP is used, OK the reverb does not stop, but the playback too (even if it is at volume 0).
So I added a sync to stop the playback @actual position (when we clic on the button) + reverb duration.
Call BASS_ChannelSetSync(Jing(btnum).Strm, BASS_SYNC_POS Or BASS_SYNC_ONETIME, _
BASS_ChannelGetPosition(Jing(btnum).Strm, BASS_POS_BYTE) + _
BASS_ChannelSeconds2Bytes(Jing(btnum).Strm, Jing(btnum).Reverb / 1000), AddressOf StopSync, 0)    ' set sync to trigger stop

And the StopSync function:
Public Sub StopSync(ByVal handle As Long, ByVal channel As Long, ByVal Data As Long, ByVal user As Long)

1        On Error GoTo Error_Routine

2        Call BASS_ChannelStop(channel) 'stop the stream

Exit_Routine:
3        Exit Sub
Error_Routine:
4        Debug.Assert False
5        ErrorLog "modClick.StopSync"
6        Resume Exit_Routine
End Sub


As you can see, I use the BASS_SYNC_ONETIME flag, so the StopSync should be used one time. But if I play again the jingle, without manually stopping it, it stops at the previous stop position.

I had to add a BASS_ChannelRemoveSync command at the "Play" function to not having unwanted stop.

Is there something I missed?

Ian @ un4seen

I suspect the issue there is that the sync isn't getting called the first time because its position has already past at the time of the BASS_ChannelSetSync call. Note that BASS_ChannelGetPosition gives you the position that's currently heard (unless you use the BASS_POS_DECODE flag) but the decoding/processing may be ahead of that due to buffering. Try adding the BASS_POS_DECODE flag to the BASS_ChannelGetPosition call. Assuming the jingles are quite short, it'd probably also be fine to just leave them playing muted to the end?

If you need to replay a jingle, remember to reset the BASS_ATTRIB_VOLDSP value to 1.0 before restarting it.

Couin

Hi Ian :)

I tested with BASS_POS_DECODE flag, this make no difference with ou without, both returns the same position.
If I read the documenta(tion about this flag, its seems that it has no effect on decode channels, and I thing this is the case because channel has decode flag (because of sent to a mixer).

Yes, about retablishing VOLDSP before playing, that is already what I do :)

For short jingles (or jingles stopped near from their end, I will implent a calculation of how much time remaining, and if setsync point falls after the end, just do not set this sync unnecessary.

Ian @ un4seen

Ah. If the jingles are decoding channels (BASS_STREAM_DECODE set) then the BASS_POS_DECODE flag indeed won't make a difference to the BASS_ChannelGetPosition call because that'll always return the decoding position anyway. To confirm whether a ONETIME sync is being called more than once, please try logging the "handle" parameter (containing the sync handle) in each StopSync call, and check if the same handle appears multiple times.

Couin

Hi Ian,

Sorry about ONETIME flag, it was an user (me !) mistake  :-[
I had in head, that sync was counted one time since we set it, but in fact, it is counted only at function calling (StopSync in the present case).
So I was testing to fast, and in my app, clicking again while sound if fading out (ou reverbering), forces Stop. I was not waiting the StopSync event, that explains why the sync point was already there.
If I wait well that StopSync if called, the sync point is well removed by ONETIME flag.
For my app, it stays more sure to remove the sync point before playing, to prevent unwanted stopping.

Thanks again for great help :)