diff chordtools/parsechord.m @ 1:8973548174c1 tip

adding tools to repo
author christopherh
date Mon, 06 May 2013 14:43:47 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chordtools/parsechord.m	Mon May 06 14:43:47 2013 +0100
@@ -0,0 +1,274 @@
+%
+%PARSECHORD parse chord symbol to its constituent string elements
+% 
+% [rootnote, shorthand, intervals, bass, success, errormessage]
+%                                   = parsechord(chord, {verbose})
+% 	
+% Parses the chord symbol string "chord" into its separate string elements. 
+% 
+% NOTE: This function does not check validity of the chord elements, it
+% merely separates them according to the chord syntax. 
+% To obtain chord elements with included validity check use GETCHORDINFO.
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise.
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 	
+% returns:  rootnote        (note string)
+%           shorthand       (shorthand string)
+%           intervals       (interval-list string)
+%           bass            (interval string)
+%           success         (boolean)
+%           errormessage    (string)
+%
+% See also: getchordinfo                     
+%
+% Author: Christopher Harte, March 2009
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit V2.0  
+%
+% The C4DM Chord Toolkit is free software; you can redistribute it and/or 
+% modify it under the terms of the GNU General Public License as published 
+% by the Free Software Foundation; either version 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function  [rootnote, shorthand, intervals, bass, success, errormessage] = parsechord(chord, verbose)
+	
+% set verbose default to 0
+if nargin <2
+    verbose = 0;
+end
+
+ilength = length(chord);
+
+% initialise variables
+errormessage = '';
+rootnote = '';
+shorthand = '';
+intervals = '';
+bass = '';
+
+success = 1;
+index = 1;
+
+
+% check for 'no chord' symbol
+if chord(index) == 'N'
+    rootnote = chord(index);
+    index = index +1;
+    % check to see there are no further characters
+    if(index<=ilength)
+        errormessage = sprintf(['Error in parsechord: \nExtra characters after "no chord" symbol "' chord '"\n']); 
+        success = 0;
+    end
+else
+% parse thechord symbol
+
+    % the first part of the symbol before a switch character should be the root note
+    while ((index <=ilength ))
+    
+        if (chord(index) ==  ':') || (chord(index) ==  '/') || ...
+           (chord(index) ==  '(') || (chord(index) ==  ')')
+            
+            break
+        end
+
+        rootnote(index) = chord(index);
+        index = index+1;
+    
+        if(index > ilength) || (chord(index) == '/')
+            % if chord is a rootnote on its own or with just a bass note 
+            % then it is a major chord therefore set shorthand to 'maj'
+            shorthand = 'maj';
+        end
+    end
+    
+    % initialise booleans to record which switch characters we have found
+    colon = 0;
+    openbracket = 0;
+    closebracket = 0;
+    slash = 0;
+    
+    % parse the rest of the chord symbol
+    while(index <= ilength)
+        
+        % reset temporary index 
+        tempindex = 1;
+        
+       switch(chord(index))
+       
+           case ':'  
+                        
+               % if we find a colon after any switch characters have 
+               % already occured then the symbol is incorrect 
+               if (colon || openbracket || closebracket || slash)
+                    errormessage = sprintf(['Error in parsechord: \nIncorrect character sequence in chord "' chord '"\n']); 
+                    success = 0;
+                    index = ilength+1;
+               else
+                
+                   % found the first instance of a colon character
+                   colon = 1;
+                   
+                   index = index +1;
+                   
+                   if(index > ilength)
+                        errormessage = sprintf(['Error in parsechord: \nFound ":" at end of chord string "' chord '"\n']); 
+                        success = 0; 
+                   end
+                   % colon should be followed by a shorthand string or
+                   % an interval list contained in brackets
+                   while (index <= ilength)
+                       
+                       if (chord(index) ==  ':') || (chord(index) ==  '/') || ...
+                          (chord(index) ==  '(') || (chord(index) ==  ')')
+
+                           break
+                       end
+
+                       % copy character into shorthand
+                       shorthand(tempindex) = chord(index);
+                       index = index +1;
+                       tempindex = tempindex +1;
+
+                   end
+               
+               end
+               
+           case '('
+               
+               % if we have had a colon but no other switch charaters then
+               % an open bracket signifies the start of the interval list
+               if (colon && ~slash && ~closebracket && ~openbracket) 
+                   
+                   openbracket = 1;
+                   
+                   index = index +1;
+                   
+                   while (index <= ilength)
+
+                       if (chord(index) ==  ':') || (chord(index) ==  '/') || ...
+                          (chord(index) ==  '(') || (chord(index) ==  ')')
+
+                           break
+                       end
+                       
+                       % copy character into intervals
+                       intervals(tempindex) = chord(index);
+                       index = index +1;
+                       tempindex = tempindex +1;
+
+                   end
+                   
+                   if(index > ilength)
+                        errormessage = sprintf(['Error in parsechord: \nInterval list brackets not closed in chord "' chord '"\n']); 
+                        success = 0; 
+                   end
+                   
+               else
+                   errormessage = sprintf(['Error in parsechord: \nIncorrect character sequence in chord "' chord '"\n']); 
+                   success = 0;
+                   index = ilength +1;
+               end
+               
+           case ')'
+               
+               
+               % if we find a closing bracket then we should either be at
+               % the end of the symbol or there should be a slash to follow
+               if (colon && openbracket && ~slash && ~closebracket) 
+                   
+                   closebracket = 1;
+                   index = index +1;
+                   
+               else
+                   errormessage = sprintf(['Error in parsechord: \nIncorrect character sequence in chord "' chord '"\n']); 
+                   success = 0;
+                   index = ilength +1;
+               end
+               
+               % check to see that the brackets contained something
+               if isempty(intervals)
+                   errormessage = sprintf(['Error in parsechord: \nBrackets contain no intervals in chord "' chord '"\n']); 
+                   success = 0;
+                   index = ilength +1;
+               end
+               
+               
+           case '/'
+               % forward slash should be followed by an interval string
+              
+                   slash = 1;
+
+                   % move on to next character to process the expected bass interval
+                   index = index +1;
+                                     
+                   % check that we haven't overun the end of the symbol string
+                   if(index > ilength)
+                        errormessage = sprintf(['Error in parsechord: \nNo bass interval "/" at end of chord "' chord '"\n']); 
+                        success = 0; 
+                   end
+                   
+                   % check that if we have had an open bracket that it also
+                   % had a closed bracket
+                   if(xor(openbracket,closebracket))
+                        errormessage = sprintf(['Error in parsechord: \nFound "/" before closing bracket in chord "' chord '"\n']); 
+                        success = 0; 
+                        index = ilength +1;
+                   end
+
+                   % check that the previous character was not a ':'
+                   if(chord(index-2) == ':')
+                        errormessage = sprintf(['Error in parsechord: \nFound "/" directly after ":" in chord "' chord '"\n']); 
+                        success = 0; 
+                        index = ilength +1;
+                   end
+
+                   
+                   while( index <= ilength )
+                       
+                       % if we find a switch character after a slash then
+                       % the symbol is incorrect
+                       if (chord(index) ==  ':') || (chord(index) ==  '/') || ...
+                          (chord(index) ==  '(') || (chord(index) ==  ')')
+         
+                           errormessage = sprintf(['Error in parsechord: \nIncorrect character sequence in chord "' chord '"\n']); 
+                           success = 0;
+                           index = ilength +1;
+                       
+                       else
+
+                           % copy remaining characters into bass
+                           bass(tempindex) = chord(index);
+                           index = index +1;
+                           tempindex = tempindex +1;
+                       end
+                   end
+                            
+           otherwise
+                errormessage = sprintf(['Error in parsechord: \nUnrecognised chord "' chord '"\n']); 
+                success = 0;
+                index = ilength + 1;
+       end
+            
+    end
+end            
+            
+if (verbose == 1) && (success == 0)
+    fprintf(1,errormessage);
+end
+        
+