record and analyse real-time audio

35 views (last 30 days)
For a project im working on i need to record audiodata from a microphone and analyse it simultaneously. I found some threads on mathworks but yet couldnt figure out how to do it.
I startet very basic with this:
fs = 8000 %or whatever suits best
recorder = audiorecorder(fs,24,1); %setting up the recorder
recordblocking(recorder,2); %record 2 secs
data = getaudiodata(recorder); %extract the recorded 2 secs
pitch(data,fs); %plot
This works fine for just 2 secs, but i cant find a way to do this with a 15 minute long recording, extracting every "new" 2 seconds...
From
i tried to obtain the function/timer combination but that didnt work.
I´d be glad to get some help,
thanks in advance!
  1 Comment
Jonas
Jonas on 28 Jun 2022
Edited: Jonas on 28 Jun 2022
please have a look into the audiodevicereader object. that object can read data much faster and buffer wise (e.g. 1024 samples). look into the documentation of it and come back if you need further assistance
if you have problems with lag, look into your drivers and in doubt, have a look into the Project Asio4all.

Sign in to comment.

Accepted Answer

jibrahim
jibrahim on 28 Jun 2022
Hi Oskar,
When working with real-time audio, you should consider audioDeviceWriter, audioDeviceReader and audioPlayerRecorder.
Here is a possible pattern:
fs = 8000; % Sample rate
% Create microphone object
adr = audioDeviceReader(SampleRate=fs);
% Create a buffer to save microphone samples
buff = dsp.AsyncBuffer(Capacity = fs*2.5);
numIterations = floor(15*fs/adr.SamplesPerFrame);
for index=1:numIterations % run as long as you want
% Read from the microphone
frame = adr();
% Save data to buffer
write(buff,frame);
% If you have enough data, do you analysis
if buff.NumUnreadSamples >= 2*fs
data = read(buff);
p = pitch(data,fs);
end
end
  5 Comments
Oskar Kilgus
Oskar Kilgus on 28 Jul 2022
Hey @jibrahim, as i´m working on and with the code i wondered why there is a constant "offset" of 0.02 seconds in the timescope. According to:
the timescope displays the time on the bottom right corner. When i run it, i "lose" 0.02 secs on every tick.
Is that caused by any properties/settings etc. or does it simply not count in full seconds and is just confusing?
Changing the SamplingRate in timescope properties simply changed the scaling of the x-axis...
Thanks in advance!
jibrahim
jibrahim on 28 Jul 2022
Hi Oskar,
I think this is due to how the pitch function works.
When you feed pitch a long audio signal, it computes pitch values on overlapped windows of audio. For example, if thw window length is 416 samples and the overlap length is 336 samples (defaults for fs=8000), the function generates an estimate for the first 416 samples of audio, then shifts the window by 416-336 = 80 samples, and computes an estimate for the window corresponding to samples 497:912, then shifts the window by 80 more samples, etc.
The first pitch estimate is based on 416 "new" samples, wheras all subsequent pitch estimates in the same function call correspond to 80 "new" samples, all the other samples coming from the previous window. So, the "update rate" of pitch computation is basically 80 samples (or 100 Hz), but not quite, because of the very first call. timescope thinks it is 100 Hz, but it is a little off on the first call, which explains this weirdness.
pitch was designed for "batch" scenarios primarly, not real-time scenarios.
You can either ignore this misleading time read-out, or you can alternatively use an ArrayPlot scope instead. It might not be as convenient as timescope, but it allows you to control the x-labels. For example:
fs = 8000; % Sample rate
% Create microphone object
adr = audioDeviceReader(SampleRate=fs);
% Create a buffer to save microphone samples
buff = dsp.AsyncBuffer(Capacity = fs*2.5);
numIterations = floor(15*fs/adr.SamplesPerFrame);
scope = dsp.ArrayPlot(XDataMode="Custom",PlotType="Line",...
YLimits=[0 500],XLabel="time (s)");
totalDrops = 0;
currentTime = 0;
for index=1:numIterations % run as long as you want
% Read from the microphone
[frame,drops] = adr();
totalDrops = totalDrops + drops;
% Save data to buffer
write(buff,frame);
% If you have enough data, do you analysis
if buff.NumUnreadSamples >= 2*fs
data = read(buff);
% loc represent the location associated with each pitch decision.
[p, loc] = pitch(data,fs);
scope(p)
% Set the x ticks
scope.CustomXData = currentTime + loc/fs;
currentTime = currentTime + loc(end)/fs;
end
end
totalDrops

Sign in to comment.

More Answers (0)

Categories

Find more on Audio I/O and Waveform Generation 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!