| 132 | |
| 133 | === How can I reduce audio latency? === #audio-latency |
| 134 | |
| 135 | The end to end audio latency consists of the following components: |
| 136 | 1. The latency of the sound capture. |
| 137 | 1. Codec latency on both sender and receiver. |
| 138 | 1. Other algorithmic latency (such as AEC or sample rate conversion). |
| 139 | 1. Network latency. |
| 140 | 1. Jitter buffering on the receiver end. |
| 141 | 1. The latency of the sound playback. |
| 142 | |
| 143 | On typical PC, normally it's the sound device and jitter buffer that contribute the most latency, so this article will try to present how to optimize these settings. Codec latency is determined by the codec algorithm and its {{{ptime}}}, but normally it shouldn't add too much latency; maybe around 20 to 30 ms. The default resampling algorithm in PJMEDIA adds about 5 ms latency. I have no idea about AEC latency. Network latency, well, we can't do nothing about it. |
| 144 | |
| 145 | ==== Optimizing Jitter Buffer Latency ==== |
| 146 | |
| 147 | The jitter buffer parameters are specified in {{{pjsua_media_config}}}, with the relevant fields are: |
| 148 | - '''jb_min_pre''' - Jitter buffer minimum prefetch delay in msec. With the default settings, it will use the hard-coded value in {{{stream.c}}}, that is '''60''' ms. |
| 149 | - '''jb_max_pre''' - Jitter buffer maximum prefetch delay in msec. With the default settings, it will use the hard-coded value in {{{stream.c}}}, that is '''240''' ms. |
| 150 | - '''jb_max''' - Set maximum delay that can be accomodated by the jitter buffer msec. The default value is also hard-coded in {{{stream.c}}}, that is '''360''' ms. |
| 151 | |
| 152 | You can tweak these jitter buffer settings according to your latency requirement. But please remember that the jitter buffer is not only used to accommodate network jitter, but also the jitter in the transmission by the sender. PJMEDIA for example, uses the sound device clock to drive its RTP transmission, and depending on the sound device clock accuracy, it may not [#tx-timing transmit RTP packets in timely manner], thus this needs to be accommodated by the receiver's jitter buffer. |
| 153 | |
| 154 | ==== Optimizing Sound Device Latency ==== |
| 155 | |
| 156 | The default sound device back-end in PJMEDIA is [http://www.portaudio.com PortAudio]. !PortAudio itself supports several types of host APIs, depending on the platform: |
| 157 | - On Windows, it supports both !DirectSound and WMME. |
| 158 | - On Linux, it supports both ALSA and OSS. |
| 159 | - On MacOS X, it supports !CoreAudio |
| 160 | - etc. |
| 161 | |
| 162 | On Windows, !DirectSound will have much better latency than WMME, so try to use !DirectSound device if possible. Unfortunately, with PJSIP version 0.7.0, WMME will be used by default. But this subsequently has been fixed with ticket #384, so version later than 0.7.0 will use !DirectSound if it is available (on Windows, that is). |
| 163 | |
| 164 | !PortAudio !DirectSound has the default buffering latency set to '''120''' ms. This can be overridden by application, by setting {{{PA_MIN_LATENCY_MSEC}}} environment variable. |
| 165 | |
| 166 | We can measure the sound device end-to-end latency using ''pjsua'', by doing this experimentation: |
| 167 | 1. For this experiment, it's important to use speaker rather than headset, since we want the speaker signal to be captured by the microphone. |
| 168 | 1. Run ''pjsua'' with this command line arguments: |
| 169 | {{{ |
| 170 | pjsua_vc6 --ec-tail 0 --rec-file latency.wav |
| 171 | }}} |
| 172 | 1. On ''pjsua'' menu, loop-back the microphone to the speaker, and record the microphone signal: |
| 173 | {{{ |
| 174 | >>> cc 0 0 |
| 175 | >>> cc 0 1 |
| 176 | }}} |
| 177 | 1. Then tap on the microphone. You should hear it being played to the speaker too. |
| 178 | 1. Quit the application: |
| 179 | {{{ |
| 180 | >>> q |
| 181 | }}} |
| 182 | |
| 183 | Using WAV file waveform display, open {{{latency.wav}}} and measure the delay between the ''tap'' being captured by microphone and its echoed signal. This is the overall (microphone and speaker) delay of the sound device. |
| 184 | |
| 185 | On my system, an IBM X23 laptop running Windows 2000 Professional, !PortAudio !DirectSound with default settings has about 320 ms latency. Setting {{{PA_MIN_LATENCY_MSEC}}} environment variable to 20 ms will result in reduction of the latency to about 220 ms, which is consistent with the setting. |
| 186 | |
| 187 | With WMME backend, the overall latency is about 464 ms, using default settings. It seems that !PortAudio sets the buffering latency to 200 ms for both input and output, in {{{paDevInfo->defaultLowInputLatency}}}. Unfortunately I don't know how to override this setting in application (setting {{{PA_MIN_LATENCY_MSEC}}} environment variable doesn't seem to change the latency). But if you want to change this setting, you can change PJMEDIA's {{{pasound.c}}} and hard-code {{{inputParam.suggestedLatency}}} and {{{outputParam.suggestedLatency}}} to your requirement (for example, {{{0.020}}}). I have experimented with setting these to {{{0.020}}}, and it reduced the latency to about 254 ms. |
| 188 | |
| 189 | Your mileage may vary, of course. |