I'm doing a simple GUI in matlab using guide, where I have some sliders to select a frequency or many which then get plotted and played through the speakers. I'm learning real-time sound right now so I thought it'd be neat to incorporate it into the application. I right now have a button that plays the sinusoidal waves for 10 seconds when I press it, but I want a checkbox that disables the button when checked and immediately starts playing the sound continuously until the checkbutton is unchecked again.
I can't really get my head around how to do this in Matlab since I heard Matlab is inherently single threaded. And how to do it right with the GUI and everything since I suspect GUI creation is something you think you do right, but you miss some kind of detail and it only works in some situations.
What I think would be the easy way would be to have the check of the checkbox set the 'Enable' property of the Play button to false, and start an infinite loop that plays it from the real time system object I create. When I however uncheck the checkbox, it should set a flag or something to false and enable the Play button again. Could someone point me to if this is the right approach? How do I make the application listen to clicks on the check box while simultanously being in an infinite loop that processes and plays sound? The simultanous loop should be sensitive to changes in the sliders determining the frequencies and those frequencies are also stored in the handles variable.
Mockup code:
function playbutton_Callback(hObject, eventdata, handles)
freqs = [handles.freq1, handles.freq2, handles.freq3]
hightensecy = sinewave(handles.hightensecx, freqs); %creates a sinewave consisting of the three frequencies. hightensecx is a time vector of ten seconds with a high sample rate.
sound(hightensecy, handles.highsr);
figure;
plot(handles.hightensecx,hightensecy);
function y = sinewave(x, freqs)
% x in sec
y(:,1:size(freqs,2)) = sin(2*pi*x*freqs);
y=sum(y,2)/size(freqs,2);
end
% --- Other code to make the sliders store their values in handles.freq1, handles.freq2... ---
function continuousbox_Callback(hObject, eventdata, handles)
selected = get(hObject,'Value');
if(selected)
set(handles.playbutton, 'Enable', 'off');
startsound(handles);
else
set(handles.playbutton, 'Enable', 'on');
stopsound();
end
% Plays sound continuously
function startsound(handles)
%%Initialization
SamplesPerFrame = 1024;
Fs = handles.highsr;
Player = dsp.AudioPlayer('SampleRate', Fs);
%%Stream
tic
while(1)
%TODO Read in a new 1024 bytes chunk and make sure it has the same
%characteristics as sinewave(x, freqs)
step(Player, outsound)
end
%Stops the continuously played sound
function stopsound()
%TODO Somehow stop the loop inside startsound(handles)
If it is possible, it would be good if the resulting startsound function plays a sound that sounds exactly like the playbutton callback, only indefinitely. I'm also not sure how to handle phase issues that might occur in the real time loop. Should I use a time counter that tics away and calculates the current 1024 chunk's y-value and in that case, should I just use the time distance from tic, or increase it with 1024/sample rate seconds per time? Thanks in advance.
Related
I am creating a game in matlab app designer in which a player plays against the computer opponent. I want to code the CPU to press a button at random when it is its turn. For example, in TicTacToe the player plays against another player but in this case, the opponent is the CPU. The CPU is able to click buttons at random for example if there are 9 buttons it will press on any of those 9 randomly providing it has not been pressed already. I am not sure how to program this any help would be highly appreciated.
I have tried to use the callback function but do not know how to program the cpu to randomly press buttons.
On second thought, this is not as simple as triggering the callback function, because you have to let the AI know when to "press" the button also. So, the part about notifying the AI should be in the callback function as well:
function ButtonPushed(app, event)
% Get the button that triggered the callback function
btn = event.Source;
btn.Text = 'X';
btn.Enable = 'off';
% Now, notify the AI to make its move
AI_btn = app.Button_(randi(9));
% Obviously there are better ways to do this
% I will leave it for your own improvisation
while ~isequal(AI_btn.Enable, 'on')
% If the button is already pressed...
AI_btn = app.Button_(randi(9));
end
AI_btn.Text = 'X';
AI_btn.Enable = 'off';
end
I am currently trying to record footage of a camera and represent it with matlab in a graphic window using the "image" command. The problem I'm facing is the slow redraw of the image and this of course effects my whole script. Here's some quick pseudo code to explain my program:
figure
while(true)
Frame = AcquireImageFromCamera(); % Mex, returns current frame
image(I);
end
AcquireImageFromCamera() is a mex coming from an API for the camera.
Now without displaying the acquired image the script easily grabbs all frames coming from the camera (it records with a limited framerate). But as soon as I display every image for a real-time video stream, it slows down terribly and therefore frames are lost as they are not captured.
Does anyone have an idea how I could split the process of acquiring images and displaying them in order to use multiple cores of the CPU for example? Parallel computing is the first thing that pops into my mind, but the parallel toolbox works entirely different form what I want here...
edit: I'm a student and in my faculty's matlab version all toolboxes are included :)
Running two threads or workers is going to be a bit tricky. Instead of that, can you simply update the screen less often? Something like this:
figure
count = 0;
while(true)
Frame = AcquireImageFromCamera(); % Mex, returns current frame
count = count + 1;
if count == 5
count = 0;
image(I);
end
end
Another thing to try is to call image() just once to set up the plot, then update pixels directly. This should be much faster than calling image() every frame. You do this by getting the image handle and changing the CData property.
h = image(I); % first frame only
set(h, 'CData', newPixels); % other frames update pixels like this
Note that updating pixels like this may then require a call to drawnow to show the change on screen.
I'm not sure how precise your pseudo code is, but creating the image object takes quite a bit of overhead. It is much faster to create it once and then just set the image data.
figure
himg = image(I)
while(true)
Frame = AcquireImageFromCamera(); % Mex, returns current frame
set(himg,'cdata',Frame);
drawnow; %Also make sure the screen is actually updated.
end
Matlab has a video player in Computer vision toolbox, which would be faster than using image().
player = vision.VideoPlayer
while(true)
Frame = AcquireImageFromCamera(); % Mex, returns current frame
step(player, Frame);
end
the getsnapshot function takes a lot of time executing since (I guess) initializes the webcam every time is called. This is a problem if you want to acquire images with a high framerate.
I trick I casually discovered is to call the preview function, which keeps the webcam handler open making getsnapshot almost instantaneous, but it keeps a small preview window open:
% dummy example
cam = videoinput(...);
preview(cam);
while(1)
img = getsnapshot(cam);
% do stuff
end
Is there a "cleaner" way to speedup getsnapshot? (without preview window opened)
You could use the new "machine vision" toolbox which is specially built for vision applications. See code below:
vid = videoinput('winvideo', 1, 'RGB24_320x240'); %select input device
hvpc = vision.VideoPlayer; %create video player object
src = getselectedsource(vid);
vid.FramesPerTrigger =1;
vid.TriggerRepeat = Inf;
vid.ReturnedColorspace = 'rgb';
src.FrameRate = '30';
start(vid)
%start main loop for image acquisition
for t=1:500
imgO=getdata(vid,1,'uint8'); %get image from camera
hvpc.step(imgO); %see current image in player
end
As you can see, you can acquire the image with getdata. The bottleneck in video applications in Matlab was the preview window, which delayed to code substantially. The new vision.VideoPlayer is a lot faster (i have used this code in real time vision applications in Matlab. When i had written the first version without the vision toolbox, achieving frame rates at about 18 fps and using the new toolbox got to around 70!).
Note: I you need speed in image apps using Matlab, you should really consider using OpenCV libs through mex to get a decent performance in image manipulation.
I'm writing a code that will take the location of the cursor and output a sound signal. But here's the catch: There is already a sin function playing in the background, the mouse click will merely change the x and y values of this sound. Here is what I came up with so far:
clear all
clc
k = 1:1200;
k = k/5000;
x=1;
y=1;
while i<10;
[x,y]=ginput(1)
vib= 0.5*sin(2*pi*y*k);
note=sin(pi*x*k*440);
ses = note+vib;
sound (ses);
end
As you can see my code just plays a sin function but it is discrete. Can someone please help me? I researched handles and callbacks but I just can't get it in my head. The explanations that I find in the net are too complicated for me to understand.
sound (ses); just takes the variable "ses" and plays. While it plays you can not interfere in the data in the way you think. You can observe the change in the next sound() function call.
If you want to continously play a waveform you can look at here:
Matlab: How to get the current mouse position on a click by using callbacks
I'm using GUIDE to create GUI in Matlab. When user hits "Start" button in GUI it starts optimisation task in background that runs in endless loop. Every iteration it outputs some information to GUI.
When I press that start button and then close GUI window Matlab freezes. When I run GUI but do not press "start" button and just close GUI it does not freeze.
How can I avoid freezing ?
The infinite loop that you've started isn't allowing any further events (i.e. the window close event) to be processed. You need to allow the interrupt mechanism to occur - although the 'interruptible' property defaults to 'on', you have to satisfy another requirement:
If the Interruptible property of the object whose callback is executing
is on, the callback can be interrupted. However, it is interrupted
only when it, or a function it triggers, calls drawnow, figure,
getframe, pause, or waitfor. Before performing their defined tasks,
these functions process any events in the event queue, including any
waiting callbacks. If the executing callback, or a function it
triggers, calls none of these functions, it cannot be interrupted
regardless of the value of its object's Interruptible property.
Since you have a loop, you can insert a pause or drawnow command to allow MATLAB to process other events, such as mouse clicks on other buttons (pause(0) may work - haven't tested - to allow checking for interrupt events without actually causing the loop to slow if there are no interrupts).
(Side note: ctrl-c breaks out of loops, so you could always do that but... not ideal.)
I have also discovered that GUI can become unresponsive because of memory fragmentation in matlab when run endlessly
after say 100K iterations i deallocated all unnecessary and temporary variables and saved the result to .mat file
after that instructed the gui to force quit
and opened a new copy from autohotkey and loaded all previous variables from previous.mat files
The GUI now works for endless cycles
As noted by tmpearce in his answer in order for function (callback) to be interrupted it have to contain call to drawnow, figure, getframe, pause, or waitfor. And property interruptible has to be set to on on the button GUI component.
So I put pause inside the infinite (endless) cycle. However it did not work well: pause(0.0000000000000001) did slow down progress significantly (I did measure it so it isn't subjective). pause(0) did not slow down the cycle and allowed for GUI to update but did not allow to execute any other callbacks after another button was pressed.
I ended up using drawnow; command inside the cycle. It did not significantly slow down the cycle (less then 5% slow down) and the GUI works as expected.
I learnt that just using matlabpool beforehand will keep your gui responsive. Basically it will automatically put your calculation in a worker thread.
Unfortunately can't find the reference now. But maybe you are willing to try black magic ;)
matlab guis have lots of objects. when you close the GUI, the objects go away.
Sometimes, threads will remain after the window closes and your program keeps running.
To close this thread, I use an axis imbedded in my gui, and I make sure it still exists every loop.
h=gca;
for x = 1:WIDTH:(size(image,1)-WIDTH-OVERLAP-1)
for y = 1:HEIGHT:(size(image,2)-HEIGHT-OVERLAP-1)
%if the main gui closes, then the axis will change...
%in that case, you should stop this thread.
if(h == gca)
window = image(x:x+WIDTH+OVERLAP,y:y+HEIGHT+OVERLAP);%%account for a 10 pixel overlap
imshow(window)
pause(.01);
else
close all;
return;
end
end
end