www.gusucode.com > 声音的处理有:LPC,FFT,共振峰,频谱源码程序 > siganlandsystemusingMatlab/SSUM/physmodel/ksstring/midird3.m

    function [midi,info,ext,ms_per_quarter,ms_per_tick] = midird3(fname,txtname)
% function [midi,info,ext,ms_per_quarter,ms_per_tick] = midird3(fname,txtname)
%
%  This function reads Standard MIDI Files (SMFs) and returns their contents
%  in the two structures midi and info.
%
%     midi     is a struct array containing one field for each track of the
%              midi file. Within each field, the midi notes are given in
%              the format
%
%              (delta time,absolute time, midi note number, note duration, note velocity,
%               channel)
%
%     info     contains all sideinfo from the header chunk as well as meter and time
%              information from the MIDI meta events
%
%     ext      is all extended information besides notes contained in the MIDI file.
%              This is needed, e.g., to reproduce the binary MIDI files
%              using midiwr.m
%              
%              -> All system exclusive data are stored in ext
%
%              Format of ext:  (track abstime [binary MIDI sequence])
%
%     ms_per_quarter     milliseconds per quarter note, if indicated by
%              MIDI-file (set to 0, if no information on time-coding is
%              found in MIDI-file)
%
%     ms_per_tick       milliseconds per MIDI tick, if indicated by
%              MIDI-file (set to 0, if no information on time-coding is
%              found in MIDI-file)
%
%  Inputs:    fname     Name of input MIDI-File
%
%			  (optional) txtname   Name of Output-Textfile
%
%             If the optional second argument txtname is used, a text
%             version of the MIDI-file is written to a file named textname
%
%   Changes:  * Frank Kurth, Feb., 26th, 2004: Rework to cope with wrongly
%             formatted SMFs
%             * Andreas Ribbrock, Apr., 14th, 2004: Stabilized w.r.t. wrongly
%             formatted SMFiles
%             * Frank Kurth, May, 11th, 2004: Incorporated functionality to
%             read time-coding from SMF (by Hinnerk Feldwisch and Meinard M黮ler)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%   Last changes by Frank Kurth, May, 11th, 2004
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
VLQLEN = 4;    % Length of variable length quantities, currently == 4 
TUPLEN = 6;

% The following are define global for use in the subfunctions within
% this file:

global smf;
global abstime;
%global ext;
%global extptr;

% some constants

UNDEF = -1; NOTEON = 0; NOTEOFF = 1; POLYAT = 2; CONTROLCHANGE = 3; PROGCHANGE = 4;
CHANNELAT = 5; PITCHWHEEL = 6; EXCEPT = 7;

% -fk 25.02.04

data = zeros(1,2);

% open input file

fid = fopen(fname,'r');

if fid < 0
   disp(['midird3: Error opening MIDI file: ' fname]);
   return;
end

% check if output file (MIDIasText) is requested

if nargin > 1
   
   TXT = 1;
   fidtxt = fopen(txtname,'w');
   if fid < 0
   	disp('midird3: Error opening output file!');
      fclose(fid);
      return;
	end

else
   TXT = 0;
end

% read full MIDI file

smf = [fread(fid,inf,'uint8')' zeros(1,10)];
ptr = 1;

extptr = 1;
status = 255;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Read MIDI Track header
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ptr = NextValidHeader(ptr);

if(ptr <0 | ptr+4 > length(smf) | ptr+7 > length(smf))
   disp('Midi file format error on line 99 of midird3');
   fclose(fid);
   info = cell(0,0);
   midi = cell(0,0);
   ext  = cell(0,0);
   return;
end

len = Read32(smf(ptr+4:ptr+7));

ptr = ptr + 8;                % 'MThd' 

if(ptr <0 | ptr+1 > length(smf))
   disp('Midi file format error on line 110 of midird3');
   fclose(fid);
   info = cell(0,0);
   midi = cell(0,0);
   ext  = cell(0,0);
   return;
end
info.format = Read16(smf(ptr:ptr+1));

if(ptr <0 | ptr+2 > length(smf) | ptr+3 > length(smf))
   disp('Midi file format error on line 118 of midird3');
   fclose(fid);
   info = cell(0,0);
   midi = cell(0,0);
   ext  = cell(0,0);
   return;
end
info.ntrks  = Read16(smf(ptr+2:ptr+3));
if smf(ptr+4) < 0
   info.division.up = double(uint8(smf(ptr+4)));
   info.division.low = smf(ptr+5);
   info.division.main = inf;
else
   info.division.main = Read16(smf(ptr+4:ptr+5));
   info.division.up = inf;
   info.division.low = inf;
end

if TXT
   
   fprintf(fidtxt,'MIDI Header Chunk\n\n');
   fprintf(fidtxt,'MIDI File Format: %d \n',info.format);
   fprintf(fidtxt,'No. of Tracks: %d\n',info.ntrks);
   if smf(ptr+4) < 0
   	fprintf(fidtxt,'Time Division: (%d,%d)\n',[info.division.up info.division.low]);   
   else
      fprintf(fidtxt,'Time Division: %d\n',info.division.main);         
   end
   
end

ptr = ptr + len;					% 32BitLength,  the length should be 6 in SMFs

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Read Tracks
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

midi = cell(1,info.ntrks);

abstime = 0;

for k = 1:info.ntrks
   
   if(ptr < 1 | ptr > length(smf))
      disp('Midi file format error on line 162 of midird3');
      fclose(fid);
      info = cell(0,0);
      midi = cell(0,0);
      ext  = cell(0,0);
      return;
   end
   
   ptr = NextValidHeader(ptr);
   
   if(ptr < 1 | ptr > length(smf))
      disp('Midi file format error on line 171 of midird3');
      fclose(fid);
      info = cell(0,0);
      midi = cell(0,0);
      ext  = cell(0,0);
      return;
   end

   
   ptrackstart = ptr;
   
   if TXT
      
      fprintf(fidtxt,'---------------------------------------------------------------------------\n');
      fprintf(fidtxt,'MIDI Track Chunk #%d\n\n',k-1);
      
   end
   
   s = char(smf(ptr:ptr+3));
   %s = sprintf('%s',smf(ptr:ptr+3))
   if(~strcmp(s,'MTrk'))
       s = sprintf('midird3: MTrk expected, %s found!',smf(ptr:ptr+3));
      disp(s);
      return;
   end
   tracklen = Read32(smf(ptr+4:ptr+7));    % track length
   ptr = ptr + 8;									 % track start after header
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % start: process track
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   
   notes = zeros(tracklen,TUPLEN);				 % faster to create array at once
   notepos = 1;
   runningstatus.cmd = UNDEF;
   runningstatus.channel = UNDEF;
   actnotes = ones(1,TUPLEN)*-1;
   uniqueID = -2;
   
   if info.format ~= 2							 % Note: abstime (here) is independent of the
      abstime = 0;                         %       time signature which is eventually
   end												 %       present in the MIDI file (Meta Event)
   													 %       abstime only counts delta ticks
                                           
   while ptr <= ptrackstart + 8 + tracklen % start: track loop
      
      if(ptr+VLQLEN-1 <0 | ptr+VLQLEN-1 > length(smf)) 
         disp('Midi file format error on line 215 of midird3');
      	fclose(fid);
      	info = cell(0,0);
        midi = cell(0,0);
        ext  = cell(0,0);
	      return;
      end
      
      
      if(ptr <1 | (ptr+VLQLEN-1) > length(smf))
         info = cell(0,0);
         midi = cell(0,0);
         ext  = cell(0,0);
			disp('Midi file format error on line 224 of midird3');
         fclose(fid);
      	return;   
      end
      
      
      [delta,offs] = readvarlenintern(smf(ptr:ptr+VLQLEN-1));
      
      if(delta == 0 & offs == 0)
         info = cell(0,0);
         midi = cell(0,0);
         ext  = cell(0,0);
	     disp('Midi file format error on line 234 of midird3');
         fclose(fid);
      	return;   
      end
      
      abstime = abstime + delta;
      ptr = ptr+offs;
    
      eventstring = sprintf('%d\t\t\t\t',delta);         
         
      next = double(uint8(smf(ptr)));
      
      if(bitand(next,128))	 							 % status byte found if expn TRUE
         										    % evaluate new command (->running status)
         status = next;                                  
         if TXT                                 
             eventstring = [eventstring sprintf('Status %x ',next)];                                  
         end    
         channel = bitand(next,15);
                        
         switch bitand(next,240)					 % &F0
            
            case 144,				             % $90, NOTEON
               runningstatus.cmd = NOTEON;
               runningstatus.channel = channel;
               ptr = ptr + 1;
            case 128				             % $80, NOTEOFF
               runningstatus.cmd = NOTEOFF;  
               runningstatus.channel = channel;  
               ptr = ptr + 1;
            case 160,				 % $A0, POLYAT
               runningstatus.cmd = POLYAT;
               runningstatus.channel = channel;
               ptr = ptr + 1;
            case 176,				 % $B0, CONTROLCHANGE
               runningstatus.cmd = CONTROLCHANGE;
               runningstatus.channel = channel;
               ptr = ptr + 1;
            case 192,            % $C0, PROGCHANGE
               runningstatus.cmd = PROGCHANGE;
               runningstatus.channel = channel;
               ptr = ptr + 1;
			case 208,				 % $D0, CHANNELAT
               runningstatus.cmd = CHANNELAT;
               runningstatus.channel = channel;
            	ptr = ptr + 1;   
            case 224,				 % $E0, PITCHWHEEL
               runningstatus.cmd = PITCHWHEEL;
               runningstatus.channel = channel;
               ptr = ptr + 1;
            case 240,				 % $F0, EXCEPT
               runningstatus.cmd = EXCEPT;
               
         end    % switch
         
      end    % if
      
      % according to the MIDI-BNF there may be real-time events 
      % before each of the data bytes: we have overread them  
      
      statusnibble = bitand(double(uint8(next)),240)/16;
            
      if statusnibble<=14
         
         data = [];
         offset = 0;
         
         if (statusnibble == 12) | (statusnibble == 13)
            bytes = 1;
         else
            bytes = 2;
         end
         %[data,offset,eventstring] = GetDataBytes(bytes,ptr,eventstring,k);
         
         %%%%%%%%%%%%%%%%%%%%%%%
         data = zeros(1,2); offset = 0;
    	   found = 0;
    
		   while found < bytes
       
        	if(double(uint8(smf(ptr+offset)))<248)
         	  data(found+1) = double(uint8(smf(ptr+offset)));
              found = found + 1;
         	else
              eventstring = [eventstring sprintf('Sys Realtime: %x ',double(uint8(smf(ptr+offset))))];
          
 		      ext(extptr).track = k;
              ext(extptr).abstime = abstime;
              ext(extptr).midistring = smf(ptr+offset);
              extptr = extptr + 1;
         	end
         
            offset = offset + 1;
         end
         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
         ptr = ptr + offset;
 
      end
 
      flag = 0;

      if (runningstatus.cmd == NOTEON) & (data(2)==0)
      
          runningstatus.cmd = NOTEOFF;
          flag = 1;
          
      end
      
      switch runningstatus.cmd
         
      	case NOTEON,
                        
            idx12 = max(find(actnotes(:,3)==data(1)& actnotes(:,6)==runningstatus.channel));
                            % note number
            
            if ~isempty(idx12)
               idx = find(actnotes(idx12,4)==notes(:,4));           % compare temporary unique ID
               notes(idx,4) = abstime-notes(idx,2); % new abstime        
               [sx,sy] = size(actnotes);
               if(idx12 == sx)
                      actnotes = [actnotes(1:idx12-1,:)];
               else
                      actnotes = [actnotes(1:idx12-1,:); actnotes(idx12+1:sx,:)]; 
               end      
            end
            
            if notepos == 1
                
                Delta = abstime;
                
            else 
                
                Delta = abstime - notes(notepos-1,2);
                
            end              
            
            actnotes = [actnotes; Delta abstime data(1) uniqueID data(2) ...
                  runningstatus.channel];
            notes(notepos,:) = [Delta abstime data(1) uniqueID data(2) ...
                  runningstatus.channel];
            notepos = notepos + 1;
            uniqueID = uniqueID - 1;
            
            if TXT
               eventstring = [eventstring sprintf('NOTE ON, Channel %d, Note # %d, Velocity %d ', ...
                 [runningstatus.channel data(1) data(2)])]; 
            end
            
         case NOTEOFF,
              
            idx12 = max(find(actnotes(:,3)==data(1)& actnotes(:,6)==runningstatus.channel));
            
            posn = max(1,notepos-7);
            if ~isempty(idx12) 
               idx = find(actnotes(idx12,4)==notes(posn:notepos,4))...
                      + posn-1; % compare temporary unique ID
               if isempty(idx)
                  idx = find(actnotes(idx12,4)==notes(1:posn,4));    
               end    
               notes(idx,4) = abstime-notes(idx,2); % new abstime         
               [sx,sy] = size(actnotes);
               if(idx12 == sx)
                      actnotes = [actnotes(1:idx12-1,:)];
               else
                      actnotes = [actnotes(1:idx12-1,:); actnotes(idx12+1:sx,:)]; 
               end      
              
            end
            
            if TXT
               eventstring = [eventstring sprintf('NOTE OFF, Channel %d, Note # %d, Velocity %d ', ...
                 [runningstatus.channel data(1) data(2)])]; 
            end
           
            if flag == 1
                
                flag = 0;
                runningstatus.cmd = NOTEON;
                
            end
                        
         case POLYAT,
            
            eventstring = [eventstring sprintf('POLYPHONIC AFTERTOUCH, Channel %d, Note # %d, AT-Pressure %d ', ...
                 [runningstatus.channel data(1) data(2)])]; 
           
           ext(extptr).track = k;
           ext(extptr).abstime = abstime;
           ext(extptr).midistring = [status data(1) data(2)];
           extptr = extptr + 1;
           
         case CONTROLCHANGE,
            
            eventstring = [eventstring sprintf('CONTROL CHANGE, Channel %d, Controller %d, Value %d ', ...
                 [runningstatus.channel data(1) data(2)])];               
           
           ext(extptr).track = k;
           ext(extptr).abstime = abstime;
           ext(extptr).midistring = [status data(1) data(2)];
           extptr = extptr + 1;

            switch(data(1))
               
            	case 7,
                  eventstring = [eventstring sprintf('(Main Volume) ')];
               case 39,
                  eventstring = [eventstring sprintf('(Main Volume) ')];
                     
            end     
            
            if((data(1)>=hex2dec('7B')) & (data(1)<=hex2dec('7F')))      % this implies/includes ALL NOTES OFF
                [lx,ly] = size(actnotes);
                for kk=2:lx
                 	idx = find(actnotes(kk,4)==notes(:,4));           % compare temporary
               	notes(idx,4) = abstime-notes(idx,2); % new abstime         % uniqueID              				      
                end    
                actnotes = ones(1,TUPLEN)*-1;

            end   
               
         case PROGCHANGE,
            
            eventstring = [eventstring sprintf('PROGRAM CHANGE, Channel %d, Program # %d ', ...
                 [runningstatus.channel data(1)])]; 
           
            ext(extptr).track = k;
            ext(extptr).abstime = abstime;
            ext(extptr).midistring = [status data(1)];
            extptr = extptr + 1;
 
         case CHANNELAT,
            
            eventstring = [eventstring sprintf('CHANNEL AFTERTOUCH, Channel %d, AT-Pressure # %d ', ...
                 [runningstatus.channel data(1)])]; 
           
            ext(extptr).track = k;
            ext(extptr).abstime = abstime;
            ext(extptr).midistring = [status data(1)];
            extptr = extptr + 1;

         case PITCHWHEEL,
              
     			eventstring = [eventstring sprintf('PITCH WHEEL CHANGE, Channel %d, MSB: %d, LSB: %d ', ...
                 [runningstatus.channel data(1) data(2)])];        
           
            ext(extptr).track = k;
            ext(extptr).abstime = abstime;
            ext(extptr).midistring = [status data(1) data(2)];
            extptr = extptr + 1;

         case EXCEPT,
              
            switch(next)
                                        
               case 240,				% $F0, SysExclusive
                    [len,offs] = readvarlenintern(smf(ptr+1:ptr+VLQLEN));
                    eventstring = [eventstring sprintf('SysEx %x, Length %d ', ...
                          [next len])];
                    ext(extptr).track = k;
                    ext(extptr).abstime = abstime;
                    ext(extptr).midistring = smf(ptr:ptr+offs+len);
                    extptr = extptr + 1;

                    ptr = ptr + 1 + offs + len;
                    
               case 255,				% $FF Meta event
                    metacmd = double(uint8(smf(ptr+1)));
                    [len,offs] = readvarlenintern(smf(ptr+2:ptr+VLQLEN+1));
						  eventstring = [eventstring sprintf('Meta %x ', ...
                             [next])];
                       
                    ext(extptr).track = k;
                    ext(extptr).abstime = abstime;
                    ext(extptr).midistring = smf(ptr:ptr+offs+len+1);
                    extptr = extptr + 1;
                     
                    if ((smf(ptr+1)>0) & (smf(ptr+1)<8))
                       
                       eventstring = [eventstring smf(ptr+2+offs:ptr+1+offs+len)];
                       
                    end   
                       
                    switch(smf(ptr+1))
               
            				case 0,
                  			eventstring = [eventstring sprintf('Sequence %d ',Read16(smf(ptr+3:ptr+4)))];
                        case 47            % hex2dec('2F'),
                  			eventstring = [eventstring sprintf('End of Track')];
                           [lx,ly] = size(actnotes);
                           for kk=2:lx
                           	idx = find(actnotes(kk,4)==notes(:,4));           % compare temporary
               					notes(idx,4) = abstime-notes(idx,2); % new abstime         % uniqueID              				      
                           end    
                           actnotes = ones(1,TUPLEN)*-1;
                        case 81,            % hex2dec('51'),
                           eventstring = [eventstring sprintf('Set Tempo %x%x%x ',...
                                 [double(uint8(smf(ptr+3:ptr+5)))])];
							   case 84,            % hex2dec('54'),
                           eventstring = [eventstring sprintf('SMPTE Offset %x %x %x %x ',...
                                 [double(uint8(smf(ptr+3:ptr+6)))])];
								case 88,            % hex2dec('58'),
                           eventstring = [eventstring sprintf('Time Signature %x %x %x %x ',...
                                 [double(uint8(smf(ptr+3:ptr+6)))])];
                    		case 89,            % hex2dec('59'),
                           eventstring = [eventstring sprintf('Key Signature sf: %d mi: %d ',[smf(ptr+3:ptr+4)])];
						  		case 127,           % hex2dec('7F'),
                           eventstring = [eventstring sprintf('Sequencer specific Meta, Length %d ',[len])];
                    end         
                    ptr = ptr + 2 + offs + len;	
                    
               case 247, 				% $F7, SysExclusive
                    [len,offs] = readvarlenintern(smf(ptr+1:ptr+VLQLEN));
						  eventstring = [eventstring sprintf('SysEx %x, Length %d ', ...
                 			[next len])];
                    
                    ext(extptr).track = k;
                    ext(extptr).abstime = abstime;
                    ext(extptr).midistring = smf(ptr:ptr+offs+len);
                    extptr = extptr + 1;
                    
                    ptr = ptr + 1 + offs + len;
                  
               case 241,  			% $F1, System Common (undef.)
                  	eventstring = [eventstring sprintf('System Common %x ', ...
                           [next])];
                     ptr = ptr + 3;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = 241;
                     extptr = extptr + 1;
               
               case 242,				% $F2, Song Position Pointer (SPP)
                  	eventstring = [eventstring sprintf('Song Position Pointer %x ', ...
                           [next])];
                     ptr = ptr + 3;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr:ptr+2);
                     extptr = extptr + 1;

                  
               case 243,				% $F3, Sys Common; Song Select (Song #)
                  	eventstring = [eventstring sprintf('Song Select %x ', ...
                           [next])];
							ptr = ptr + 2;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr:ptr+1);
                     extptr = extptr + 1;

                 
               case 244,				% $F4, Sys Common - undefined
                  	eventstring = [eventstring sprintf('System Common (undef.) %x ', ...
                           [next])];
                     ptr = ptr + 3;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr:ptr+2);
                     extptr = extptr + 1;
                  
               case 245,				% $F5, Sys Common - undefined
                  	eventstring = [eventstring sprintf('System Common (undef.) %x ', ...
                           [next])];
                     ptr = ptr + 3;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr:ptr+2);
                     extptr = extptr + 1;
                  
               case 246,				% $F6, Sys Common Tune Request
                    	eventstring = [eventstring sprintf('System Common Tune Request %x ', ...
                          [next])];
                     ptr = ptr + 1;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr);
                     extptr = extptr + 1;
                  
               case 248,				% $F8, Sys Real Time 
                    	eventstring = [eventstring sprintf('System Real Time %x ', ...
                             [next])];
                     ptr = ptr + 1;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr);
                     extptr = extptr + 1;
                  
               case 249,    			% $F9, Sys Real Time 
                    	eventstring = [eventstring sprintf('System Real Time %x ', ...
                             [next])];
                     ptr = ptr + 1;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr);
                     extptr = extptr + 1;
           
               case 250,				% $FA, Sys Real Time 
                    	eventstring = [eventstring sprintf('System Real Time %x ', ...
                             [next])];
                     ptr = ptr + 1;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr);
                     extptr = extptr + 1;
               
               case 251,				% $FB, Sys Real Time 
                    	eventstring = [eventstring sprintf('System Real Time %x ', ...
                             [next])];
                     ptr = ptr + 1;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr);
                     extptr = extptr + 1;

               case 252,				% $FC, Sys Real Time 
                    	eventstring = [eventstring sprintf('System Real Time %x ', ...
                             [next])];
                     ptr = ptr + 1;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr);
                     extptr = extptr + 1;
                
               case 253,				% $FD, Sys Real Time 
                    	eventstring = [eventstring sprintf('System Real Time %x ', ...
                             [next])];
                     ptr = ptr + 1;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr);
                     extptr = extptr + 1;
                 
               case 254, 				% $FE, Sys Real Time 
                    	eventstring = [eventstring sprintf('System Real Time %x ', ...
                             [next])];
                     ptr = ptr + 1;
                     ext(extptr).track = k;
                     ext(extptr).abstime = abstime;
                     ext(extptr).midistring = smf(ptr);
                     extptr = extptr + 1;           
             						  	                   
            end 
            
         otherwise,
            disp('midird3: Undefined running status!');
            disp('Position:');
            ptr
            if TXT
               eventstring = [eventstring sprintf('\n')];
         		fprintf(fidtxt,eventstring);
            	fprintf(fidtxt,'Code at Errorposition: %x \n',smf(ptr:ptr + 10));   
            	fclose(fidtxt);
            end
  				fclose(fid);
				return;
            
      end				% switch running status
      
      if TXT
         eventstring = [eventstring sprintf('\n')];
         fprintf(fidtxt,eventstring);
      end
      
   end				% End: track loop
   
   midi{k} = notes(1:notepos-1,:);
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % end: process track
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

   ptr = ptrackstart + 8 + tracklen;       % fwd to next track/chunk
   
end

if TXT
	fclose(fidtxt);
end   
fclose(fid);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% extract tick resolution 
%
% ms_per_tick         milliseconds per tick
% ticks_per_quarter   ticks per quarter note
% ms_per_quarter      milliseconds per quarter note
%
% Determines the time per tick from the binary MIDI-data in ext.
% Additional functionality by Hinnerk Feldwisch and Meinard M黮ler
% added to midird3 by Frank Kurth, 11.05.2004
%
%>>>BEGIN>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ticks_per_quarter = info.division.main;

exe = [];

for I=1:length(ext)
    ex=ext(I);
    if(max(abs(ex.midistring(1:2)-[255 81]))==0)
      exe = ex.midistring(4:end);
    end
end

if(length(exe) == 3)
    microsec_per_quarter = (exe(1) * 256 + exe(2)) * 256 + exe(3);
else
    microsec_per_quarter = 0;    % return zero, if no time-coding was found
end

ms_per_quarter = microsec_per_quarter/1000;      % == 0, if no time-coding was found  !
ms_per_tick = ms_per_quarter/ticks_per_quarter;  % == 0, if no time-coding was found  !

%<<<END<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% End of main program
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%
% At the moment, we know Chunks with the IDs 'MThd' and 'MTrk'
% The following function sets the pointer to the starting index within smf
% (it is assumed that the MIDI file is a contiguous sequence of chunks)
%

function p = NextValidHeader(pt)

global smf;

s = char(smf(pt:pt+3));

%s = sprintf('%s',smf(pt:pt+3));
% DDD
%disp(s);
% DDD

while(~strcmp(s,'MThd') & ~strcmp(s,'MTrk'))
   if(pt < 1 | (pt+3) > length(smf))
      p = -1;
      return;
   end
   
   len = Read32(smf(pt:pt+3));
   pt = pt + 4 + 4 +len;           % HeaderId + 32BitLength + Length
   if pt > length(smf)
      p = -1;
      return
   end
end   

p = pt;
return;

%
% Read 4 Byte Word
%

function val = Read32(stream)

  val = double(uint8(stream(1)));

  for k = 2:4
  		val = val*256 + double(uint8(stream(k)));
  end   

return;

%
% Read 2 Byte Word
%

function val = Read16(stream)

	val = double(uint8(stream(1)))*256 + double(uint8(stream(2)));
 
return;

%
% overread real time messages
%

function [dat,offs,evstring] = GetDataBytes(byte,pt,evstring)

    global smf;
    global abstime;
    
    dat = zeros(1,2);
    offs = 0;
    found = 0;
    
    while found < byte
       
       if(double(uint8(smf(pt+offs)))<248)
          dat(found+1) = double(uint8(smf(pt+offs)));
          found = found + 1;
       else
         evstring = [evstring sprintf('Sys Realtime: %x ',double(uint8(smf(pt+offs))))];
       end
       offs = offs + 1;
       
    end
    
return;

%
% readvarleninternIntern
%

function [value,len] = readvarlenintern(stream)
% function [value,len] = readvarlenintern(stream)   read MIDI variable length quantity number
%
%  'value' returns the resulting Number, len is the number of values read from the
%  input smf-stream 'stream'
%
len = 1;
value = 0;
if(len > length(stream))
   value = 0;
   len = 0;
   return;
end

act = double(uint8(stream(len)));
value = act;
if(bitand(act,128))
   
   value = bitand(act,127);
   while bitand(act,128)
      len = len + 1;
      if(len > length(stream))
   		value = 0;
		   len = 0;
		   return;
		end
      act = double(uint8(stream(len)));
      value = value * 128 + bitand(act,127);
   end

end