Author Topic: Convenient method of crossfading/fadeout+fadein mixer stream with itself  (Read 133 times)

gosucherry

  • Posts: 16
Hello!
I'm struggling with a problem of crossfading a stream attached to mixer with itself. Why would I do that? It's because I want to "rewind" a stream from random point to random point. Obviously it would result in clicks, so I'm trying to find a way for crossfading the stream with itself. Currently I'm trying to use BASS_ChannelSlideAttribute with BASS_ATTRIB_VOL attribute, sadly without any success. I would like to ask, if there is any convenient way of acomplishing such thing? Fadeout+fadein can be achieved by the advices of : http://www.un4seen.com/forum/?topic=17280.0, but crossfade would be even better.
« Last Edit: 5 Jul '18 - 09:30 by gosucherry »

Ian @ un4seen

  • Administrator
  • Posts: 21124
To crossfade, you will need 2 streams: one fading-in and one fading-out. If you want to crossfade 2 positions from the same file then you could create a 2nd stream from the same file. You could have "playing" and "fading" stream handles, which get swapped when crossfading. For example, something like this:

Code: [Select]
DWORD newstream = fadestream;
BASS_ChannelSetPosition(newstream, seekpos, BASS_POS_BYTE); // set the 2nd stream to the new position
BASS_ChannelSetAttribute(newstream, BASS_ATTRIB_VOL, 0); // mute it
BASS_ChannelPlay(newstream, 0); // start it
BASS_ChannelSlideAttribute(newstream, BASS_ATTRIB_VOL, 1, fadems); // fade-in
BASS_ChannelSlideAttribute(playstream, BASS_ATTRIB_VOL, -1, fadems); // fade-out and stop current playback stream
// swap the handles
fadestream = playstream;
playstream = newstream;

If you're playing through a mixer then the above would need to be changed a bit, to something like this:

Code: [Select]
DWORD newstream = fadestream;
BASS_ChannelSetPosition(newstream, seekpos, BASS_POS_BYTE); // set the 2nd stream to the new position
BASS_ChannelSetAttribute(newstream, BASS_ATTRIB_VOL, 0); // mute it

BASS_ChannelLock(mixer, true); // lock the mixer to prevent mixing
BASS_Mixer_StreamAddChannel(mixer, newstream, 0); // start it
QWORD fadelen = BASS_ChannelSeconds2Bytes(mixer, BASS_ChannelBytes2Seconds(newstream, fadems/1000.0)); // get fade length in mixer bytes
BASS_MIXER_NODE nodes[2] = { // 2 envelope nodes for a fade-in
{0, 0}, // start at vol=0
{fadelen, 1} // end at vol=1
};
BASS_Mixer_ChannelSetEnvelope(newstream, BASS_MIXER_ENV_VOL, nodes, 2); // apply the envelope
// switch envelope vales for fade-out
nodes[0].val = 1;
nodes[1].val = 0;
BASS_Mixer_ChannelSetEnvelope(playstream, BASS_MIXER_ENV_VOL, nodes, 2); // apply the envelope
BASS_Mixer_ChannelSetSync(playstream, BASS_SYNC_MIXER_ENVELOPE | BASS_SYNC_ONETIME, 0, EnvelopeSyncProc, 0); // set sync at end of fade-out
BASS_ChannelLock(mixer, false); // unlock the mixer

// swap the handles
fadestream = playstream;
playstream = newstream;

...

void CALLBACK EnvelopeSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
BASS_Mixer_ChannelRemove(channel); // stop playing the stream
}

Please see the documentation for details on the mentioned functions.