Code covered by the BSD License  

Highlights from
SIFT Pitch Detector

image thumbnail

SIFT Pitch Detector

by

 

13 Feb 2014 (Updated )

This exercise designs and implements a pitch period detector based on detecting and tracking peaks.

Callbacks_sift_pitch_GUI25(f,C,start_path)
function Callbacks_sift_pitch_GUI25(f,C,start_path)

%SENSE COMPUTER AND SET FILE DELIMITER
switch(computer)				
    case 'MACI64',		char= '/';
    case 'GLNX86',  char='/';
    case 'PCWIN',	char= '\';
    case 'PCWIN64', char='\';
    case 'GLNXA64', char='/';
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
x=C{1,1};
y=C{1,2};
a=C{1,3};
b=C{1,4};
u=C{1,5};
v=C{1,6};
m=C{1,7};
n=C{1,8};
lengthbutton=C{1,9};
widthbutton=C{1,10};
enterType=C{1,11};
enterString=C{1,12};
enterLabel=C{1,13};
noPanels=C{1,14};
noGraphicPanels=C{1,15};
noButtons=C{1,16};
labelDist=C{1,17};%distance that the label is below the button
noTitles=C{1,18};
buttonTextSize=C{1,19};
labelTextSize=C{1,20};
textboxFont=C{1,21};
textboxString=C{1,22};
textboxWeight=C{1,23};
textboxAngle=C{1,24};
labelHeight=C{1,25};
fileName=C{1,26};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%PANELS
for j=0:noPanels-1
uipanel('Parent',f,...
'Units','Normalized',...
'Position',[x(1+4*j) y(1+4*j) x(2+4*j)-x(1+4*j) y(3+4*j)-y(2+4*j)]);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%GRAPHIC PANELS
for i=0:noGraphicPanels-1
switch (i+1)
case 1
graphicPanel1 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
case 2
graphicPanel2 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
case 3
graphicPanel3 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%TITLE BOXES
for k=0:noTitles-1
switch (k+1)
case 1
titleBox1 = uicontrol('parent',f,...
'Units','Normalized',...
'Position',[u(1+4*k) v(1+4*k) u(2+4*k)-u(1+4*k) v(3+4*k)-v(2+4*k)],...
'Style','text',...
'FontSize',textboxFont{k+1},...
'String',textboxString(k+1),...
'FontWeight',textboxWeight{k+1},...
'FontAngle',textboxAngle{k+1});
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%BUTTONS
for i=0:(noButtons-1)
enterColor='w';
if strcmp(enterType{i+1},'pushbutton')==1 ||strcmp(enterType{i+1},'text')==1
enterColor='default';
end
if (strcmp(enterLabel{1,(i+1)},'')==0 &&...
        strcmp(enterLabel{1,(i+1)},'...')==0) %i.e. there is a label
%creating a label for some buttons
uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i)-labelDist-labelHeight(i+1) ...
(m(2+2*i)-m(1+2*i)) labelHeight(i+1)],...
'Style','text',...
'String',enterLabel{i+1},...
'FontSize', labelTextSize(i+1),...
'HorizontalAlignment','center');
end
switch (i+1)
case 1
button1=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button1Callback);
case 2
button2=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button2Callback);
case 3
button3=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button3Callback);
case 4
button4=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button4Callback);
case 5
button5=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button5Callback);
case 6
button6=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button6Callback);
case 7
button7=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button7Callback);
case 8
button8=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button8Callback);
case 9
button9=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button9Callback);
case 10
button10=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button10Callback);
case 11
button11=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button11Callback);
case 12
button12=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button12Callback);
case 13
button13=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button13Callback);
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%USER CODE FOR THE VARIABLES AND CALLBACKS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initialize Variables
    curr_file=1;
    fs=8000;
    fsd=10000;
    directory_name='abcd';
    wav_file_names='abce';
    fin_path='filename';
    fname='output';
    nsamp=1;
    ss=8000;
    Lm=40;
    L=400;
    Rm=10;
    R=100;
    imf=1;
    nframes=20;
    nlayers=5;
    nfft=10000;
    xin=[];
    y=[];
    yf=[];
    yfl=[];
    p=4;
    pthr1=2.0;
    Lmed=5;
    nl=1;
    n=[];
    p1m=[];
    c1m=[];
    xpp=' ';

% Name the GUI
    set(f,'Name','SIFT_pitch_detector');

% CALLBACKS
% Callback for button1 -- Get Speech Files Directory
 function button1Callback(h,eventdata)
     directory_name=uigetdir(start_path,'dialog_title');
%     if isempty(getpref('SpeechApps'))
%          url = sprintf('%s%s%s',...
%              'http://www.mathworks.com/matlabcentral/fileexchange/',...
%              '42911-speech-and-audio-files-for-speech-processing-excercises',...
%              '?download=true');
%          [saveloc,~,~] = fileparts(pwd); %save to one level up from current folder
%          % Create a waitbar during download
%          h = waitbar(0.35,'This may take several minutes...',...
%              'Name','Downloading Speech Files...');
%          % Download the zipped file
%          [filestr,status] = urlwrite(url,[saveloc filesep 'speech_files.zip'],...
%              'Timeout',10);
%          if status
%              delete(h);
%              hh1= helpdlg('Downloaded. Select a location to UNZIP the speech files.');
%              uiwait(hh1);
%              unziploc = uigetdir(saveloc,'Select a location to unzip the speech files');
%              h2 = waitbar(0.2,'This may take a minute...',...
%                  'Name','Unzipping the Speech Files to Location Selected...');
%              unzip(filestr,unziploc);
%              delete(h2)
%              addpref('SpeechApps','path',unziploc);
%              hh2= helpdlg('Ready. Select the speech_files folder in the next window');
%              uiwait(hh2);
%          else
%              warndlg('No Internet Connection to MATLAB Central!');
%          end
%          
%      else
%      end
%      directory_name=uigetdir(getpref('SpeechApps','path'));
     A=strvcat(strcat((directory_name),[char,'*.wav']));
     struct_filenames=dir(A);
     wav_file_names={struct_filenames.name};
     set(button2,'String',wav_file_names);
     
% once the popupmenu/drop down menu is created, by default, the first
% selection from the popupmenu/drop down menu id not called
    indexOfDrpDwnMenu=1;
    
% by default first option from the popupmenu/dropdown menu will be loaded
    [curr_file,fs]=loadSelection(directory_name,wav_file_names,indexOfDrpDwnMenu);
 end

% Callback for button2 -- Choose speech file for play and plot
 function button2Callback(h,eventdata)
     indexOfDrpDwnMenu=get(button2,'val');
     [curr_file,fs]=loadSelection(directory_name,wav_file_names,indexOfDrpDwnMenu);
 end

%*************************************************************************
% function -- load selection from designated directory and file
%
function [curr_file,fs]=loadSelection(directory_name,wav_file_names,...
    indexOfDrpDwnMenu);
%
% read in speech/audio file
% fin_path is the complete path of the .wav file that is selected
    fin_path=strcat(directory_name,char,strvcat(wav_file_names(indexOfDrpDwnMenu)));
    
% clear speech/audio file
    clear curr_file;
    
% read in speech/audio signal into curr_file; sampling rate is fs 
    [curr_file,fs]=wavread(fin_path);
    xin=curr_file*32768;
    
% create title information with file, sampling rate, number of samples
    fname=wav_file_names(indexOfDrpDwnMenu);
    FS=num2str(fs);
    nsamp=num2str(length(curr_file));
    file_info_string=strcat('  file: ',fname,', fs: ',FS,' Hz, nsamp:',nsamp);
    
% read in filename (fname) from cell array
    fname=wav_file_names{indexOfDrpDwnMenu};
end

% Callback for button13 -- Play Speech File
    function button13Callback(h,eventdata)
        soundsc(curr_file,fs);
    end

% Callback for button3 -- fsd: sampling rate of signal processing
 function button3Callback(h,eventdata)
     fsd=str2num(get(button3,'string'));
     a = [6000 8000 10000 16000 20000];
     fsd = a(get(button3,'val'));
 end

% Callback for button4 -- imf: male/female pitch period range option; 1 for
% male, 2 for female
 function button4Callback(h,eventdata)
     imf=get(button4,'val');
 end

% Callback for button5 -- Lm: analysis frame length in msec
 function button5Callback(h,eventdata)
     Lm=str2num(get(button5,'string'));
     if ~((Lm >= 1 && Lm <= 100))
        waitfor(errordlg('Lm must be a positive number between 1 and 100'))
        return;
     end
 end

% Callback for button6 == Rm: analysis frame shift in msec
 function button6Callback(h,eventdata)
     Rm=str2num(get(button6,'string'));
     if ~((Rm >= 1 && Rm <= 100))
        waitfor(errordlg('Rm must be a positive number between 1 and 100'))
        return;
     end
 end

% Callback for button7 -- p: lpc system order
 function button7Callback(h,eventdata)
     p=str2num(get(button7,'string'));
     if ~((p >= 4 && p <= 32))
        waitfor(errordlg('p must be a positive integer between 4 and 32'))
        return;
     end
     p=round(p);
     set(button7,'string',num2str(p));
 end

% Callback for button8 -- pthr1: SIFT ratio threshold
 function button8Callback(h,eventdata)
     pthr1=str2num(get(button8,'string'));
     if ~((pthr1 >= 2.0 && pthr1 <= 2.6))
        waitfor(errordlg('pthr1 must be a number between 2.25 and 2.6'))
        return
     end
 end

% Callback for button9 -- Lmed: size of median smoother in samples
 function button9Callback(h,eventdata)
     Lmed=str2num(get(button9,'string'));
     if ~((Lmed >= 3 && Lmed <= 11))
        waitfor(errordlg('Lmed must be a positive integer between 3 and 11'))
        return;
     end
     Lmed=round(Lmed);
     set(button9,'string',num2str(Lmed));
 end

% Callback for button10 -- run SIFT pitch detector -- unsmoothed
 function button10Callback(h,eventdata)
     
% check editable buttons for changes
    button3Callback(h,eventdata);
    button4Callback(h,eventdata);
    button5Callback(h,eventdata);
    button6Callback(h,eventdata);
    button7Callback(h,eventdata);
    button8Callback(h,eventdata);
    button9Callback(h,eventdata);
       
% function to setup signal processing parameters for cepstral pitch detector
    [n,p1m,nl,c1m]=setup_SIFT_pitch_detector(xin,fs,fsd,imf,pthr1,p,...
        Lm,Rm,Lmed,fname);
 end

%***********************************************************************
function [n,p1m,nl,c1m]=setup_SIFT_pitch_detector(xin,fs,fsd,imf,pthr1,p,...
        Lm,Rm,Lmed,fname)
%
% sift--simple inverse filtering tracking pitch detector
% basic idea is to bandpass filter speech signal to bandwidth of about 1000
% Hz, decimate to a sampling rate of 2 kHz, do a 4-pole LPC analysis,
% inverse filter the speech signal giving the flat spectrum excitation,
% autocorrelate the error signal (using the modified autocorrelation), find
% the strongest and the second strongest peaks in the appropriate pitch
% period range, interpolate back to a 10 kHz rate, search local regions of
% contiguous pitch period peaks to refine location of peaks in regions of
% uncertainty, designate regions of low confidence as non-voiced,
% non-linearly smooth pitch period estimates using median smoother
% function to set up all signal processing parameters for cepstral pitch
% detection
    clear y ye yf yfl;
    clear pp1 pp2 plevel1 plevel2;
    clear ppdf ppsav pplevel;
    clear p1m c1m ppm plevel1m;
    
% convert frame duration and frame shift to samples at signal processing
% sampling rate
    L=round(Lm*fsd/5000);
    R=round(Rm*fsd/5000);
    
% resample if fs ~= fsd
    y=xin;
    if (fs ~= fsd)
        y=srconv(y,fs,fsd);
    end
    ly=length(y);
    
% design bandpass filter for eliminating DC, hum, high frequency components
    n=400;
    fl1=60*fsd/10000;
    fl2=960*fsd/10000;
    fh1=120*fsd/10000;
    fh2=900*fsd/10000;
    bbp=bpf(n,fl1,fh1,fh2,fl2,fsd,0);
    n=n+1;
    
% bandpass filter the speech file and compensate for the linear phase delay
    ye=[y; zeros(1,n)'];
    yf=filter(bbp,1,ye);
    yf=yf((n-1)/2+1:ly+(n-1)/2);
    
% downsample by 5-to-1 to 2000 Hz sampling rate
    yfl=yf(1:5:length(yf));
    fsl=fsd/5;
    % soundsc(yfl,fsl);

% perform lpc analysis, inverse filter speech waveform, compute 
% autocorrelation, determine primary and secondary pitch periods for each 
% frame, determine confidence score as autocorrelation level
    [pp1,pp2,plevel1,plevel2]=...
        pitch_detect_lpc_sift(yfl',fsl,imf,L,R,fname);
    
% determine regions of pitch period with smooth connectivity
% try to extend regions based on secondary candidates
    ppdf=smoothpitch_sift(pp1,pp2,plevel1,plevel2,pthr1);
    fprintf('length: %d  \n',length(pp1));
    ppsav=pp1;

% plot out pitch period contours and confidence scores
    nl=length(ppdf);
    n=1:length(ppdf);
    
% clear graphics Panel 3
        reset(graphicPanel3);
        axes(graphicPanel3);
        cla;
        
% plot entire speech waveform in graphics Panel 3
        nfrm=length(ppdf);
        ss1=L/2+1-R;
        es1=L/2+1+nfrm*R;
        plot(ss1:es1,yfl(ss1:es1),'b');
        xpp=['Time in Samples;  fsd=',num2str(fsd),' samples/second'];
        xlabel(xpp);ylabel('Value');grid on;
        axis([L/2+1-R, L/2+1+nfrm*R, min(yf), max(yf)]);
    
% clear graphics Panel 2
        reset(graphicPanel2);
        axes(graphicPanel2);
        cla;
        
% plot unsmoothed pitch period contour in graphics Panel 2
    plot(n,ppdf,'r','LineWidth',2);
        axis([0 nfrm+1 min(ppdf)-.1 max(ppdf)+5]); grid on;
        xlabel('Frame Number'),ylabel('Pitch Period (Samples)'); 
        stitle=sprintf(' file: %s',fname); 
        
% clear graphics Panel 1
        reset(graphicPanel1);
        axes(graphicPanel1);
        cla;
        
% plot sift top peak level contour, second peak level contour, and peak 
% ratios of first-to-second peak levels -- all in graphics Panel 1 
    plot(n,plevel1(1:nl),'k','LineWidth',2),hold on;
    plot(n,plevel2(1:nl),'r','LineWidth',2),hold on;
    pratio=min(plevel1(1:nl)./plevel2(1:nl),3);
    pratio=max(pratio,0);
    plot(n,pratio,'b','LineWidth',2);
        axis([0 nfrm+1 0 max(pratio)+0.1]); grid on;
        xlabel('Frame Number'),ylabel('Confidence'),...
        legend('peak level','second peak level','peak ratios');
    
% compute median pitch period and median log confidence scores using Lmed
% median smoother
    p1m=medf(ppdf,Lmed,length(pp1));
    c1m=medf(plevel1(1:nl),Lmed,nl);
    ppm=p1m;
    plevel1m=c1m(1:nl);
    
% display fname and signal processing parameters in titleBox1
        stitle1=strcat('SIFT Pitch Detector (Unsmoothed) -- ',stitle);
        set(titleBox1,'string',stitle1);
        set(titleBox1,'FontSize',20);
end

% Callback for button11 -- run SIFT pitch detector -- smoothed
 function button11Callback(h,eventdata)
     
% clear graphics Panel 3
        reset(graphicPanel3);
        axes(graphicPanel3);
        cla;
        
% plot entire speech signal in graphics Panel 3
        nfrm=length(p1m);
        ss1=L/2+1-R;
        es1=L/2+1+nfrm*R;
        plot(ss1:es1,yfl(ss1:es1),'b');xlabel(xpp);
        ylabel('Value');grid on;
        axis([L/2+1-R, L/2+1+nfrm*R, min(yfl), max(yfl)]);
     
% clear graphics Panel 2
        reset(graphicPanel2);
        axes(graphicPanel2);
        cla;
        
% plot median-smoothed pitch period contour in graphics Panel 2
    plot(n,p1m(1:nl),'k','LineWidth',2),grid on,...
       xlabel('Frame Number'),ylabel('Pitch Period');
        axis([0 nfrm min(p1m)-0.5 max(p1m)+5]);
        stitle=sprintf(' file: %s, median smoothed (Lmed=5)',fname);
        
% clear graphics Panel 1
        reset(graphicPanel1);
        axes(graphicPanel1);
        cla;
        
% plot median-smoothed confidence score in graphics Panel 1
     plot(n,c1m(1:nl),'k','LineWidth',2), grid on,...
        xlabel('Frame Number'),ylabel('Confidence');
        axis([0 nfrm min(c1m)-0.1 max(c1m)+0.1]);
    
% display fname and signal processing features in titleBox1
        stitle1=strcat('SIFT Pitch Detector (Smoothed) -- ',stitle);
        set(titleBox1,'string',stitle1);
        set(titleBox1,'FontSize',20);
        
% save pitch perod contour (appropriately scaled to original sampling rate)
% in mat file
    ppmi=round(p1m'*fs/fsd);
    fsave=strcat('out_SIFT_',fname(1:length(fname)-4),'.mat');
    save(fsave,'ppmi');
    % save 'c:\data\matlab_gui\compare_pitch_period_contours\out_SIFT_pitch_period.mat' ppmi;
 end

% Callback for button12 -- close GUI
 function button12Callback(h,eventdata)
     close(gcf);
 end
end

Contact us