-
Notifications
You must be signed in to change notification settings - Fork 748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Latency compensation in scsynth & supernova #3790
Latency compensation in scsynth & supernova #3790
Conversation
this is not what I'd call a heated debate! It is really a friendly conversation on what might be the best solution.
There is only (very) accurate UTP-level time-stamp synchronzation in supercollider. We (unfortunately) have no means for sample level sync. Where exactly is the difference between scsynth and supernova? Both do support OSC bundles with time stamps, I had thought. What is it you corrected? |
Sorry I didn't mean that in a negative way at all ! I read with interest everyone's ideas. My apologies. Most audio applications use estimated audio latency to compute signals ahead of time so that the audio is produced just at the right moment (see PortAudio doc for example). For example you have a latency of 32ms and you want to produce a sound at a time T. If you start writing in the buffer at T you will hear the sound at T + 32ms. So by advancing the internal clock by 32ms, the buffer will be written ahead of time, and the audio will produced at T. That's what scsynth is doing, except that in the Jack backend the latency was subtracted instead of added, so the audio was computed late. This is also done in the Link demo |
Ah I see. I had supposed that not only for scsynth but also for supernova the scheduled time means the nanosecond (according to network time) when the signal hits the wire. Thanks for the fix! |
i feel like i would have a better grip on what this is doing if i had some test code. i'm not asking for a unit test, just a quick experiment to demonstrate the effect of this change. also, congrats on finding a |
@smiarx could you post a quick example of how you verified that it works? |
thanks @snappizz :). So I used two examples to test it. The first one checks that scsynth & supernova are in sync. (
~scsynth = Server(\scsynth, NetAddr("localhost", 57110));
~scsynth.waitForBoot{
~supernova = Server(\supernova, NetAddr("localhost", 57111));
Server.supernova;
~supernova.boot;
~scsynth.latency = 0.2; ~supernova.latency = 0.2;
}
)
(
SynthDef(\click, {
OffsetOut.ar(0, Impulse.ar(0, mul:0.6));
Line.kr(dur:0.01, doneAction:Done.freeSelf)
}).send(~scsynth).send(~supernova);
)
(
~pattern = Pbind(\instrument, \click);
Ppar([
Pbindf(~pattern, \server, ~scsynth),
Pbindf(~pattern, \server, ~supernova)
]).play();
) One can then use a recording tool to check the waveform of the output of the two servers. Before the fix supernova should be late by a time corresponding to the estimated latency (or the opposite for Jack). After the fix the clicks should be in sync. I also tested it against an external tool using the LinkClock branch. In my case I used linkhut from the Link demos, but I believe that any other Link metronome should do it. Note that the Jack version of linkhut use the wrong latency estimation, use this patch to make it use the Jack API estimated latency (same as scsynth). s.boot;
s.latency = 0.2;
l = LinkClock.new;
l.tempo = 1; // be sure that the tempo is 60 bpm on both sides
(
SynthDef(\click, {
OffsetOut.ar(0, Impulse.ar(0, mul:0.6));
Line.kr(dur:0.01, doneAction:Done.freeSelf)
}).add;
)
// I use the phase argument of Quant to compute ahead of time
// so that clicks happen right on time
Pbind(\instrument, \click).play(l, quant:[1, -0.2]); I get <1ms of latency between the two programs with the fix. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this works as expected and the code looks fine. thanks!
SC_PortAudio was left out!! |
There is currently a
heateddebate on the Ableton Link PR on how to implement accuratesample-levelsynchronization between instances. While doing some tests I noticed some inconsistencies regarding latency compensation in scsynth and supercollider for timestamped events: