Author Topic: Perfect Syncronization  (Read 1586 times)

_undex

  • Posts: 7
Perfect Syncronization
« on: 7 Apr '14 - 12:45 »
Hi folks,

first of all, great job with the bass library, un4seen team. I love it ;D

So I'm trying to beatsync two (later more) tracks. I know their bpm and the position of their first beat.
First one track is playing. When the user gives input, the second track starts playing and alignes to the nearest beat.
Here is my code, so you can understand what i mean by that:

Code: [Select]
Bass.BASS_ChannelPause(tracks[first].stream);
long p = Bass.BASS_ChannelGetPosition(tracks[first].stream);
long last = GetLastBeat(p, first);
long next = GetNextBeat(p, first);
if(p - last < next - p)
{
     Bass.BASS_ChannelPlay(tracks[track].stream, false);
     Bass.BASS_ChannelPlay(tracks[first].stream, false);
     Bass.BASS_ChannelSetPosition(tracks[track].stream, launch + Bass.BASS_ChannelGetPosition(tracks[first].stream) - last);
     BassMix.BASS_Mixer_ChannelPlay(mixerhandle[track]);
     //tracks are perfectly aligned
}
else
{
     Bass.BASS_ChannelSetSync(tracks[first].stream, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME, next, sy, new IntPtr(by[1]));
     Bass.BASS_ChannelPlay(tracks[first].stream, false);
     //sync doesn't fire
}

...

void sync(int handle, int channel, int data, IntPtr user)
{
    int track = 0;
    int clip = 0;
    unsafe
    {
         track = (byte)user.ToInt32() / 0x10;
         clip = (byte)user.ToInt32() & 0x0f;
    }
    Bass.BASS_ChannelSetPosition(tracks[track].stream, tracks[track].launchpoints[clip].point);
    Bass.BASS_ChannelPlay(tracks[track].stream, false);
    BassMix.BASS_Mixer_ChannelPlay(mixerhandle[track]);
    Bass.BASS_ChannelRemoveSync(channel, handle);
}

tracks[first] is the playing track and tracks[track] is the track that I want to start. launch is the position in bytes where the track I want to start has its first beat.
I have two problems. The first is that I don't like that I have to pause/play the playing tracks if I want to sync the starting track (they are perfectly synced than), as this could lead to gabs.
I also have to pause all playing tracks, as I want all to be in sync.
The other problem is that the sync method only fires after I restart the track where the synchronization got set. And even then I get slight double beats.

Ian @ un4seen

  • Administrator
  • Posts: 20424
Re: Perfect Syncronization
« Reply #1 on: 7 Apr '14 - 16:33 »
There appears to be a mixer in your code, but you're not currently playing the tracks through it? If so, to get perfect synchronisation, I would suggest that you do play the tracks through the mixer. It shouldn't be necessary to pause existing tracks when starting a new one; you can instead lock the mixer to prevent it processing while you add the new track. Starting a new track might look something like this...

Code: [Select]
BASS_ChannelLock(mixer, TRUE); // lock the mixer
mixpos=BASS_ChannelGetPosition(mixer, BASS_POS_DECODE|BASS_POS_BYTE); // get the mixer's decoding position
// get next beat pos here
BASS_Mixer_StreamAddChannelEx(mixer, newtrack, 0, nextbeatpos-mixpos, 0); // add the new track with delay to next beat
BASS_ChannelLock(mixer, FALSE); // unlock the mixer

_undex

  • Posts: 7
Re: Perfect Syncronization
« Reply #2 on: 7 Apr '14 - 21:58 »
Hmm.. I thought that I have to use the ordinary ChannelPlay to use it with BassMix.
I implemented this method:

Code: [Select]
void PlayTrack(int stream, long start)
{
    Bass.BASS_ChannelLock(mixer, true);
    if(BassMix.BASS_Mixer_ChannelIsActive(stream) != BASSActive.BASS_ACTIVE_PLAYING)
    {
          BassMix.BASS_Mixer_StreamAddChannelEx(mixer, stream, BASSFlag.BASS_DEFAULT, start, 0);
          BassMix.BASS_Mixer_ChannelPlay(stream);
    } else
    {
          BassMix.BASS_Mixer_ChannelSetPosition(stream, start);
    }
    Bass.BASS_ChannelLock(mixer, false);
}

Unfortunatly nothing happens when I call it. I also can't solve my other problem. Even if I execute this

Code: [Select]
Bass.BASS_ChannelSetSync(tracks[first].stream, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME | BASSSync.BASS_SYNC_ONETIME, Bass.BASS_ChannelGetPosition(tracks[first].stream) + 44100, sy, new IntPtr(by[1]));

the sync method doesn't fire. Anyway, thank you for your reply.

Chris

  • Posts: 1810
Re: Perfect Syncronization
« Reply #3 on: 7 Apr '14 - 22:03 »
Remember if you are working with a Mixer you have to create the Stream with the BASS_STREAM_DECODE Flag

_undex

  • Posts: 7
Re: Perfect Syncronization
« Reply #4 on: 7 Apr '14 - 22:55 »
I set it to BASS_STREAM_DECODE, but now I'm only able to play one track at a time.
The other is active but I can't hear any output.

Ian @ un4seen

  • Administrator
  • Posts: 20424
Re: Perfect Syncronization
« Reply #5 on: 8 Apr '14 - 14:10 »
If you aren't already, please check the return values to find out if any calls are failing, and if any is, then use BASS_ErrorGetCode to get the error code and find out why it failed.

_undex

  • Posts: 7
Re: Perfect Syncronization
« Reply #6 on: 8 Apr '14 - 16:55 »
I solved both problems (I think).. One more question... how do I assign a Fx to one of the channels of my mixer?

Ian @ un4seen

  • Administrator
  • Posts: 20424
Re: Perfect Syncronization
« Reply #7 on: 8 Apr '14 - 17:08 »
You can use the channel's handle in a BASS_ChannelSetFX call to apply one of the ready-made effects to that channel. If you would like to apply your own effects, that can be done via BASS_ChannelSetDSP. Please see the documentation for details on those 2 functions.

_undex

  • Posts: 7
Re: Perfect Syncronization
« Reply #8 on: 8 Apr '14 - 18:23 »
Got it. Thanks for your help ;D I really appreciate it

_undex

  • Posts: 7
Re: Perfect Syncronization
« Reply #9 on: 8 Apr '14 - 21:18 »
 :'( it's me again. After I added a TempoFx to each channel, the ChannelSetSync method seems to fail.
I think the problem is that it takes time to process the ChannelSetSync method and in that time the position of the source stream is already behind the sync position.. So I tried to check right before I call ChannelSetSync if the stream is already behind the sync position, but that didn't help.

Ian @ un4seen

  • Administrator
  • Posts: 20424
Re: Perfect Syncronization
« Reply #10 on: 9 Apr '14 - 17:10 »
Please confirm what stream you're setting the sync on, and what you're using the sync to achieve. If you're using it to add a new track to the mix, then the sync should be set on the mixer, ie. at the position that you want the new track to start. BASS_ChannelGetPosition with the BASS_POS_DECODE flag can be used to get the mixer's current decoding/processing position, which the sync position should be ahead of.

_undex

  • Posts: 7
Re: Perfect Syncronization
« Reply #11 on: 9 Apr '14 - 22:04 »
Yes you're right, I add a channel in the sync. I use this method now:

Code: [Select]
Bass.BASS_ChannelSetSync(mixer, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME | BASSSync.BASS_SYNC_ONETIME,
    Bass.BASS_ChannelGetPosition(mixer, BASSMode.BASS_POS_DECODE | BASSMode.BASS_POS_BYTES)
    + next - Bass.BASS_ChannelGetPosition(tracks[first].stream, BASSMode.BASS_POS_DECODE | BASSMode.BASS_POS_BYTES), sy, new IntPtr(by[1]));

And I think it works :) Again, thank you very much. You helped me a lot.