Optimizing Audio I/O Latency

To achieve the lowest latency possible without audio break ups, a combination of variables needs to be tweaked. The final values will be platform and system dependent, and will also depend on the complexity of the audio calculations performed. You need to adjust ksmps in the orchestra, as well as the software (-b) and harware buffer (-B) sizes.

Usually the simplest solution is the following:

  1. Set ksmps to a value with a good tradeoff between quality and performance, without adjusting -B at all.

  2. Set -b to a negative power of two of this value.

    To get the optimal values, start with something you think is going to be too low, ie -1, and then continue "upwards", -2, -4 and so on, until you stop getting x-runs (glitches). The real value of -b will be the absolute value of -b * ksmps.

  3. Reduce the hardware buffer (-B). Bring it down from the default (1024 on Linux, 4096 on Mac OS X, 16384 on Windows), halving it each time, until you start to get x-runs (glitches) again. Then take it back up again until performance is continuous.

This process assumes you have a 16-bit soundcard. If you have a 24-bit soundcard, then -B should be 3/2, or 3 times -b, rather than 2 or 4 times. Csound works with 32-bit floats, or 64-bit doubles whereas most soundcards are 16 or 24-bit integer. -b is the internal buffer, so it's dealing with the 32 or 64-bit side of things, whereas -B is the hardware buffer, so it's dealing with the 16 or 24-bit side. The csound default for floats is -B = 4 * -b. This is a sane value for a 16 bit card. You can usually get away with -B = 2 * -b, but this is the absolute minimum. For example, if you set -b1024 -B2048, csound will tell you that:

audio buffered in 1024 sample-frame blocks
      writing 4096-byte blocks to dac

4096 bytes is 32768 bits. 32768/32 = 1024, our sample-frame size, 1024 * 32/16 = 2048, our buffer size. Were we to reduce the value of -B, we would need to reduce the value of -b by a corresponding amount in order to continue to write 16-bit integers to dac. The minimum size of -b is (-B * bitrate)/32. That is to say that the minimum ratio of -b to -B should be:

While there is no theoretical maximum ratio, it makes no sense to have a very high ratio here, as the software buffer has to fill the hardware buffer before returning. If the ratio is high, it will take a long time, defeating the purpose of setting a small value for -b.

The value of -b is something that will need to be varied depending on the complexity of the instrument you're working with, but because it's intimately related to the value of ksmps, it's better to synchronise it with ksmps and go from there. One way to do it is to decide how long the release on your envelopes might need to be at maximum (for desired effect), set the release on all envelopes to maximum, give yourself a generous value for -b, and then play. If it breaks up, double ksmps, repeat until smooth, then bring the value of -b down as far as possible.

The value of -B is primarily determined by operating system and soundcard. Figure out (using above method) how low you can go, and use that value (or one higher for safety). If you have problems you'll know that it's probably because of an inappropriate value for ksmps, too low a value for -b, or denormals (see denorm).