= Measuring Sound Latency = This article describes how to measure both sound device latency and overall (end-to-end) latency of [http://www.pjsip.org/pjsua.htm pjsua]. The objective of the test is to measure the latency introduced by both the sound device and the [http://www.pjsip.org/pjmedia/docs/html/index.htm pjmedia] framework. == Requirements == You will need: * [http://www.pjsip.org/pjsua.htm pjsua] * a computer with microphone and loudspeaker (not headset) * {{{tock8.wav}}} WAV file attached. * a WAV waveform display/analyzer to visually see the latency (such as Cool Edit on Windows) * or {{{latency.c}}} file if you don't have WAV waveform analyzer program. This file is included in PJSIP version 0.9.5 and later in {{{pjsip-apps/src/samples}}} directory, or if you use older PJSIP you can find the {{{latency.c}}} file attached. == Setup == * You MUST make sure that the loudspeaker level is set high enough so that the output is fed-back to the microphone (i.e. we deliberately want to capture the audio echo) * Build pjsua and the latency.c == Measuring Sound Device Latency == This test will measure the total latency introduced by: * microphone and speaker device buffering (both in application layer, driver layer, and hardware itself) * conference bridge buffering Test method: * play a special WAV file to the speaker device, and simultaneously record WAV file * as the audio is played in the speaker, capture the signal in the microphone (i.e. similar to how sound echo is captured) * record the microphone capture to WAV file. By looking in the recorded WAV file we should be able to know the sound device latency by measuring the interval between the recording of original signal and recording of the echo signal. === Running the Test === Run pjsua: {{{ pjsua --no-tones --ec-tail 0 --clock-rate 8000 --snd-clock-rate 8000 --rec-file rec1.wav --play-file tock8.wav }}} Run this script all at once (i.e. copy these and paste it to pjsua): {{{ cc 0 0 cc 1 0 cc 1 2 cc 0 2 sleep 10000 cd 0 0 cd 1 0 cd 1 2 cd 0 2 q }}} The command above will play the tock8.wav file to the speaker over and over for 10 seconds, while at the same time both the WAV file and the microphone signal will be recorded to {{{rec1.wav}}} file. === Analyzing the result with WAV analyzer === Here's what the recorded signal ({{{rec1.wav}}}) looks like in my WAV analyzer: [[Image(rec1.PNG, 50%)]] The highlighted area in above picture shows one recording of both original signal and the echo. If we zoom-in the highlighted area, it will look like this: [[Image(rec1-zoom.PNG, 50%)]] And to find out the latency, just measure the interval between original signal and echoed signal: [[Image(rec1-latency.PNG, 50%)]] In this test, I found out that the latency is approximately 171 milliseconds. === Analyzing the result with latency analyzer === If you don't have WAV waveform analyzer, you can measure the latency using {{{latency.c}}} application. {{{ C:\> latency.exe rec1.wav Latency average = 197 Latency minimum = 173 Latency maximum = 213 Number of data = 9 }}} As you can see above, measuring the latency this way has several advantages: * it's more automatic than manually measuring the latency with WAV analyzer. * it should measure the latency more precisely * it can measure the changes in the latency (as min, max, and average) as the buffers are adapting == Measuring Overall/End-to-end Latency == The objective of this test is to measure the overall latency of: * microphone and speaker device buffering (both in application layer, driver layer, and hardware itself) * conference bridge buffering * jitter buffering * codec buffering * and everything else Note that in order to measure the latency, we use loopback call for this test (meaning, the pjsua application is making call to itself), so this test method cannot be used to measure end-to-end latency of two pjsua instances. Test method: * make loopback call (i.e. pjsua is calling itself, so we have both caller and callee in the same pjsua instance) * arrange the conference bridge connection so that audio flow is one way (i.e. microphone -> call1 --> local network/OS --> call2 --> speaker) * play a special WAV file to caller, and simultaneously record WAV file * audio/RTP is received by callee, which will play the received the audio to speaker * as the audio is played in the speaker, capture the signal in the microphone (i.e. similar to how sound echo is captured) * record the microphone capture to WAV file. By looking in the recorded WAV file we should be able to know the sound device latency by measuring the interval between the recording of original signal and recording of the echo signal. === Running the Test === Run pjsua with the following command line arguments: {{{ pjsua --no-tones --ec-tail 0 --no-vad --clock-rate 8000 --snd-clock-rate 8000 --rec-file rec2.wav --play-file tock8.wav --add-codec pcmu }}} Then copy/paste the script below to pjsua: {{{ m sip:localhost sleep 100 ] a 200 sleep 1000 cd 0 4 cd 3 0 cd 0 3 cc 1 3 cc 1 2 cc 0 2 sleep 10000 cd 0 2 cd 1 2 q }}} The command above will make pjsua calls itself, answer the call, setup the conference bridge interconnection to record the WAV file, and do recording to 10 seconds. Once it's done, the recorded WAV file is in {{{rec2.wav}}} file. === Analyzing the result with WAV analyzer === Measuring the latency in the recorded WAV file is the same as in the previous test. Here's my {{{rec2.wav}}} looks like in the WAV analyzer: [[Image(rec2.png, 50%)]]] And in my measurement, I measured the delay is about 200 milliseconds. === Analyzing the result with latency analyzer === Again, similar like previous test, and here's my result: {{{ C:\> latency.exe rec2.wav Latency average = 213 Latency minimum = 183 Latency maximum = 227 Number of data = 9 }}}