Author Topic: BASS_ChannelSetPosition Sync issue when using SYNCPROC  (Read 499 times)

djex81

  • Posts: 6
Hello

I'm trying to beat sync two songs. Right now I am testing with two identical test songs that I created in my audio software consisting of only a kick drum hitting on every beat. I am running into an issue when calling BASS_ChannelSetPosition for both songs in a SYNCPROC method. The two songs will not sync. However, if I call BASS_ChannelSetPosition on both songs using a button click for example both songs will sync perfectly. Why is there a latency when using BASS_ChannelSetSync from a SYNCPROC event? This is driving me crazy and I can not figure it out.

My example code is below:

Code: [Select]
SYNCPROC BeatSync;

public void Play() //PlayerA Play method
{
BeatSync = new SYNCPROC(onBeatSync);

long beatToSync = Bass.BASS_ChannelSeconds2Bytes(loadedTrack.GetStreamChannel(), (60f / 120f) * 8f); //Both songs are 120 bpm and im syncing at the 8th beat

Bass.BASS_ChannelSetSync(loadedTrack.GetStreamChannel(), BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_ONETIME | BASSSync.BASS_SYNC_MIXTIME, beatToSync, BeatSync, IntPtr.Zero);

BassMix.BASS_Mixer_ChannelPlay(loadedTrack.GetStreamChannel());

//Note: PlayerB is played at a random time after PlayerA play method is called in order to desync the two tracks so we can test syncing them
}

public void onBeatSync(int syncHandle, int channel, int data, IntPtr user)
{
//This DOES NOT sync

Sync();
}

public void Sync()
{
long beat1 = (60f / 120f) * 8f;
long beat2 = (60f / 120f) * 8f;

Bass.BASS_ChannelSetPosition(PlayerA.loadedTrack.GetStreamChannel(), beat1);
Bass.BASS_ChannelSetPosition(PlayerB.loadedTrack.GetStreamChannel(), beat2);
}

private void button5_Click(object sender, EventArgs e)
{
//This WILL sync

Sync();
}

Ian @ un4seen

  • Administrator
  • Posts: 22121
BASS_ChannelSetPosition will normally clear the stream's playback buffer, so that the new position is heard immediately. But it won't clear the playback buffer when it's called within a "mixtime" sync callback, to allow seamless custom looping. In your case, the sync callback is "mixtime" for one of the streams (the SYNCPROC's "channel" handle) but not the other. Try setting a separete sync on each of the streams, so that they both get a "mixtime" sync callback, and only call BASS_ChannelSetPosition on the sync's stream in there.

djex81

  • Posts: 6
BASS_ChannelSetPosition will normally clear the stream's playback buffer, so that the new position is heard immediately. But it won't clear the playback buffer when it's called within a "mixtime" sync callback, to allow seamless custom looping. In your case, the sync callback is "mixtime" for one of the streams (the SYNCPROC's "channel" handle) but not the other. Try setting a separete sync on each of the streams, so that they both get a "mixtime" sync callback, and only call BASS_ChannelSetPosition on the sync's stream in there.

Thank you for the reply. So I did as you suggested and set a SYNCPROC for both streams with only one of the SYNCPROC's doing the syncing and still there is desync. I even tried removing the mixtime flag as a test and it made no difference. Is there a way to clear the buffer manually?

As a test I played each stream at the same time. Both streams played in sync without issue. Then on the 8th beat the SYNCPROC fires and both streams go out of sync. It would be expected that they stay in sync if there was no latency issue. It's definitely something with calling BASS_ChannelSetPosition using a SYNCPROC.

djex81

  • Posts: 6
Ok so a quick update. If I pause the mixer channels then set their positions and then play them they will sync using SYNCPROC. This is not ideal though as I do not want to interrupt the first song that's playing in order to sync the second song. I will also note this only works when mixtime flag is not used.

I really don't want to create my own timer that would constantly check the channel position. Not even sure if that would be accurate enough. I would like to get SYNCPROC to work. Are there any other method of syncing two song positions together?


Ok so I ended up switching over to using BASS_Mixer_StreamAddChannelEx and delaying the start of the next song by a specific beat of the first song. This works great for two songs that have the same BPM. However if the songs are not the same BPM and I use BASS_ChannelSetAttribute on a tempo channel to change the one songs speed to match the other it causes issues. I am using the WaveForm class to find the first beat in the songs using the cue in position but when I change the tempo the first beat is no longer in the same position causing a slight desync. How can I determine the first beat of a tempo modified channel?
« Last Edit: 20 Apr '19 - 00:56 by djex81 »

Ian @ un4seen

  • Administrator
  • Posts: 22121
BASS_ChannelSetPosition will normally clear the stream's playback buffer, so that the new position is heard immediately. But it won't clear the playback buffer when it's called within a "mixtime" sync callback, to allow seamless custom looping. In your case, the sync callback is "mixtime" for one of the streams (the SYNCPROC's "channel" handle) but not the other. Try setting a separete sync on each of the streams, so that they both get a "mixtime" sync callback, and only call BASS_ChannelSetPosition on the sync's stream in there.

Thank you for the reply. So I did as you suggested and set a SYNCPROC for both streams with only one of the SYNCPROC's doing the syncing and still there is desync...

I meant that each SYNCPROC should only call BASS_ChannelSetPosition on its own stream, ie. the one in the SYNCPROC's "channel" parameter. That way the playback buffers of both streams do not get reset and they should stay in sync.

Ok so I ended up switching over to using BASS_Mixer_StreamAddChannelEx and delaying the start of the next song by a specific beat of the first song. This works great for two songs that have the same BPM. However if the songs are not the same BPM and I use BASS_ChannelSetAttribute on a tempo channel to change the one songs speed to match the other it causes issues. I am using the WaveForm class to find the first beat in the songs using the cue in position but when I change the tempo the first beat is no longer in the same position causing a slight desync. How can I determine the first beat of a tempo modified channel?

You can use BASS_FX_TempoGetRateRatio to modify positions according to a tempo adjustment.

Code: [Select]
new_beatpos = original_beatpos / BASS_FX_TempoGetRateRatio(handle);