Author Topic: I3D£2Reverb with pybass  (Read 161 times)

cae_jones

  • Posts: 1
I3D£2Reverb with pybass
« on: 8 May '24 - 09:47 »
I'm using the sound_lib wrapper for pybass. When I try using the I3DL2Reverb effect, I get a couple issues.

One of these is the known issue where the effect lasts for the duration of the source. Sound_lib's wrapping obfuscates the underlying stream arrangements somewhat, but it shouldn't stop me from using pybass directly to try the mix-a-silent-stream-first trick, assuming that works with pybass (I don't see why it wouldn't, but I've been surprised by this sort of thing before).

More troublesome is that, even with the truncated, 100% wet result, changing the effect properties does nothing. No matter what, the result sounds exactly the same, as though the reverb is cranked up to just under the piercing-metallic-buzz threshold. From what I can tell, sound_lib is setting properties individually, while Bass would normally take the properties all at once, but I can't tell if that's causing the problem, or if there's something else I should look into.
Of course, there's also the matter of mixing the unaltered signal with the wet signal after all the above is resolved, but that seems like the simplest of the challenges, here.

So I suppose what I'm asking is:
  • Pybass can manage the dummy stream / add silence / whatever tricks to avoid truncated reverbs, right?
  • How do I actually get the effect properties to change, so as to evoke different environments?
  • Is there anything I should beware when it comes to mixing the wet and dry with pybass?

Help greatly appreciated.

Ian @ un4seen

  • Administrator
  • Posts: 25834
Re: I3D£2Reverb with pybass
« Reply #1 on: 9 May '24 - 15:37 »
I'm not familiar with pybass, so I'm afraid I can't advise on any specifics of that, but to answer your questions more generally...

Pybass can manage the dummy stream / add silence / whatever tricks to avoid truncated reverbs, right?

You can extend a stream via its BASS_ATTRIB_TAIL setting with BASS_ChannelSetAttribute.

How do I actually get the effect properties to change, so as to evoke different environments?

An effect's current parameters are available from BASS_FXGetParameters.

Is there anything I should beware when it comes to mixing the wet and dry with pybass?

You would probably use a DSP callback (DSPPROC) and a "dummy" (STREAMPROC_DUMMY) or "push" (STREAMPROC_PUSH) stream (with the same sample format as the source stream) for this. The reverb effect would be set on the dummy/push stream, and the DSP callback would send the data through that and then mix the result. Using a push stream, it could look like this (in C++):

Code: [Select]
fxstream = BASS_StreamCreate(freq, chans, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE, STREAMPROC_PUSH,  0); // create push stream
BASS_ChannelSetFX(fxstream, BASS_FX_DX8_I3DL2REVERB, 0); // set reverb effect on it
BASS_ChannelSetDSP(stream, EffectDSP, 0, 0); // set DSP function on playback stream

...

void CALLBACK EffectDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
{
float *data = (float*)buffer;
float *fxbuf = new float[length / 4]; // effect buffer
BASS_StreamPutData(fxstream, data, length); // pass the data to the effect host push stream
BASS_ChannelGetData(fxstream, fxbuf, length); // get back the effect output
for (int a = 0; a < length / 4; a++)
data[a] = dry * data[a] + wet * fxbuf[a]; // mix the original/dry and effect/wet
delete fxbuf;
}

Or like this using a dummy stream:

Code: [Select]
fxstream = BASS_StreamCreate(freq, chans, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE, STREAMPROC_DUMMY,  0); // create dummy stream
BASS_ChannelSetFX(fxstream, BASS_FX_DX8_I3DL2REVERB, 0); // set reverb effect on it
BASS_ChannelSetDSP(stream, EffectDSP, 0, 0); // set DSP function on playback stream

...

void CALLBACK EffectDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
{
float *data = (float*)buffer;
float *fxbuf = new float[length / 4]; // effect buffer
memcpy(fxbuf, data, length); // copy the data to the effect buffer
BASS_ChannelGetData(fxstream, fxbuf, length); // pass the buffer through the effect host dummy stream
for (int a = 0; a < length / 4; a++)
data[a] = dry * data[a] + wet * fxbuf[a]; // mix the original/dry and effect/wet
delete fxbuf;
}

Note this is assuming the stream is floating-point (BASS_SAMPLE_FLOAT). Please see the documentation for details on the mentioned functions.