jdkmidi class library documentation

Copyright © 2004 J.D. Koftinoff Software, Ltd.

Released under the GNU General Public License (GPL)




Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

src/jdkmidi_keysig.cpp

Go to the documentation of this file.
00001 /*
00002  *  libjdkmidi-2004 C++ Class Library for MIDI
00003  *
00004  *  Copyright (C) 2004  J.D. Koftinoff Software, Ltd.
00005  *  www.jdkoftinoff.com
00006  *  jeffk@jdkoftinoff.com
00007  *
00008  *  *** RELEASED UNDER THE GNU GENERAL PUBLIC LICENSE (GPL) April 27, 2004 ***
00009  *
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 */
00024 /*
00025 **  Copyright 1986 to 1998 By J.D. Koftinoff Software, Ltd.
00026 **
00027 **  All rights reserved.
00028 **
00029 **  No one may duplicate this source code in any form for any reason
00030 **  without the written permission given by J.D. Koftinoff Software, Ltd.
00031 **
00032 */
00033 
00034 
00035 #include "jdkmidi/world.h"
00036 
00037 #include "jdkmidi/keysig.h"
00038 
00039 
00040 #ifndef DEBUG_MDKEYSIG
00041 # define DEBUG_MDKEYSIG 0
00042 #endif
00043 
00044 #if DEBUG_MDKEYSIG
00045 # undef DBG
00046 # define DBG(a) a
00047 #endif
00048 
00049 namespace jdkmidi
00050 {
00051   
00052   
00053   int MIDIKeySignature::sharp_list[7] = { 3, 0, 4, 1, 5, 2, 6 };
00054   int MIDIKeySignature::flat_list[7] =  { 6, 2, 5, 1, 4, 0, 3 };
00055   
00056   
00057   MIDIKeySignature::MIDIKeySignature()
00058   {
00059     ENTER( "MIDIKeySignature::MIDIKeySignature()" );
00060     use_sharps=true;
00061     sharp_flat=0;
00062     major=true;
00063     Reset();
00064   }
00065   
00066   MIDIKeySignature::MIDIKeySignature( const MIDIKeySignature &k )
00067   {
00068     ENTER( "MIDIKeySignature::MIDIKeySignature()" );  
00069     use_sharps=k.use_sharps;
00070     sharp_flat=k.sharp_flat;
00071     major=k.major;
00072     
00073     Reset();
00074   }
00075   
00076   
00077 //
00078 // Reset() generates the sharp/flat list based on sharp_flat, major,
00079 // and use_sharps.
00080 //
00081   
00082   void MIDIKeySignature::Reset()
00083   {
00084     ENTER( "MIDIKeySignature::Reset()" );
00085     if( sharp_flat < -7 )
00086       sharp_flat=-7;
00087     if( sharp_flat >7 )
00088       sharp_flat=7;
00089     
00090     for( int note=0; note<7; ++note )
00091       state[note]=ACCNatural;
00092     
00093     if( sharp_flat==0 )
00094     {
00095       // Key of C has no sharps or flats.
00096       // and any accidentals will be sharp
00097       
00098       use_sharps=true;
00099     }
00100     else if( sharp_flat>0 )
00101     {
00102       //
00103       // this key has a number of sharps in it.
00104       //
00105       
00106       use_sharps=true;
00107       
00108       for( short i=0; i<sharp_flat; ++i )
00109       {
00110         state[sharp_list[i]]=ACCSharp;
00111       }
00112     }
00113     else if( sharp_flat<0 )
00114     {
00115       //
00116       // this key has flats in it.
00117       // -sharp_flat is how many flats.
00118       //
00119       
00120       int flats= -sharp_flat;
00121       
00122       use_sharps=false;
00123       
00124       for( int i=0; i<flats; ++i )
00125       {
00126         state[ flat_list[i] ]=ACCFlat;
00127       }
00128       
00129     }
00130     
00131   }
00132   
00133   
00134   
00135   
00136   bool  MIDIKeySignature::ProcessWhiteNote( int in_note, int *out_note )
00137   {
00138     ENTER( "MIDIKeySignature::ProcessWhiteNote()" );
00139     //
00140     // check to see if this white note is allowed in the current
00141     // state.
00142     //
00143     
00144     if( state[in_note]==ACCNatural )
00145     {
00146       //
00147       // yes it is allowed, return it.
00148       //
00149       
00150       *out_note=in_note;
00151       
00152       //
00153       // return false to signify that this note doesn't need
00154       // an accidental.
00155       //
00156       
00157       return false;
00158     }
00159     else
00160     {
00161       //
00162       // no it was not allowed. We must change our state.
00163       // to allow it. return it.
00164       //
00165       
00166       *out_note=in_note;
00167       
00168       //
00169       // change the desired note to a natural
00170       //
00171       
00172       state[in_note]=ACCNatural;
00173       
00174       //
00175       // return true because it needed an accidental
00176       //
00177       
00178       return true;
00179     }
00180   }
00181   
00182   
00183   bool MIDIKeySignature::ProcessBlackNote( int in_note, int *out_note )
00184   {
00185     ENTER( "MIDIKeySignature::ProcessBlackNote()" );  
00186     //
00187     // if this note is already sharped,
00188     // return the note unchanged and return false
00189     // because no accidental was required
00190     
00191     if( state[in_note]==ACCSharp )
00192     {
00193       *out_note=in_note;
00194       return false;
00195     }
00196     
00197     //
00198     // if the next note is flatted, then we could use it
00199     // instead.
00200     //
00201     
00202     if( state[in_note+1]==ACCFlat )
00203     {
00204       *out_note=in_note+1;
00205       return false;
00206     }
00207     
00208     //
00209     // Couldn't find a black note. we gotta make one.
00210     // make a sharp if use_sharps==1
00211     
00212     if( use_sharps )
00213     {
00214       //
00215       // make this white note a sharp.
00216       //
00217       
00218       state[in_note]=ACCSharp;
00219       *out_note=in_note;
00220       
00221       //
00222       // Accidental required. return true.
00223       //
00224       return true;
00225     }
00226     else
00227     {
00228       //
00229       // make the next white note a flat.
00230       //
00231       
00232       state[in_note+1]=ACCFlat;
00233       *out_note=in_note+1;
00234       
00235       //
00236       // Accidental required. Return true.
00237       //
00238       
00239       return true;
00240     }
00241   }
00242   
00243   
00244   
00245 //
00246 // ConvertMIDINote() takes a real MIDI note number and converts it to a
00247 // white-key note number. it returns true if an Accidental is required.
00248 //
00249   
00250   bool MIDIKeySignature::ConvertMIDINote(
00251     int in_note,
00252     int *out_note
00253     )
00254   {
00255     ENTER( "MIDIKeySignature::ConvertMIDINote()" );
00256     
00257     int octave=in_note/12;
00258     int midi_note=in_note%12;
00259     int actual_note=0;
00260     bool  changed=false;
00261     
00262     switch( midi_note )
00263     {
00264     case 0:   // C
00265       changed=ProcessWhiteNote(0,&actual_note);
00266       break;
00267     case 2:   // D
00268       changed=ProcessWhiteNote(1,&actual_note);
00269       break;
00270     case 4:   // E
00271       changed=ProcessWhiteNote(2,&actual_note);
00272       break;
00273     case 5:   // F
00274       changed=ProcessWhiteNote(3,&actual_note);
00275       break;
00276     case 7:   // G
00277       changed=ProcessWhiteNote(4,&actual_note);
00278       break;
00279     case 9:   // A
00280       changed=ProcessWhiteNote(5,&actual_note);
00281       break;
00282     case 11:  // B
00283       changed=ProcessWhiteNote(6,&actual_note);
00284       break;
00285       
00286     case 1:   // C#
00287       changed=ProcessBlackNote(0,&actual_note);
00288       break;
00289     case 3:   // D#
00290       changed=ProcessBlackNote(1,&actual_note);
00291       break;
00292     case 6:   // F#
00293       changed=ProcessBlackNote(3,&actual_note);
00294       break;
00295     case 8:   // G#
00296       changed=ProcessBlackNote(4,&actual_note);
00297       break;
00298     case 10:  // A#
00299       changed=ProcessBlackNote(5,&actual_note);
00300       break;
00301     };
00302     
00303     *out_note = (octave*7) + actual_note;
00304     return changed;
00305     
00306   }
00307   
00308 }