| # Notes on Implementation |
| |
| ## Latency from Resampling |
| |
| There are two components of the latency. The resampler itself, and a buffer that |
| is used to adapt the block sizes. |
| |
| 1) The resampler is an FIR running at the target sample rate. So its latency is the number of taps. |
| From MultiChannelResampler.cpp, numTaps is |
| |
| Fastest: 2 |
| Low: 4 |
| Medium: 8 |
| High: 16 |
| Best: 32 |
| |
| For output, the device sampling rate is used, which is typically 48000.For input, the app sampling rate is used. |
| |
| 2) There is a block size adapter that collects odd sized blocks into larger blocks of the correct size. |
| |
| The adapter contains one burst of frames, from getFramesPerBurst(). But if the app specifies a |
| particular size using setFramesPerCallback() then that size will be used. |
| Here is some pseudo-code to calculate the latency. |
| |
| latencyMillis = 0 |
| targetRate = isOutput ? deviceRate : applicationRate |
| // Add latency from FIR |
| latencyMillis += numTaps * 1000.0 / targetRate |
| // Add latency from block size adaptation |
| adapterSize = (callbackSize > 0) ? callbackSize : burstSize |
| if (isOutput && isCallbackUsed) latencyMillis += adapterSize * 1000.0 / deviceRate |
| else if (isInput && isCallbackUsed) latencyMillis += adapterSize * 1000.0 / applicationRate |
| else if (isInput && !isCallbackUsed) latencyMillis += adapterSize * 1000.0 / deviceRate |