I've done a function playSound(f) which looks like this:
function playSound(f)
fs = 44100;
t = 0:1/fs:1;
y = sin(2.*pi.*f.*t);
sound(y,fs,16);
end
I'm using this function in another function with the following code:
while i <= y
b = bin2dec(bits(i:i+k-1));
freq = 2000-frequencyInterval+b*deltaFreq;
playSound(freq);
pause(1);
i = i + k;
end
What I'm expecting from the last piece of code is getting a succession of sinusoids with different frequencies each lasting one second and one after another. But I've noticed that this is completely unreliable and I'm not getting exactly one second of one sin directly followed by another one.
Is there a more precise way to tell Matlab to play my sounds one by one, each during a certain time (no more no less) and without interruptions (or anything else in the middle)?
Matlab pause does not provide millisecond precision, even when measured by its internal tic-toc timer. For example:
tic;pause(1);toc
Elapsed time is 1.006905 seconds.
tic;pause(0.001);toc
Elapsed time is 0.018834 seconds.
If you can't 'pre-render' the entire sound sequence as suggested in the comments, I'd use a tool such as Psychophysics toolbox that can take care both of timing and audio playback.
Playing sound elegantly requires some low-level access and buffering and what not. Matlab's sound() function does not provide such access, and will not do what you want, unfortunately. However, if you've a recent Matlab, you will find audioplayer does do what you want, that's exactly the role it's designed for. Because of the need to 'play nice' with your sound hardware, you will have to invest a little more time in making it behave.
Start at "doc audioplayer".
Related
Say I have many (around 1000) large matrices (about 1000 by 1000) and I want to add them together element-wise. The very naive way is using a temp variable and accumulates in a loop. For example,
summ=0;
for ii=1:20
for jj=1:20
summ=summ+ rand(400);
end
end
After searching on the Internet for some while, someone said it's better to do with the help of sum(). For example,
sump=zeros(400,400,400);
count=0;
for ii=1:20
for j=1:20
count=count+1;
sump(:,:,count)=rand(400);
end
end
sum(sump,3);
However, after I tested two ways, the result is
Elapsed time is 0.780819 seconds.
Elapsed time is 1.085279 seconds.
which means the second method is even worse.
So I am just wondering if there any effective way to do addition? Assume that I am working on a computer with very large memory and a GTX 1080 (CUDA might be helpful but I don't know whether it's worthy to do so since communication also takes time.)
Thanks for your time! Any reply will be highly appreciated!.
The fastes way is to not use any loops in matlab at all.
In many cases, the internal functions of matlab all well optimized to use SIMD or other acceleration techniques.
An example for using the build in functionalities to create matrices of the desired size is X = rand(sz1,...,szN).
In your explicit case sum(rand(400,400,400),3) should give you then the fastest result.
Is there any way to show the execution progress (even a rough estimation) of a Matlab instruction?
For example let's say I am computing distances using pdist:
D = pdist(my_matrix,'cosine');
and this computation takes hours, does Matlab provide any way to show periodically the execution progress?
Not intrinsically. You can of course do after-the-fact checking with the profiler or tic/toc.
If this is something you will be doing a lot for a single function, you could consider modifying the function and saving it in your path with a new name (I have a directory called "Modified Builtin" for just this purpose). In the case of pdist.m, you might save pdist_updates.m. Looking a the function, the actual distances are calculated starting around line 250 with a series of nested loops. Add in a line like:
disp(sprintf('Processing pair %d of %d',i,n-1));
at line 265. If you really wanted to get fancy, you could use tic and toc to time each loop and provide an estimate of how long the entire calculation would take so you would know how long you had to run to the coffee machine.
Of course this will cause problems if you end up cancelling your Statistics Toolbox license or if Mathworks upgrades the toolbox and changes the functionality, so use this approach sparingly.
The matlab recording function"record ( recordObj, samplingTime )" needs 0.8 second plus the sampling time to be executed.
this means that if i want to record for only 0.2 second the execution time of this function will be 1 second.
I am working on a real time processing project in which I need to record 0.2 second files with high frequency and make real time processing on each file.
So i tried to record a long record and access it every 0.2 second.
So I wonder if i can access recordObj while the recording function is in progress .
I tried this code but i got error as the matlab couldn't access "myvoise" while recording is in progress. thanks in advance
clc
% clear all
% myVoice = audiorecorder;
% % Define callbacks to show when
% % recording starts and completes.
% myVoice.StartFcn = 'disp(''Start speaking.'')';
% myVoice.StopFcn = 'disp(''End of recording.'')';
% record(myVoice,20);
% y=getaudiodata(myVoice);
Unfortunately, Matlab is not really designed for real time processing. But if you really need it, look into the DSP Systems Toolbox, which provide this functionality.
You couldn't access myVoice because record is a not blocking function, this means that after execution of record(myVoice,20) immediately getaudiodata is executed but myVoice has not yet captured any data. If instead you use recordblocking(myVoice,20) then this will block flow of your code for 20 seconds. So myVoice now will contain data for 20 seconds and getaudiodata will be successfully executed.
Because you want real time operation I suggest set myVoice.TimerFcn = 'callbackfcn(myVoice)' and also set myVoice.TimerPeriod=period. Where callback fcn will be a user specified function in which you call data = getaudiodata(myVoice). This function will be called every period seconds during execution. So in this way you can call record(myVoice,20) and after period(s) getaudiodata will be successfully executed because myVoice already has period(in s) of audio data.
Be aware of that every time getaudiodata is executed will acquire all data of my voice from the beggining of recording, so you can skip every period the previous acquired data (i*period/Fs) where i is the time the callback function is executed(beginning from zero). Be also awhere of that myVoice will be buffered in memory, so if you record for a long period of time at high sampling frequency matlab performance will deteriorate
I am new to sound processing and I am trying to present a tone of 0.2ms, 0.3ms and 0.4ms to a user.
The code that I did is as follows: (MATLAB)
Fs = 16000;
duration = 0.2;
level = 0;
freq1 = 500;
t = 0: 1/Fs : duration*(Fs-1)/Fs;
fa1 = 10^(level/20);
y1 = fa1*sin(2*pi*freq1*t)';
ap = audioplayer(y1,Fs);
tic
playblocking(ap)
toc
The time I obtained from the tic,toc functions is 0.56 for a 0.2s duration I specified.
Is there anyway to make it present for exactly 0.2s?
My guess is that the sound persists for exactly the specified time. The discrepancy you are getting from tic and toc is the overhead required for calling the function, etc.
You could test this hypothesis by trying different lengths of sound. I suspect the overhead time should remain more or less constant relative to the time you play the sound. If you consistently get a tic-toc time of 0.3 sec longer than the time you expect the sound to play, then you can probably chalk the discrepancy off to overhead.
You may write a sound file with the wavwrite function that takes y1 and Fs variables as input. Then open the .wav with a sound editor (audacity for example) and check the exact timing.
Gordon's assumption is correct here. It takes time to start the audio stream and stop the audio stream. You can verify this by putting separate tic/toc calls inside the audioplayer/playblocking, resume, and stop methods.
You can then subtract the times of the pause and resume tic/toc from the playblocking call.
Audio player should only des the samples you give it to the soundcard.
Alternatively you can plug the audio output into the audio input on your soundcard and use audio recorder to record the audio back into MATLAB, then measure the number of samples in the signal.
Is there an API function call for this board that would allow me to generate a clock signal on an output at 500 kHz while running some other code on the board? Thanks in advance for the advices.
According to the Supported Hardware documentation, version 2.8 or greater of the Data Acquisition Toolbox is needed to support a Measurement Computing USB-1024HLS device. Assuming you have version 2.8 or newer, the following should come close to a solution for you...
The first step would be to get the hardware ID for the device. The function DAQHWINFO should help with this:
deviceInfo = daqhwinfo('mcc');
The hardware ID gotten from the structure deviceInfo can then be used to create a Digital I/O Object (DIO) using the DIGITALIO function:
dio = digitalio('mcc',hardwareID);
Next, you have to add two output lines (for a clock signal and a pulse-width modulation (PWM) signal) using ADDLINE:
addline(dio,0:1,'out');
Then, you have to set a few DIO properties.
set(dio,'TimerPeriod',0.000002); % i.e. 500 kHz
set(dio,'TimerFcn',#update_outputs);
The function update_outputs is called once every timer period and should set the output pins to the appropriate values. The clock signal is simply going to switch back and forth between 0 and 1 every timer period. The PWM signal will likely alternate between 0 and 1 as well, but it will not change every timer period, remaining in each state for a set amount of time based upon the sort of pulse-width modulation you want. Here's what your update_outputs function may end up looking like:
function update_outputs(obj,event)
currentValues = getvalue(obj);
clockValue = ~currentValues(1);
pwmValue = pwm_compute();
putvalue(obj,[clockValue pwmValue]);
end
Note that this uses PUTVALUE and GETVALUE to set/get the values of the output pins. You will have to write the function pwm_compute such that it computes a new PWM value for each time period. Since pwm_compute will likely have to know how many values have been output already (i.e. how many times it has already been called), you can track that using a persistent variable:
function newValue = pwm_compute
persistent nValues;
if isempty(nValues)
nValues = 0;
else
nValues = nValues+1;
end
...
% Compute the new value for the (nValues+1) time period
...
end
This is just one possible solution. You could potentially precompute the PWM signal and pull the value for each timer period from a vector or data file, or you could potentially use the event data structure passed to update_outputs to get the time of the timer event (relative to the DIO timer start, I believe).
Finally, you have to start the DIO:
start(dio);
...and, once you're finished using it, delete it and clear it from memory:
delete(dio);
clear dio;
One potential stumbling block...
Generating a 500 kHz signal could be difficult. It's such a high frequency that you may run into problems, specifically with the 'TimerFcn', which is called once every timer period. If the 'TimerFcn' takes longer than 0.000002 seconds to run, some timer events may not be processed, leading to an output that is actually of a lower frequency. I have a feeling you may have to use a lower signal frequency for things to work properly, but I could be wrong. =)
I found Example: Generating Timer Events in the Data Acquisition Toolbox documentation.
dio = digitalio('nidaq','Dev1');
addline(dio,0:7,'in');
set(dio,'TimerFcn',#daqcallback)
set(dio,'TimerPeriod',5.0)
start(dio)
pause(11)
delete(dio)
clear dio