Thursday, 24 March 2011

Making a MATLAB Media Player

Recently i got a request to write a blog on making a media player on MATLAB. This example shows you a simple way to make a mp3 player in steps. In this step, i will write how to setup the initial background and design base GUI using GUIDE.


Using a mp3 reader
MATLAB does not have an inbuilt mp3 reader function. mp3 is a  encoded which you need to convert to wavfile before reading it. But Dont worry, matlab central provides you all.

go to this download link and download the zip file.
http://www.mathworks.com/matlabcentral/fileexchange/6152-mp3write-and-mp3read

extract the folder and save it to your current directory with name mp3readwrite.

Now you need to add the path of these files in your matlab file.
path(path,'mp3readwrite');
To verify that you have done right, put a mp3 file with name playfile.mp3 in your current directory and run this command
[y f]=mp3read('playfile.mp3');
if you get undefined function or variable mp3readwrite, then check the path of the file inside folder and change the path accordingly.

Generating gui fig using GUIDE
first step is to generate a fig file which contains the basic component of a media player. (As in fig 1)

Fig 1 : sample media player GUI
  1. A playlist (ListBox)
  2. An Add File button (PushButton)
  3. A Volume Silder (Slider)
  4. A play Progress Slider(Slider)
  5. Play/Pause Button (Push Button)
  6. Stop Button (Push Button)
  7. Visualization (Axis)
See fig 2 to see the sample tag name used in this example
save this file as mmp.fig and this will generate a mmp.m file

Fig 2 : GUIDE TAGS

 
 In the previous section, We have seen the basic GUI fig. In this section, we would be learning to add basic features in this player.

Making the playlist work
Making the playlist is easy task. Since we need the full path for playing purpose and we need to show only title information in playlist. So we will maintain a spearate list playfiles for full path.

Add this to your opening function 

function mmp_OpeningFcn(hObject, eventdata, handles, varargin)
handles.playfiles=[];
% Update handles structure
guidata(hObject, handles);
We have made the add button. Modify the callback for pladd 
function pladd_Callback(hObject, eventdata, handles)
% hObject    handle to pladd (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[f g]=uigetfile;
p=get(handles.playlist,'String');
p{length(p)+1}=[f];
set(handles.playlist,'String',p);
handles.playfiles{length(handles.playfiles)+1}=[g '\' f];
guidata(hObject,handles);

As you can see, uigetfile is used to open a filebrowser and then i store the filename and its path into a list playfiles.
I also update the playlist string property with the file name which is shown on playlist on player.

How to play Audio
There are some option like wavplay or sound in matlab which can play your audio. But you cannot pause or resume it once you have started it. We will use audioplayer class of MATLAB for our purpose.

This small code tells you how to play a wav file by audioplayer object.
first read the .wav file using wavread
[y f]=wavread('aa.wav');
now make an instance of audioplayer with this y and f.
pl=audioplayer(y,f);
pl is the handle to this audioplayer.
Now you can use the play/pause/resume/stop methods to do the respective operations. As an Example:
play(pl);
pause(pl);
resume(pl);
You can get the total sample and current sample number using get method over pl object as 
cs=get(pl,'CurrentSample');
ps=get(pk,'TotalSamples');
To get the progress of the sound file, you can use
ctime=cs/ps;
you can use isplaying option to check whether the pl is running or not.
f=isplaying(pl);
You can combine this with mp3reader to read a mp3 file
cfile='aa.mp3';
extn=cfile[end-2:end];
switch (extn)
  case 'mp3'
        [y f]=mp3read(cfile);
  case  'wav'
       [y f]=wavread(cfile);
end
pl=audioplayer(y,f);
play(pl);
There is one more cool thing to do here. You can make a function which gives you the current progress of music and it will be called automatically by matlab after a certain time if you give its name to audioplayer object. let us see how we can do it.
first make an new m file and save it as UpdateWin.m and write the following in this

function UpdateWin(pl)
%global pl;
c=get(pl,'CurrentSample');
t=get(pl,'TotalSamples');
disp(c/t);

Now make a function f where you can pass this pl.
f=@() UpdateWin(pl);
Now set this f as timer function of pl.
set(pl,'TimerFcn','f()');
Timercall time is automatically set as TimerPeriod: 0.0500 in seconds


Whole piece of code will look like as
cfile='aa.mp3';
extn=cfile[end-2:end];
switch (extn)

  case 'mp3'
        [y f]=mp3read(cfile);

  case  'wav'
       [y f]=wavread(cfile);
end
pl=audioplayer(y,f);

f=@() UpdateWin(pl);
set(pl,'TimerFcn','f()');
play(pl);
Adding Playing Callback
In playbuttonCallback function add the following code for starting the playing of music. Steps we are following are
1. Selecting the file name from playlist
v=get(handles.playlist,'Value');
cfile=handles.playfiles{v};
2. create the player and assign it to the player in handles structure.
extn=cfile[end-2:end];
switch (extn)
  case 'mp3'
        [y f]=mp3read(cfile);
  case  'wav'
       [y f]=wavread(cfile);
end
pl=audioplayer(y,f);
f=@() UpdateWin(pl);
set(pl,'TimerFcn','f()');
handles.pl=pl;
3. Now play this if the player is not running else pause it
if isrunning(pl)
    pause(pl);
else
  resume(pl);
end
Adding other callbacks
making other call backs are pretty easy.
just write following in stop callback
stop(pl);
Making the playersilder move
 Noe it is time to move your player slider to show the progress.
Update your UpdateWin file as following
function UpdateWin(pl)
c=get(pl,'CurrentSample');t=get(pl,'TotalSamples');
%disp(c/t);
h=guidata(pl);
set(h.playslider,'value',c/t);
Enjoy Your player is working now

29 comments:

  1. Hmm.. not entirely working here.
    In the playbutton_callback, at the point resume(pl), no music is played when i run the program.

    When i place a "keyboard" commando right before the resume(pl), and by hand type resume(pl), it DOES play music. Strange?

    ReplyDelete
  2. Hmm, seems the music stops playing when the program comes to the end of the playbutton_callback.

    When i place a pause(10) after the resume(pl), the music plays for 10 seconds. Any way to overcome this?

    ReplyDelete
  3. This should work as i have tested it on my system.

    Check that you have not written stop(pl); inside the playbackcallback and you have clicked on the button play.

    ReplyDelete
  4. There's no stop(pl) in the playbutton callback.

    When I press the play, music starts and plays for 10 seconds, due to the pause(10). When I remove the pause(10), i can't hear the music start playing, it immediately stops.

    [y f]=mp3read(cfile);
    pl=audioplayer(y,f)
    handles.pl=pl;
    resume(pl)
    pause(10)

    That's what's inside the playbutton callback

    ReplyDelete
  5. can you paste your full code here.. there may be mistake anywhere else

    ReplyDelete
  6. Okay, i skipped some comments to make it more compact. Only thing i changed is the if isrunning on the pause/resume thing, because isrunning is from the data-aquisition, not yet installed. But with resume(pl) and just pressing the play button once it should work also.

    function varargout = NLTmediaplayer(varargin)

    % Begin initialization code - DO NOT EDIT
    gui_Singleton = 1;
    gui_State = struct('gui_Name', mfilename, ...
    'gui_Singleton', gui_Singleton, ...
    'gui_OpeningFcn', @NLTmediaplayer_OpeningFcn, ...
    'gui_OutputFcn', @NLTmediaplayer_OutputFcn, ...
    'gui_LayoutFcn', [] , ...
    'gui_Callback', []);
    if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
    end

    if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
    else
    gui_mainfcn(gui_State, varargin{:});
    end
    % End initialization code - DO NOT EDIT


    % --- Executes just before NLTmediaplayer is made visible.
    function NLTmediaplayer_OpeningFcn(hObject, eventdata, handles, varargin)

    % Choose default command line output for NLTmediaplayer
    handles.output = hObject;
    handles.playfiles=[];

    % Update handles structure
    guidata(hObject, handles);


    % --- Outputs from this function are returned to the command line.
    function varargout = NLTmediaplayer_OutputFcn(hObject, eventdata, handles)

    % Get default command line output from handles structure
    varargout{1} = handles.output;


    % --- Executes on selection change in playlist.
    function playlist_Callback(hObject, eventdata, handles)

    % --- Executes during object creation, after setting all properties.
    function playlist_CreateFcn(hObject, eventdata, handles)

    if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
    end


    % --- Executes on button press in pladd.
    function pladd_Callback(hObject, eventdata, handles)

    [f g]=uigetfile
    p=get(handles.playlist,'String');
    p{length(p)+1}=[f];
    set(handles.playlist,'String',p);
    handles.playfiles{length(handles.playfiles)+1}=[g f];
    guidata(hObject,handles);





    % --- Executes on button press in pladdD.
    function pladdD_Callback(hObject, eventdata, handles)


    % --- Executes on slider movement.
    function playslider_Callback(hObject, eventdata, handles)

    % --- Executes during object creation, after setting all properties.
    function playslider_CreateFcn(hObject, eventdata, handles)

    if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
    end


    % --- Executes on slider movement.
    function volslider_Callback(hObject, eventdata, handles)

    % --- Executes during object creation, after setting all properties.
    function volslider_CreateFcn(hObject, eventdata, handles)

    if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
    end


    % --- Executes on button press in playbutton.
    function playbutton_Callback(hObject, eventdata, handles)

    v=get(handles.playlist,'Value');
    cfile=handles.playfiles{v};

    [y f]=mp3read(cfile);
    pl=audioplayer(y,f);

    handles.pl=pl;
    resume(pl);

    pause(10)


    %end



    % --- Executes on button press in stopbutton.
    function stopbutton_Callback(hObject, eventdata, handles)


    function UpdateWin(pl)
    c=get(pl,'CurrentSample');
    t=get(pl,'TotalSamples');
    %disp(c/t);
    h=guidata(pl);
    set(h.playslider,'value',c/t);

    ReplyDelete
  7. see this

    function playbutton_Callback(hObject, eventdata, handles)
    v=get(handles.playlist,'Value');
    cfile=handles.playfiles{v};
    [y f]=mp3read(cfile);
    pl=audioplayer(y,f);
    handles.pl=pl;
    resume(pl);
    pause(10);
    %end


    In the last line, you have commented out the end. that may be the reason . uncomment that end

    ReplyDelete
  8. The end does not belong to the function, but to a previous existing if-statement.

    Also tried it with the end (had to add it to every function), but still the same problem.

    ReplyDelete
  9. Maybe a version problem? I'm using R2010b

    ReplyDelete
  10. Ah, I have solved it. The variable pl ends living when the function end. So adding: global pl; before stating pl=audioplayer(y,f); solves the problem!

    Now it works. Nice program, and thanks for the help!

    ReplyDelete
  11. I am not sure, because i used the same thing and it is working on my side. need a closer debug

    although the pl is not global, but the object it is pointing will not end after the function ends, so it should work.


    anywyas, may be a version problem

    ReplyDelete
  12. This comment has been removed by the author.

    ReplyDelete
  13. it will be called always in fixed interval of time.

    ReplyDelete
  14. This comment has been removed by the author.

    ReplyDelete
  15. ah yes, thanks for the info. this post was very helpful. im just wondering if the slider could change the time it was playing while it is playing?

    ReplyDelete
  16. NO you have to put extra callback for that, change the slidercallback to set the playback time

    ReplyDelete
  17. could i request for tips? the timerfcn always updates the slider while its playing..thank you so much..your response is well appreciated!

    ReplyDelete
  18. could i request for tips? the timerfcn always updates the slider while its playing..thank you so much..your response is well appreciated!

    ReplyDelete
  19. yeah sure, u can ask your questions here

    you can also visit this page and post your queries

    http://www.facebook.com/pages/Matlab-By-Examples-Book/158144800875598

    ReplyDelete
  20. path(path,'mp3readwrite');


    what u mean by this at path ===i have to add any path location

    ReplyDelete
    Replies
    1. Read how to add path in matlab. Adding a path, will tell matlab to look for a file in this location otherwise maltab can not find the file. it cannot searchthe whole computer for file. it need to know where is it. so you can either tell the path each time you run the code or you can add path once in starting.

      Delete
  21. I solved the music not playing problem and also the stopping problem.
    global variables needed to be defined starting of every function.
    just add
    global pl;
    to start of every callback function

    ReplyDelete
  22. @cosinus thanks for the suggestion :)

    ReplyDelete
  23. Any way that you could paste your whole code here, or provide a download link? I've been staring at this example for a while... My stop(pl) isn't working (nor is pause), even after globalizing pl.

    Thanks!

    ReplyDelete
  24. code for extracting video frames from a video and saving it into a folder,visit :

    http://matlabnstuff.blogspot.in/2013/01/extracting-frames-from-video-file.html

    ReplyDelete
  25. Code for motion detection in a video,visit :

    http://matlabnstuff.blogspot.in/p/object-detection-using-matlab-code.html

    ReplyDelete
  26. This comment has been removed by the author.

    ReplyDelete
  27. i'm having a hard time understanding this. i'm still a newbie in matlab. is there someone who can teach this to me step by step through a video maybe? your help will be much appreciated.

    ReplyDelete
  28. i am getting the following error when i try to run any other mp3 file (rather than the already provided mp3 files in the system) in MATLAB :-

    Error while decoding file. File may be corrupted

    how can i rectify this error? i have stored the downloaded mp3's in the MATLAB directory and these files are also running in Windows Media Player.

    ReplyDelete