Author Topic: independent volumes of a stereo channel  (Read 149 times)

dbaxter

  • Posts: 72
independent volumes of a stereo channel
« on: 14 Mar '23 - 15:20 »
Is there a way to independently raise and lower a channel volume outside of pan? I'd like to be able to have a stereo channel playing, then lower the volume of the left side faster than that of the right. Or, it gets messy when I start the channel, have right at 0, left at 100, fade out left, then try to raise only the right. The pan gets in the way and raises the left from 0 until the pan gets all the way right. Probably something obvious everybody should know - sorry.

Ian @ un4seen

  • Administrator
  • Posts: 25067
Re: independent volumes of a stereo channel
« Reply #1 on: 14 Mar '23 - 16:31 »
You can use a combination of BASS_ATTRIB_VOL and BASS_ATTRIB_PAN settings for separate left/right volume control, as described in this thread:

   http://www.un4seen.com/forum/?topic=17480

Another option is to use the BASS_FX add-on's BASS_FX_BFX_VOLUME effect. You would have 2 instances of that, with the "lChannel" parameter set to BASS_BFX_CHAN1 on one (left) and BASS_BFX_CHAN2 on the other (right). Note that this method will have higher latency because it'll be applied during decoding, not during final output mixing like BASS_ATTRIB_VOL/PAN is. That is unless you set the effects on the output mix, which you can get a handle for from BASS_StreamCreate with STREAMPROC_DEVICE.

dbaxter

  • Posts: 72
Re: independent volumes of a stereo channel
« Reply #2 on: 15 Mar '23 - 02:22 »
Thank you. Looking at the referenced posting, I may have the cart before the horse. Currently, to go from one volume and pan setting to another over time, I use BASS_CHANNEL_SLIDE_ATTRIBUTE on both vol and pan. Left and right for display then come from a call to CalcLRFromPanandVolume. If I understand correctly, you would drive L and R values outside of Bass and then feed them in via that function.

Ian @ un4seen

  • Administrator
  • Posts: 25067
Re: independent volumes of a stereo channel
« Reply #3 on: 15 Mar '23 - 14:45 »
Oh right, I see now that that you said you want to be able to slide the left/right levels at different speeds. That will indeed be tricky using BASS_ATTRIB_VOL+PAN. Still, you could try simply replacing the BASS_ChannelSetAttribute calls in the linked code with BASS_ChannelSlideAttribute and see if it works well enough for your purposes. If it doesn't then you may need to use a DSPPROC callback function (via BASS_ChannelSetDSP) instead for full control, which could look something like this:

Code: [Select]
float vol[2]; // wanted volume levels (left/right)
float volcur[2]; // current volume levels
float volinc[2]; // per-sample volume increments

void CALLBACK LeftRightVolDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
{
    float *data = (float*)buffer; // assuming floating-point data
for (int a = 0; a < length / sizeof(float); a++) {
if (volinc[a & 1] != 0) { // sliding
volcur[a & 1] += volinc[a & 1];
if ((volinc[a & 1] > 0 && volcur[a & 1] >= vol[a & 1]) || (volinc[a & 1] < 0 && volcur[a & 1] <= vol[a & 1])) { // reached target
volcur[a & 1] = vol[a & 1];
volinc[a & 1] = 0; // stop sliding
}
}
data[a] *= volcur[a & 1]; // apply volume to data
    }
}

When you want to change a volume level, you would set "vol" to the wanted level and "volinc" according to how fast you want it to get there:

Code: [Select]
vol[chan] = level;
volinc[chan] = (level - volcur[chan]) / samplerate / seconds;

dbaxter

  • Posts: 72
Re: independent volumes of a stereo channel
« Reply #4 on: 22 Mar '23 - 03:16 »
Yes, I was using the PanDSP function as illustrated in one of the demos (sorry, long time ago, don't know which one). From your response, I should  abandon that and also using BASS_ChannelSlideAttribute to do my volume changes on volume directly? Testing understanding.
And, BTW, it would be nice if someone could translate Ian's code to Delphi. I could translate his first response, but this last one is a bit more complicated. Thanks!

Ian @ un4seen

  • Administrator
  • Posts: 25067
Re: independent volumes of a stereo channel
« Reply #5 on: 22 Mar '23 - 13:49 »
Yes, I was using the PanDSP function as illustrated in one of the demos (sorry, long time ago, don't know which one). From your response, I should  abandon that and also using BASS_ChannelSlideAttribute to do my volume changes on volume directly? Testing understanding.

That PanDSP function is probably based on the example in the DSPPROC documentation? If so, I don't think it will help with individually sliding left/right volume controls.

You could first try just replacing the BASS_ChannelSetAttribute calls in the linked code (in the 1st reply) with BASS_ChannelSlideAttribute, and see if that works well enough for you. If it doesn't then I think you would need to use a DSP function like above. I'm not a Delphi user myself, so I'm unfortunately unable to provide a translation for that. But your PanDSP function should at least give you a starting point, eg. on accessing/modifying the data in the buffer.