22 May '13 - 23:35 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1]
  Reply  |  Print  
Author Topic: Synchronize Two Tracks  (Read 717 times)
Matthew
Guest
« on: 23 Apr '12 - 04:33 »
Reply with quoteQuote

Hello,

I'm looking into the functionality of BASS for my needs. I need to play two audio tracks simultaneously, perfectly sync'd together.  I also need to be able to separately control the volume on the two tracks.

My current solution is to put them both into a mixer, and then start and stop the mixer appropriately to keep them in sync. Will this reliably keep the tracks in sync? Assuming I don't shift their positions, will it be able to loop indefinitely?

Is there another, better solution to this problem?  When BASS claims it can "synchronize playback of multiple channels together," is there other functionality out there I'm missing?

Thanks in advance everyone!
Logged
Ian @ un4seen
Administrator
Posts: 15269


« Reply #1 on: 23 Apr '12 - 14:46 »
Reply with quoteQuote

Yes, using a mixer (via the BASSmix add-on) is guaranteed to keep the tracks in sync with each other, and they will remain so after looping (so long as the tracks have the same length). Regarding synchronized playback with BASS alone, there is the BASS_ChannelSetLink function, but note that is not guaranteed to start them perfectly in sync on Windows (it will on other platforms). So if you're using Windows, it is probably best to stick with the mixer method.
Logged
SoundMike
Posts: 252


« Reply #2 on: 3 May '12 - 08:14 »
Reply with quoteQuote

using a mixer (via the BASSmix add-on) is guaranteed to keep the tracks in sync with each other...

Is there any such guarantee when using multiple mixer streams? I have an instance with one of my customers where multiple music tracks are to be played in sync to 4 stereo outputs and 2 mono outputs, ie one file plays to the first stereo output, another file plays to the second stereo output, and so on. These physical outputs are connected to an external audio mixer. So in this scenario I create 6 mixer streams. When it comes time to play them, my program locks all 6 mixer streams, 'unpauses' the 6 source channels, and then unlocks the 6 mixer streams.

To lock and unlock the mixer streams I have a tight loop to try to do this as quickly as possible, but since the mixer streams are unlocked separately I guess I cannot guarantee perfect sync. Would it be feasible - and helpful - if BASS had a function that I could call to lock or unlock an array of channel handles? The theory is that by having a single function call to unlock all the mixer streams then hopefully BASS could guarantee syncing of these mixer streams.
Logged
Ian @ un4seen
Administrator
Posts: 15269


« Reply #3 on: 3 May '12 - 17:25 »
Reply with quoteQuote

Are all of the outputs on the same device and you're using SPEAKER flags to access them? If so, are you feeding them all through a master 10 channel mixer? If you are, you can lock that master mixer (rather than any sub-mixers) for synchronized changes to the mix, and it should all remain in sync.

If the outputs are entirely separate streams, then any changes won't necessarily be perfectly in sync across them, even with locking. If you want to synchronize changes in separate streams, "mixtime" BASS_SYNC_POS syncs could perhaps be used to get them in sync. For example, you could try something like this...

BASS_ChannelLock(mixer1, TRUE); // lock the mixers to prevent further processing
BASS_ChannelLock(mixer2, TRUE);
QWORD pos1=BASS_ChannelGetPosition(mixer1, BASS_POS_BYTE|BASS_POS_DECODE); // get the current processing positions
QWORD pos2=BASS_ChannelGetPosition(mixer2, BASS_POS_BYTE|BASS_POS_DECODE);
if (pos1==pos2) { // the mixers are at the same position
// apply changes to mixer1 and mixer2 here
} else if (pos1<pos2) { // mixer2 is ahead of mixer1
// apply changes to mixer2 here
BASS_ChannelSetSync(mixer1, BASS_SYNC_POS|BASS_SYNC_MIXTIME, pos2, ...); // set a sync to apply the changes on mixer1
} else { // mixer1 is ahead of mixer2
// apply changes to mixer1 here
BASS_ChannelSetSync(mixer2, BASS_SYNC_POS|BASS_SYNC_MIXTIME, pos1, ...); // set a sync to apply the changes on mixer2
}
BASS_ChannelLock(mixer1, FALSE); // unlock the mixers
BASS_ChannelLock(mixer2, FALSE);

If the change that you want to apply is adding a source, then BASS_Mixer_StreamAddChannelEx could be used to do that instead of a sync, ie. with the "start" parameter set accordingly.

Note this won't necessarily keep things in sync if the devices that the mixers are using are going at slightly different rates; things get even more tricky then!
Logged
SoundMike
Posts: 252


« Reply #4 on: 4 May '12 - 02:39 »
Reply with quoteQuote

Thanks, Ian. They are entirely separate streams as this customer is using a device with DirectSound outputs published by the driver as stereo pairs. And since this a single physical device then there shouldn't be an issue regarding 'different rates'.

In your code for applying changes to a mixer that's ahead of another mixer, I presume the recommended approach is to slow down the mixer that's ahead, by adjusting the BASS_ATTRIB_FREQ until they're back in sync? Should this setting be applied to the mixer channel or to the source channel?
Logged
Ian @ un4seen
Administrator
Posts: 15269


« Reply #5 on: 4 May '12 - 14:36 »
Reply with quoteQuote

Yep, if the devices are on the same hardware, I think there's a good chance that they will be going at the same rate and so they hopefully won't drift apart over time. If they were to drift apart, then you would indeed manipulate the BASS_ATTRIB_FREQ settings to bring them back together. An updated LIVEFX example (which could be recording and playing on 2 separate devices) was included in the BASS 2.4.9 package to demonstrate doing that sort of thing.

Regarding the code above, the difference in the mixer positions won't necessarily be due to the devices going at different rates. Note that it's checking the processing/decoding position (via the BASS_POS_DECODE flag) rather than the output position. The mixers are unlikely to be processed at exactly the same time, ie. they won't necessarily begin their update cycles simultaneously. For example, if one mixer starts processing 1ms later than the other, then it would have another 1ms of space in its output buffer that it can fill, and so its processing would be 1ms ahead of the other mixer after the update cycle. The use of the POS sync (or BASS_Mixer_StreamAddChannelEx) is to delay the change on the mixer that's behind, until it reaches the same position as the change was applied to the other mixer.
Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines