Latency measure audio delays for multiple channels

Latency is the time delay between when one initiates something and when it happens.

There are several places in the SC architecture where latencies occur:

1. Interpreter latency:

the time between entering a command and the time it is executed in the client (sclang).

This depends on how much code it is and how complex the calculations are.

For many cases, it is near zero.

// a function that does nothing runs really fast

bench({ nil });

// filling a big array with random numbers takes a while longer.

bench({ Array.rand(100000, 0.0, 1.0) });

// different operations may take different times

bench({ 1000000.do { 3.sqrt.cos } });

bench({ 1000000.do { 12.squared } });

2. Network latency:

sclang and scserver communicate via network (OpenSoundControl, usually UDP, or also TCP/IP);

until a network packet sent from sclang to the server arrives, an undetermined time passes.

On the same machine, with little other network traffic, this is typically ca. 0.02 seconds, depending mainly

on the server's hardware buffer size. This can be measured with:

s.boot;

s.ping(10, 0.1);

// compare

s.options.hardwareBufferSize;

s.options.hardwareBufferSize / s.sampleRate

The order in which packets arrive is not guaranteed, so in the worst case, one can end up sending a command to start a synth process, then set one of its controls to some value; if the order is accidentally reversed, trying to set e.g. frequency on a node which does not exist yet - which will complain (server - Node not found), and then start that node playing at the wrong pitch and staying there forever (because the failed command has happened already).

Therefore, one usually sets a latency value for the server, which is safely greater than the worst value measured/estimated (e.g. with s.ping). The default for this is 0.2 sec.

s.latency;

3. Audio I/O latency :

scsynth passes buffers (one block of numbers per channel) to the audio hardware;

the size of these buffers determines the time it takes between when a synth starts

internally and when it actually is heard.

The same goes for audio input too: input signals are passed to SC as blocks,

so there is some latency between when e.g. a trigger happens at the analog audio input,

and when it is detected with e.g. a Trig Ugen.

While this latency can be set directly with some utility software for audiocards,

such software may not consider all the factors:

E.g. the operating system itself, firewire or USB connections, and intermediate layers

like Jack may introduce extra buffering and thus extra delay somewhere along the line.

For multiple speaker setups, distances to the listening position may also introduce delays.

So it makes sense to measure audio latency. The *testAudio method generates pulses

on several output channels and measures time until each pulse registers again at an audio input.

Latency.initClass;

*testAudio(numChans, maxDT, server, inChan)

numChans: the number of audio channels to be measured

maxDT: the longest expected delay time to be measured

server: the server to be generating the test sound on

inChan: the input channel where the returning audio signal comes in,

typically, the mic input.

Latency.testAudio;

s.scope;