MATLAB: Cross Correlation (xcorr) of Two simultaneously Recorded Audio Signals Always return randomly different lags? Help!!

Audio Toolboxcross correlationDSP System Toolboxlocalizationmicrophonemicrophone-arraysSignal Processing Toolboxsoundsoundlocalizationxcorr

Hi everyone! I'm working on a sound localization project in which I record two audio signals simultaneously and then take their 'cross correlation' to find out the "lags" existing between the two signals! But what happens is that every time a random angle is calculated because of the abrupt values of the lags each time! I don't know where I'm going wrong! Please guide me if there is a better approach to achieve a better sound localization ! The code is given as follows:
if true
fs = 48000 ; %sampling frequency in Hz
recObj1 = audiorecorder(fs, 16, 1, 1);
recObj2 = audiorecorder(fs, 16, 1, 2);
record(recObj1);
record(recObj2);
pause(5); % record for 5 seconds simultaneously
stop(recObj1);
stop(recObj2);
out1 = getaudiodata(recObj1, 'int16');
out2 = getaudiodata(recObj2, 'int16');
L = out1 ;
R = out2 ;
t1 = (0:length(L)-1)/fs;
t2 = (0:length(R)-1)/fs;
figure;
plot(t1,L);
figure;
plot(t2,R);
threshold = 100;
k=1;
win =200 ;
[k max(L) max(R)]
if max(L)>th && max(R)>th %set power threshold
[c, lags] = xcorr(L, R);
[a1,b1] = max(L);
[a2, b2] = max(R);
[a3, b3] = max(c);
s = lags(b3);
time_delay = s/fs ;
disp(time_delay);
s = abs(s); % taking absolute of s
disp('Estimated angle');
c = 342; % avg speed of sound at room temperature
dis = 1 ; % mean distance between the two microphones
cal = ((time_delay*c)/dis) ;
if cal<-1
cal=-1;
elseif cal>1
cal=1;
end
ang =((acosd(cal))
disp(ang); %displays the angle of sound source due to these microphones
end

Best Answer

Hi Ali,
I work at MathWorks in the Audio System Toolbox team. I can't exactly replicate your experiement as I don't have your hardware, but I could notice a few possible sources of issues.
In your code you seem to be acquiring simultaneously from two different devices using the default audio drivers (typically DirectSound or WASAPI on Windows). That gives you no guarantee of synchronous acquisition for L and R. The two devices themselves may be triggered asynchronously by the operating system, giving you an arbitrary new delay between the two signals every single time you run your script.
The simplest guarantee of a synchronous acquisition comes from acquiring different channels of the same device, ideally using its ASIO driver instead of the default one. ASIO drivers guarantee synchronous multi-channel acquisition.
At a minimum, you should try something like the following, which gets L and R from the first two channels of the same device:
recObj = audiorecorder(fs, 16, 2, deviceID);
Even better, you may want to try audioDeviceReader object in Audio System Toolbox, which supports ASIO drivers and is routinely used out there for latency-sensitive acoustic measurements. See for example the first example from the reference doc page (Read from Microphone and Write to Audio File):
deviceReader = audioDeviceReader('Driver','ASIO','NumChannels',2);
setup(deviceReader);
fileWriter = dsp.AudioFileWriter('myTwoChannelRecording.wav');
disp('Recording...')
tic;
while toc < 5
acquiredAudio = deviceReader();
fileWriter(acquiredAudio);
end
disp('Recording complete.')
release(deviceReader);
release(fileWriter);
audioDeviceReader also gives you the ability to acquire whatever arbitrary pair of channels from your device through what we call channel mapping.
You'll find more detailed explanations on audio measurement latency under Audio I/O: Buffering, Latency, and Throughput.
I hope this helps.
Regards,
Gabriele.