Author Topic: Using effects channels efficiently  (Read 224 times)

srylain

  • Posts: 18
Using effects channels efficiently
« on: 20 Nov '17 - 09:50 »
Because I'm using Bass.NET with a game, I need to be cautious about anything that could potentially drop performance. All I'm basically doing right now is creating the streams (up to 14 at once), and then enabling the Tempo effect on them so players can speed up/slow down the audio when they want to and I'll eventually want to add some other effects like reverb and pitch shifting. My main question, is it better or more efficient to have all the effects enabled at once when the audio is loaded and then edit their parameters when they change (they can change pretty often if the player decides to) or is it better to create the effects when they're needed?

The way I'm using the Tempo effect now, is that even if the audio is supposed to start at 100% speed it still creates the effect that way I can just change the tempo when I need to without having to create the effect each time the speed is changed. And for the other effects I was thinking of doing the same thing, and in the end each channel may have 3-4 effects running on them (although they may not all be modifying the output all at the same time). Is that a good way of using effects?

EDIT:

I've just tried to add a pitch shifteffect, and it appears to hard lock the game and causes a pretty big memory leak. This happens both with the channel already having the tempo effect and without. Hopefully I'm doing something wrong there, all I'm doing is stemChannel = Bass.BASS_ChannelSetFX(stemChannel, BASSFXType.BASS_FX_BFX_PITCHSHIFT, 0);
« Last Edit: 20 Nov '17 - 11:01 by srylain »

Ian @ un4seen

  • Administrator
  • Posts: 20433
Re: Using effects channels efficiently
« Reply #1 on: 20 Nov '17 - 15:20 »
The BASS_FX tempo processing is reduced when the tempo is unchanged, but there will still be some extra processing compared to not enabling the tempo effect. The problem with enabling/disabling the tempo processing mid-playback is that the transition won't be smooth. If that will be fine, then you could go ahead and do that.

Are you applying the same effect(s) to all of the streams? If so, the biggest efficiency saving would come from having a single instance of the effect(s) applied to all of them. You can achieve that by using a mixer, ie. plug the streams into the mixer and apply the effect(s) to the mixer. But note that a mixer can increase latency, eg. if you add a new file to the mix while the mix is already playing, then it won't be heard immediately due the mixer's playback buffer (see BASS_CONFIG_BUFFER). Depending on the platform your running on, you may be able to avoid that by enabling the BASS_ATTRIB_NOBUFFER option on the mixer.

Regarding the possible memory leak with BASS_FX_BFX_PITCHSHIFT, are you definitely freeing the effect or stream via BASS_ChannelRemoveFX or BASS_StreamFree afterwards, yet memory usage is getting higher each time? You can use the BASS_CONFIG_HANDLES option to quickly check for possible BASS channel leaks:

Code: [Select]
int handles = BASS_GetConfig(BASS_CONFIG_HANDLES); // get current number of HMUSIC/HRECORD/HSAMPLE/HSTREAM handles

srylain

  • Posts: 18
Re: Using effects channels efficiently
« Reply #2 on: 21 Nov '17 - 08:36 »
The hardlock and memory leak happens as soon as I create the effect. I've seen it hit somewhere close to 4GBs usage (when the game itself is usually around 200MB) within a couple seconds, and I'm completely sure I'm not running it inside of an infinite loop somewhere (I have a for loop that loads all the channels, and then after the for loop is when I tried to add the effect). It also happened the exact same when I tried applying freeverb and BASS_FX_DX8_REVERB.

In the end I don't think it'd be best if I were to use a Mixer and have a single instance of the effects, because eventually I'd like for each player to be able to modify their own audio with separate pitch shift and reverb effects.

Quote
The problem with enabling/disabling the tempo processing mid-playback is that the transition won't be smooth.

I have code that smoothes out the difference between the drift from the position Bass reports and the time since gameplay started, so while it is a bit jarring to have it happen during gameplay it's perfectly fine because the differences are minor enough that they're not that noticeable.

Ian @ un4seen

  • Administrator
  • Posts: 20433
Re: Using effects channels efficiently
« Reply #3 on: 21 Nov '17 - 16:40 »
Looking at the BASS_FX_BFX_PITCHSHIFT effect's source code, it does use a bit of memory but that gets freed when the effect is freed. So if there is a leak, I think it must be originating elsewhere. How many BASS channels are you applying the effects to, and did you try checking the BASS_CONFIG_HANDLES value to see if any are being leaked? You could check that after you have freed the BASS channels, to see if there are any left behind. If there is a leak, check/log the return value of all BASS_StreamFree calls to confirm whether they were successful. Such a leak could explain the BASS_FX_BFX_PITCHSHIFT leak too, ie. the effect's memory isn't being freed because its BASS channel isn't being freed (unless you use BASS_ChannelRemoveFX).

srylain

  • Posts: 18
Re: Using effects channels efficiently
« Reply #4 on: 22 Nov '17 - 10:34 »
EDIT: Pretty sure I found the problem. I assume that the returned effect handle is not the same as the handle returned from creating a tempo stream, so the channels aren't linking which is causing nothing to be played which causes songs to constantly keep loading, which explains the memory usage and the hardlock.

So if that's correct, do I need to keep track of the effect handles separately?
« Last Edit: 22 Nov '17 - 11:18 by srylain »

Ian @ un4seen

  • Administrator
  • Posts: 20433
Re: Using effects channels efficiently
« Reply #5 on: 22 Nov '17 - 13:50 »
An effect applied via BASS_ChannelSetFX is automatically freed when the BASS channel that it is applied to (used in the BASS_ChannelSetFX call) is freed, eg. when BASS_StreamFree is called. So you don't need to keep track of effect handles to prevent memory leaks, but you will usually want to keep them anyway to use in BASS_FXSetParameters calls.

BASS_FX_TempoCreate works differently and gives you a new stream handle (HSTREAM) rather than an effect handle (HFX). When using that, make sure the source BASS channel (used in the BASS_FX_TempoCreate call) is also freed when finished with it. You can have that happen automatically by using the BASS_FX_FREESOURCE flag. The previously mentioned BASS_CONFIG_HANDLES option can help detect any such leaks (it includes all HSTREAM handles).

srylain

  • Posts: 18
Re: Using effects channels efficiently
« Reply #6 on: 22 Nov '17 - 20:01 »
Alright, thanks for the help. I seem to have everything working now, it's crazy how well Bass works when you're doing everything correctly.