Ableton Link Sequencer demo made in JUCE


#1

Hi guys,

I’ve just finished a demo of using Ableton Link with JUCE, feel free to have at it. It works for the most part and I tried as hard as possible to use all link features in the shortest amount of code possible (350 lines only).
Heres the repo with prebuilt binary (Windows).
https://github.com/ianacaburian/AbeLinkolnsJuce

There’s a few things I’m unsure about however which I wouldn’t mind some help on if anyone’s out there with Link experience.
Basically, I’m intermittently getting some skipped/missing beats which I cannot replicate. On top of that, it sounds a little out of sync in some setups but I can’t be sure if it’s just in my head. The only thing I can think of is that I’m performing the suggested “Latency Compensation” incorrectly which causes issues when beat changes occur on samples at the buffer boundaries (Ableton stresses a particular concept of doing it found here and overview here):

using Micros = std::chrono::microseconds;
auto output_host_time = link->clock().micros();
output_host_time += Micros{ llround(micros_per_sample * current_device->getOutputLatencyInSamples()) };

This is pretty much guesswork on my end because Ableton doesn’t have an example of how to do this other than to do it manually for an asio driver (which I’m assuming JUCE does this behind the scenes with getOutputLatencyInSamples. Here is Ableton’s example of how they do it manually with ASIO which is found in this file. I have tried it this way but I get the same results (or so I think) just using getOutputLatencyInSamples() provided by JUCE:

  long inputLatency, outputLatency;
  result = ASIOGetLatencies(&inputLatency, &outputLatency);
  if (result != ASE_OK)
  {
    fatalError(result, "ASIOGetLatencies");
  }
  std::clog << "Driver input latency: " << inputLatency << "usec"
            << ", output latency: " << outputLatency << "usec" << std::endl;

  const double bufferSize = driverInfo.preferredSize / driverInfo.sampleRate;
  mEngine.mOutputLatency =
    std::chrono::microseconds(llround(outputLatency / driverInfo.sampleRate));
  mEngine.mOutputLatency += std::chrono::microseconds(llround(1.0e6 * bufferSize));

Would really appreciate if someone could have a play around my demo to confirm any unusual behaviour (should know within seconds). To test Link, you can have Ableton or some other app in the background on the same machine or same LAN and it should pick up as soon as you click Link.

Otherwise, you have a free project to play around with, enjoy!

Thanks for any help guys.
Cheers.