Trying to use audiorecorder for impulse response testing in a for loop
3 views (last 30 days)
Show older comments
Hi everyone,
I'm trying to test the impulse response of a microphone that i have attached to a rotary device connected to an arduino board. Basically trying to automate getting the impulse response at different angles. Thing is, I can't get the audiorecorder function to work properly within the for loop. It only gives me the impulse response for the final iteration. The rest has no values.
Goal is to play a white noise, record the data from mic using audiorecorder, do my ffts and iffts for impulse response, rotate by a certain angle and repeat the process.
My code is below. Any help would be greatly appreciated because I'm at a complete standstill on what to do here.
close all
clear all
% Parameters
fs = 44100; % Sampling frequency
dur = 30; % Duration of recording in seconds
dt = 1/fs; % Time step
% Create time vector for plotting
time = 0:dt:dur-dt;
% Generate white noise for the entire duration
noise=randn(dur*fs,1);
ramp_up = 0:0.01:1;
ramp_up=ramp_up';
ramp_down= 1:-0.01:0;
ramp_down=ramp_down';
noise(1:length(ramp_up))=noise(1:length(ramp_up)).*ramp_up;
noise(end-length(ramp_down)+1:end)=noise(end-length(ramp_down)+1:end).*ramp_down;
noise=noise./max(noise);
recObj = audiorecorder(fs, 24, 2, 2);
%Arduino Setup
clear dcm sm shield a;
a = arduino('COM5','Uno','Libraries','Adafruit\MotorShieldV2');
shield = addon(a,'Adafruit\MotorShieldV2');
addrs = scanI2CBus(a,0);
sm = stepper(shield,2,200);
sm.RPM = 3;
Angle = 45; %Rotation Angle
n_rot = 180 / Angle; %Number of Rotations
IM_L=1000; % Truncated impulse response length in number of data points
LS_IR=zeros(n_rot,IM_L);
nfft = 96000; % FFT size
df = fs / nfft; % Frequency resolution
faxis = df:df:nfft*df; % Frequency axis
nFreq=length(faxis);
%Initializing data storage
nSamples = fs * dur;
allData_mic = zeros(nSamples, n_rot);
allData_spk = zeros(nSamples,n_rot);
allIR = zeros(nFreq, n_rot);
allIR_trunc=zeros(IM_L, n_rot);
allfrf=zeros(nFreq/2,n_rot);
allfrf_trunc=zeros(IM_L,n_rot);
%for i = 1:1
for i = 1:n_rot+1
%recording
sound(noise, fs);
% Record two-channel microphone input (24-bit, 2 channels)
recordblocking(recObj, dur); % Record for specified duration
% Get recorded data (two channels)
recordedData = getaudiodata(recObj);
spkinput = recordedData(:, 1); % First channel: Speaker
microphoneInput = recordedData(:, 2); % Second channel: Microphone
microphoneInput = microphoneInput./0.0462;%Left Ear (Fixed)
%microphoneInput = microphoneInput./0.0630;%Right Ear
%% FFT
nav = floor(length(spkinput) / nfft) * 2 - 1; % Number of averages
% Initialize accumulators for power spectral densities and cross-spectral density
G1 = zeros(nfft, 1); % Power Spectral Density of Speaker
G2 = zeros(nfft, 1); % Power Spectral Density of Microphone
G12 = zeros(nfft, 1); % Cross-Spectral Density between Microphone 1 and Microphone 2
G21 = zeros(nfft, 1);
% Loop through the signal with 50% overlap and apply FFT
for i = 1:nav
p1 = 1 + nfft * (i - 1) * 0.5; % Start index for the current block
p2 = p1 + nfft-1; % End index for the current block
% Apply Hann window to the blocks
win=hann(length(spkinput(p1:p2))); % Create a Hann window for the current segment
% Applying windows to blocks
spk_win = win.*spkinput(p1:p2); % Mic1 input
mic_win = win.*microphoneInput(p1:p2); % Mic2 input
% FFT of the windowed blocks
Xf = fft(spk_win, nfft); % FFT of Mic1
Yf = fft(mic_win, nfft); % FFT of Mic2
G1 = G1 + Xf .* conj(Xf); % PSD of Speaker input
G2 = G2 + Yf .* conj(Yf); % PSD of Microphone recording
G12 = G12 + Xf .* conj(Yf); % CSD between Microphone and Speaker
G21=G21 + Yf.*conj(Xf);
end
G1 = 2*G1(1:nfft/2)./(nfft*nfft*nav);
G2 = 2*G2(1:nfft/2)./(nfft*nfft*nav);
G12 = 2*G12(1:nfft/2)./(nfft*nfft*nav);
G21 = 2*G21(1:nfft/2)./(nfft*nfft*nav);
% Compute Coherence Function
coherence = abs(G21).^2 ./ (G1 .* G2);
% Compute Frequency Response Function (FRF)
frf = G2./G12; % FRF
magdB=20*log10(abs(frf));
%% Impulse Response
IR = ifft(frf,nfft);
IR_trunc=IR(1:IM_L);
%impulse_time = (0:nfft-1) * dt;
% n_samp=length(frf);
% impulse_time= 0:dt:(length(microphoneInput1)-1)*dt;
%store everything to the two vectors made above
allData_spk(:, i) = spkinput;
allData_mic(:, i) = microphoneInput;
allIR (:,i) = IR;
allIR_trunc (:,i)= IR_trunc;
allfrf (:,i) = frf;
filenameOut = sprintf('HeadTesting_Baseline_27Jan_%ddeg.mat', ((i-1)*5));
%Movement-----------
% - moves it to the left (counterclockwise) (standing behind it)
% + moves it to the right (clockwise) (stangind behind it)
if i~=n_rot+1
move(sm, +50*Angle);
end
end
clear dcm sm shield a;
0 Comments
Answers (1)
William Rose
on 28 Jan 2025
I do not have an Arduino, and the only audio devices are the built-in speakers and microphone on my PC. (I know they work, because I use them frequently for zoom meetings.) I commented out the Arduino-specific parts of your code. I reduced duration from 30 s to 2 s, and I increased Angle from 45 to 90, so that the outer loop would run 3 times instead of 5, for faster run times. The modified script ran without error. I could easily hear the white noise audio when it ran.
% recObj = audiorecorder(fs, 24, 2, 2);
recObj = audiorecorder(fs, 24, 2)
I added lines to display the mean and standard deviation of each audio channel after each recording.
sound(noise, fs); % play signal
recordblocking(recObj, dur); % record for specified duration
recordedData = getaudiodata(recObj); % transfer data to array
fprintf('Mean(recordedData)=%.3e %.3e\n',mean(recordedData))
fprintf('StDv(recordedData)=%.3e %.3e\n',std(recordedData))
The means and SDs equaled 0.000 on each pass through the outer loop.
Mean(recordedData)=0.000e+00 0.000e+00
StDv(recordedData)=0.000e+00 0.000e+00
I changed the bit depth from 24 to 16.
% recObj = audiorecorder(fs, 24, 2)
recObj = audiorecorder(fs, 16, 2)
Then the means and SDs were no longer zero.
Mean(recordedData)=1.384e-09 -6.920e-09
StDv(recordedData)=1.461e-05 1.462e-05
I conclude that my system cannot record at 24 bits, but it can do 16 bits. You could check for the same.
1 Comment
William Rose
on 28 Jan 2025
You have an inner and an outer loop both using index i. Change one of them to j.
I plotted the |FRF| and coherence on each of the three passes. (I have three passes, not five, since I set Angle=90.) See figure below. The coherence is between 0 and 1, which is reassuring.

The X and Y in these calculations are the two microphone input channels. You refer to them as speaker and microphone.
spkinput = recordedData(:, 1); % First channel: Speaker
microphoneInput = recordedData(:, 2); % Second channel: Microphone
However, they are both microphones, at least on my system, and probably on yours. The relatively flat FRF, and relatively high coherence, indicates that the two mics are hearing the same thing. Which is not surprising. A more interesting frequency response function, in my opinion, is from the signal sent to the speaker ("noise") to either microphone signal.
See Also
Categories
Find more on Audio Processing Algorithm Design in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!