Issue with trying to play and record audio simultaneously

Hi guys, For my project I need to play a wav file from my speaker and while it's playing I want to record it with a microphone simultaneously. I'm using the audioPlayerRecorder which I believe is what I need to use. This is what I've done so far, however I'm not quite sure if its correct.
clear all
clc
filereader=dsp.AudioFileReader('chirp_2.wav'); % this is the wav file saved in my Computer
fs=filereader.SampleRate;
filewriter= audioDeviceWriter(fs);
apr=audioPlayerRecorder('SampleRate',fs);
while ~isDone(filereader)
audioToPlay = filereader();
audioRecorded = apr(audioToPlay);
filewriter(audioToPlay);
end
release(apr);
release(filewriter);
release(filereader);
mic1=getaudiodata(apr);
mic2=getaudiodata(filewriter);
When I run this, it runs fine so I'm assuming that both speaker and microphone are working synchronously?
My issue is, I want to plot both the audio from speaker and the recorded audio. I'm trying to convert the object to a numerical array through the getaudiodata function however having I get an error saying "Unrecognized function or variable getaudiodata()".
Does anyone know how to plot both the speaker and microphone audio?

 Réponse acceptée

Walter Roberson
Walter Roberson le 24 Juil 2020
getaudiodata() is only for audiorecorder() https://www.mathworks.com/help/matlab/ref/audiorecorder.html which is a routine that records audio and holds on to it until it is asked for.
You are using the system-object based routines such as audioPlayerRecorder. Those do not hold on to all the data: they only hold on to one buffer-worth. The audio data can be obtained by using step() -- or, exactly the way you did, by invoking the variable storing the object as-if it were a function. One buffer at a time.

8 commentaires

Could you give me an example, as I don't quite understand your method. Presumably, I'm assuming that AudioRecorded holds the data captured by microphone and AudioToPlay holds the data played by the Speaker, so they can be obtained using the step function? I looked at the documentation for the step function and I don't see how it relates to that, unless i'm looking at the wrong documentation.
I'm assuming that AudioRecorded holds the data captured by microphone
Yes -- one buffer of it.
AudioToPlay holds the data played by the Speaker
Not necessarily. What is recorded will not necessarily be the same as what you are outputing with apr(audioToPlay) . audioPlayerRecorder() is not a loopback process. The playing part sends signal out the line out (or headphone) connector, which you presumably have connected to a speaker of some kind. The recording part receives signal from the line in (or microphone) connector, which you presumably have connected to a microphone of some kind. However, the speaker and the microphone could be quite distant from each other.
For example, you could be having someone playing at a concert, and the line in could be connected to the speaker's microphone, and the line out could be connected to big speakers at the other end of the soccer pitch.
audioToPlay = filereader();
That is an abbreviation for
audioToPlay = step(filereader);
and
audioRecorded = apr(audioToPlay);
That is an abbreviation for
audioRecorded = step(apr, audioToPlay);
step(filereader), which can also be written as just filereader() , pulls in the next buffer of input data, and sends it to the output variable. step(apr, audioToPlay), which can also be written as apr(audioToPlay), queues audioToPlay with the sound output system, and also turns on recording for one buffer-full.
Your existing code
while ~isDone(filereader)
audioToPlay = filereader();
audioRecorded = apr(audioToPlay);
filewriter(audioToPlay);
end
is already recording from a microphone at the same time that the next block of sound is playing. If the microphone is near the speaker, then it would be recording what is playing (but possibly with a slight time lag.)
filewriter= audioDeviceWriter(fs);
Your variable name suggests that you believe that that will write to file, but that is incorrect: it will write to an audio device such as the line output jack, probably interfering with your other output. To write to a file, you would use https://www.mathworks.com/help/dsp/ref/dsp.audiofilewriter-system-object.html
Thanks for your reply. Regarding your first point, that is itself the purpose of this Code, as I'm building a SODAR detection system where the Speaker and Microphone are a distance apart and I play/record audio synchronously to detect the distance via further processing. Upon further trial, you are indeed correct that AudioToPlay variable does not hold the data played by the Speaker. It's just an array of 0s, i'm not sure why that's the case but its not a big thing right now.
Regarding your point about my while loop, that was also something I wasn't sure about and I copied the names from the documentation about audioPlayerRecorder. From what I understood, audioFileReader will read the audio samples from the wav file, and the audioDeviceWriter is going to write these samples to my sound card. That covers the Speaker aspect, and with audioRecorded, im recording the data captured by the microphone. I don't believe I should need audioFileWriter because I'm not writing to a file, despite the contradictory name.
Just so I'm understanding you correctly, my SamplesPerFrame is 1024, which im assuming is the buffer size. Since it's a while loop, my AudioRecorded variable is only holding the latest buffer read by the ~isDone command and not the whole thing. Am i right with this assumption? Sorry for this long comment but I'm trying to get my head across this thing.
Apologies for the late reply and thanks for your comment again!
SamplesPerFrame is indeed the buffer size, in samples; you would read in that many samples for each channel, each time you did the fileread()
[See also https://www.mathworks.com/help/audio/ref/asiosettings.html if you are using ASIO (which you should be if you can, as that has the lowest latency.)]
That would be the same number of audio samples you sent to the play/record, and the same number of samples you received from the play/record .
You would then have to process that buffer-full somehow before continuing the loop, unless you are going to write the samples somewhere, as it hold only the latest data you read in, and not all previous data.
Victor Dunira
Victor Dunira le 12 Août 2020
Modifié(e) : Walter Roberson le 12 Août 2020
Hello i'm also trying to record and play simulantaneously and have adapted the code from the MATLAB webpage: https://uk.mathworks.com/help/audio/ref/audioplayerrecorder-system-object.html
My issue is that i want to retreive the input signal and output signal and peform IFFT (to obtain the impulse response) on them however my matrices do not match and they are slightly off.
my created input signal (x) has a matrix value of 441000
and my output signal (D2) has a matrix value of 440320
CODE IS ATTACHED BELOW
clear all
close all
clc;
% Create a signal to play and record
fs =44100; % sampling frequency
fs2 =44100; % sampling frequency
time = 10; % signal duration
N = time * fs; % number of samples
x = randn(1,N); % Gaussian white noise
x_normalized = x/(max(abs(x))); %%to avoid Data clipping
info = audioinfo('Whitenoise.wav');
filename = 'Whitenoise.wav';
audiowrite(filename, x_normalized, fs2); %%writes audio and saves as wav file
% [x,fs] = audioread('Whitenoise.wav');
% sound(x,fs);
fileReader = dsp.AudioFileReader('Whitenoise.wav', ...
'SamplesPerFrame',1920); %%Reads the audio samples
fileWriter = dsp.AudioFileWriter('WhitenoisePlaybackRecorded.wav', ...
'SampleRate',fs2); %%Writes audio samples to audio file
aPR = audioPlayerRecorder('SampleRate',fs2);
while ~isDone(fileReader) %% while reads the audio samples
audioToPlay = fileReader();
[audioRecorded,nUnderruns,nOverruns] = aPR(audioToPlay);
fileWriter(audioRecorded)
if nUnderruns > 0
fprintf('Audio player queue was underrun by %d samples.\n',nUnderruns);
end
if nOverruns > 0
fprintf('Audio recorder queue was overrun by %d samples.\n',nOverruns);
end
end
[D2,fs2] = audioread('WhitenoisePlaybackRecorded.wav');
h = ifft(fft(D2)./fft(x'));
figure;
plot(abs(h));
Unfortunately I do not appear to have a simultaneous input/output device on my system (not sure why it isn't recognizing the mic on my webcam, but since webcams are not output that is not curently relevant.)
Have you installed ASIO driver, it recognised my laptops microphone and speakers after installation.
ASIO does not exist for MacOS. ;-)
And it is true that I do not have a simultaneous input/output audio device. I had been thinking of my speakers and built-in mic as one combine unit, but really they are not at all.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Audio I/O and Waveform Generation dans Centre d'aide et File Exchange

Produits

Version

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by