Why Cross Correlation (xcorr) of Two simultaneously Recorded Audio Signals Always return randomly different lags? Help!!
7 次查看(过去 30 天)
显示 更早的评论
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
0 个评论
采纳的回答
Gabriele Bunkheila
2018-1-16
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.
3 个评论
Gabriele Bunkheila
2018-1-17
Hi Ali,
Sorry to hear that! Indeed ASIO drivers are the ones used by most professional applications and support for them within the MATLAB toolboxes only comes with Audio System Toolbox. Audio System Toolbox is available for all types of licenses, including for schools, students and home use. I hope you can find a viable way to add it to your installation.
Regards,
Gabriele.
更多回答(1 个)
Jeffrey Noe
2019-4-11
Thank you for your guidance Gabriele! I've also been working on this problem.
Following your advice, I'm using a multi-channel audio interface (Behringer U-PHORIA UMC404HD) and the Audio System Toolbox. Here's what I've found. The numbers and drivers I mention here may be different for other users.
When the "deviceReader" object is instantiated as follows,
deviceReader = audioDeviceReader('Driver','ASIO','NumChannels',2);
I've found that there are 22-27% fewer samples than there should be. This can be found by the following code:
[y, Fs] = audioread(fileName);
sampleDifference = Fs * recordDuration - length(y)
percentDifference = sampleDifference / (Fs * recordDuration) * 100
With an error of this magnitude, audio localization cannot be done. Instead, if "deviceReader" is instantiated with the "Device" specified (Behringer provides a driver on their website in my case), the "sampleDifference" is reduced substantially! It can be fine-tuned by also using the "SamplesPerFrame" parameter.
deviceReader = audioDeviceReader('Driver', 'ASIO', 'Device', 'UMC ASIO Driver','NumChannels', 2, 'SamplesPerFrame', 128);
I've found that by making this change, "percentDifference" can be consistently reduced to 0.01%!
I would also recommend closing any non-essential applications, turning all wireless devices off (Wi-Fi, Bluetooth, etc), and increasing the priority of Matlab. In Windows 10, this is done through the Task Manager.
![Screenshot (9).png](https://www.mathworks.com/matlabcentral/answers/uploaded_files/213059/Screenshot%20(9).png)
This final step is helpful when using 3-pin audio devices that have ground, positive and negative wires. The positive and negative wires both carry audio but have opposite polarities to cancel noise from outside interference. Testing has revealed that each microphone will have different noise characteristics. Their polarities will reduce the ability to accurately find the number of samples between audio reception at microphone 1 and microphone 2, which is found by performing cross-correlation on the two inputs.
A simple fix is to find the absolute values of the two inputs for use when performing cross-correlation.
[y, Fs] = audioread(fileName);
y = abs(y);
Below is the script up to the point of cross-correlation.
%Close all figures and clear variables
close all
clear
%Set up the device reader
fileName = 'myTwoChannelRecording.wav';
deviceReader = audioDeviceReader('Driver', 'ASIO', 'Device', 'UMC ASIO Driver','NumChannels', 2, 'SamplesPerFrame', 128);
setup(deviceReader);
fileWriter = dsp.AudioFileWriter(fileName);
%Record the audio
recordDuration = 5;
disp('Recording...')
tic;
while toc < recordDuration
acquiredAudio = deviceReader();
fileWriter(acquiredAudio);
end
disp('Recording complete.')
%Release system resources
release(deviceReader);
release(fileWriter);
%Read the audio file
[y, Fs] = audioread(fileName);
y = abs(y);
%Show the difference between the number of expected samples and the number
%of actual samples
sampleDifference = Fs * recordDuration - length(y)
percentDifference = sampleDifference / (Fs * recordDuration) * 100
%Separate the audio into left and right channel
leftAudio = y(:,1);
rightAudio = y(:,2);
%Perform the cross-correlation and plot the result
[xCorrResult, lag] = xcorr(leftAudio, rightAudio);
Fixing these errors has taken me quite some time, so I hope this helps others work through some of these issues. A good explanation of acoustic localization can be found at the YouTube video here: Where did that come from? An introduction to Sound Localisation.
1 个评论
A.J. Beckmann
2023-4-3
Jerfferey,
How do I know which value to use for SamplesPerFrame? My audiodevice is sampling at 48KHz.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Measurements and Spatial Audio 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!