C:/Musimathics_local/Musimat/include/Pitch.h

Go to the documentation of this file.
00001 /* $Revision: 1.4 $ $Date: 2006/09/12 17:37:40 $ $Author: dgl $ $Name:  $ $Id: _pitch_8h-source.html,v 1.4 2006/09/12 17:37:40 dgl Exp $ */
00002 #ifndef PITCH_H
00003 #define PITCH_H
00004 
00005 // The Musimat Tutorial © 2006 Gareth Loy
00006 // Derived from Chapter 9 and Appendix B of "Musimathics Vol. 1" © 2006 Gareth Loy 
00007 // and published exclusively by The MIT Press.
00008 // This program is released WITHOUT ANY WARRANTY; without even the implied 
00009 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
00010 // For information on usage and redistribution, and for a DISCLAIMER OF ALL
00011 // WARRANTIES, see the file, "LICENSE.txt," in this distribution.
00012 // "Musimathics" is available here:     http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=10916
00013 // Gareth Loy's Musimathics website:    http://www.musimathics.com/
00014 // The Musimat website:                 http://www.musimat.com/
00015 // This program is released under the terms of the GNU General Public License
00016 // available here:                      http://www.gnu.org/licenses/gpl.txt
00017 
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <iostream>
00025 using namespace std;
00026 #include <math.h>
00027 
00032 
00034 class Pitch
00035 {
00036         friend ostream& operator<<(ostream&, Pitch&);
00037         friend istream& operator>>(istream&, Pitch&);
00038 
00039         friend Bool operator==(Integer& i, Pitch& p) { Return i == p.degree(); }
00040         friend Bool operator==(Pitch& p, Integer& i) { Return p.degree() == i; }
00041         friend Bool operator!=(Integer& i, Pitch& p) { Return i != p.degree(); }
00042         friend Bool operator!=(Pitch& p, Integer& i) { Return p.degree() != i; }
00043         friend Bool operator>=(Pitch& p, Integer& r) { Return p.degree() >= r; }
00044         friend Bool operator>=(Integer& i, Pitch& p) { Return i >= p.degree(); }
00045         friend Bool operator>(Pitch& p, Integer& i) { Return p.degree() > i; }
00046         friend Bool operator>(Integer& i, Pitch& p) { Return i > p.degree(); }
00047         friend Bool operator<=(Pitch& p, Integer& i) { Return p.degree() <= i; }
00048         friend Bool operator<=(Integer& i, Pitch& p) { Return i <= p.degree(); }
00049 
00050         friend Bool operator==(Real& r, Pitch& p) { Return r == p.hertz(); }
00051         friend Bool operator==(Pitch& p, Real& r) { Return p.hertz() == r; }
00052         friend Bool operator!=(Real& r, Pitch& p) { Return r != p.hertz(); }
00053         friend Bool operator!=(Pitch& p, Real& r){ Return p.hertz() != r; }
00054         friend Bool operator>=(Pitch& p, Real& r) { Return p.hertz() >= r; }
00055         friend Bool operator>=(Real& r, Pitch& p) { Return r >= p.hertz(); }
00056         friend Bool operator>(Pitch& p, Real& r) { Return p.hertz() > r; }
00057         friend Bool operator>(Real& r, Pitch& p) { Return r > p.hertz(); }
00058         friend Bool operator<=(Pitch& p, Real& r) { Return p.hertz() <= r; }
00059         friend Bool operator<=(Real& r, Pitch& p) { Return r <= p.hertz(); }
00060 
00061 public:
00062 
00063         operator Integer() { Return degree(); }
00064         operator Real() { Return hertz(); }
00065 
00067         Pitch() : m_pc(0), m_acc(0), m_oct(0) { }
00068 
00071         Pitch(Integer degree) : m_pc(0), m_acc(0), m_oct(0) { 
00072                 transpose( degree, m_pc, m_acc, m_oct ); 
00073         }
00074 
00079         Pitch(Integer pitchClass, Integer accidental, Integer octave) : m_pc(pitchClass), m_acc(accidental), m_oct(octave) { }
00080 
00083         Pitch(String s);
00084 
00088         Pitch(Real hz) : m_pc(0), m_acc(0), m_oct(0) {
00089                 For(Integer pc = s_lowestDegree; pc < s_lowestDegree+s_highestDegree; pc++) {
00090                         Pitch p = Pitch(pc);
00091                         Real x = p.hertz(); // get the Hz equivalent of this pitch
00092                         If ( x > hz) {                          // have we passed our target?
00093                                 pc -= 1;
00094                                 *this = Pitch(pc); // return the pitch
00095                                 Return;
00096                         }
00097                 }
00098                 // If we get here, the hz value is out of range
00099                 *this = Pitch(s_highestDegree); // Pitch is out of range, clip at top of range
00100         }
00101 
00105         Integer degree() Const {
00106                 Return( degree(m_pc, m_acc, m_oct) ); 
00107         }
00108 
00114         Integer degree(Integer pc, Integer acc, Integer oct) Const {
00115                 Return((pc + acc) + s_nDegrees * oct); 
00116         }
00117 
00120         Integer pianoKey() Const {
00121                 Return( pianoKey(m_pc, m_acc, m_oct) ); 
00122         }
00123 
00129         Integer pianoKey(Integer pc, Integer acc, Integer oct) Const {
00130                 Return((pc + acc) + s_nDegrees * (oct - 1) + 3); 
00131         }
00132 
00139         Void transpose(Integer x, Integer& pc, Integer& acc, Integer& oct) {
00140                 pc += acc + x;  // add the pitch, its accidental and the transposition to get raw semitones
00141                 acc = 0; // clear the accidental
00142                 While ( pc >= s_nDegrees ) { pc = pc - s_nDegrees; oct++; }
00143                 While ( pc < 0 ) { pc = pc + s_nDegrees; oct--; }
00144                 // cvt. to diatonic
00145                 switch (pc) {                   // adjust for enharmonic spelling
00146                 case 0: Break;                                                                                                  // C
00147                 case 1: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // C# Db
00148                 case 2: Break;                                                                                                  // D
00149                 case 3: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // D# Eb
00150                 case 4: Break;                                                                                                  // E
00151                 case 5: Break;                                                                                                  // F
00152                 case 6: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // F# Gb
00153                 case 7: Break;                                                                                                  // G
00154                 case 8: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // G# Ab
00155                 case 9: Break;                                                                                                  // A
00156                 case 10:If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // A# Bb
00157                 case 11: Break;                                                                                                 // B
00158                 }
00159         }
00160 
00164         Void transModuloOctave(Integer x) {
00165                 Integer o = m_oct;
00166                 transpose( x, m_pc, m_acc, m_oct );
00167                 m_oct = o;
00168         }
00169 
00172         Void invert() {
00173                 Integer p = Mod( m_pc + m_acc, s_nDegrees );
00174                 p = Mod( s_nDegrees - p, s_nDegrees );
00175                 transpose( p, m_pc = 0, m_acc = 0, m_oct );
00176         }
00177 
00179         Bool operator==(Const Pitch& x) Const {
00180                 Return degree() == x.degree();
00181         }
00182 
00184         Bool operator==(Const Integer& x) Const {
00185                 Return degree() == x;
00186         }
00187 
00189         Bool operator==(Const Real& x) Const {
00190                 Return hertz() == x;
00191         }
00192 
00194         Bool operator!=(Const Pitch& x) Const {
00195                 Return degree() != x.degree();
00196         }
00197 
00199         Bool operator!=(Const Integer& x) Const {
00200                 Return degree() != x;
00201         }
00202 
00204         Bool operator!=(Const Real& x) Const {
00205                 Return hertz() != x;
00206         }
00207 
00209         Bool operator>=(Const Pitch& x) Const {
00210                 Return degree() >= x.degree();
00211         }
00212 
00214         Bool operator>=(Const Integer& x) Const {
00215                 Return degree() >= x;
00216         }
00217 
00219         Bool operator>=(Const Real& x) Const {
00220                 Return hertz() >= x;
00221         }
00222 
00224         Bool operator>(Const Pitch& x) Const {
00225                 Return degree() > x.degree();
00226         }
00227 
00229         Bool operator>(Const Integer& x) Const {
00230                 Return degree() > x;
00231         }
00232 
00234         Bool operator>(Const Real& x) Const {
00235                 Return hertz() > x;
00236         }
00237 
00239         Bool operator<(Const Pitch& x) Const {
00240                 Return degree() < x.degree();
00241         }
00242 
00244         Bool operator<(Const Integer& x) Const {
00245                 Return degree() < x;
00246         }
00247 
00249         Bool operator<(Const Real& x) Const {
00250                 Return hertz() < x;
00251         }
00252 
00254         Bool operator<=(Const Pitch& x) Const {
00255                 Return degree() <= x.degree();
00256         }
00257 
00259         Bool operator<=(Const Integer& x) Const {
00260                 Return degree() <= x;
00261         }
00262 
00264         Bool operator<=(Const Real& x) Const {
00265                 Return hertz() <= x;
00266         }
00267 
00269         Pitch& operator+=(Const Pitch x) {
00270                 transpose( x.degree(), m_pc, m_acc, m_oct );
00271                 Return( *this );
00272         }
00273 
00275         Pitch& operator+=(Const Integer x) {
00276                 transpose( x, m_pc, m_acc, m_oct );
00277                 Return( *this );
00278         }
00279 
00281         Pitch& operator+=(Const Real x) {
00282                 Real hz = hertz() + x;
00283                 *this = Pitch( hz );
00284                 Return( *this );
00285         }
00286 
00288         Pitch& operator-=(Const Pitch x) {
00289                 transpose( -x.degree(), m_pc, m_acc, m_oct );
00290                 Return( *this );
00291         }
00292 
00294         Pitch& operator-=(Const Integer x) {
00295                 transpose( -x, m_pc, m_acc, m_oct );
00296                 Return( *this );
00297         }
00298 
00300         Pitch& operator-=(Const Real x) {
00301                 Real hz = hertz() - x;
00302                 Return( *this = Pitch( hz ) );
00303         }
00304 
00306         Pitch& operator*=(Const Pitch x) {
00307                 Integer d = degree() * x.degree();
00308                 Return( *this = Pitch(d) );
00309         }
00310 
00312         Pitch& operator*=(Const Integer x) {
00313                 Integer d = degree() * x;
00314                 Return( *this = Pitch(d) );
00315         }
00316 
00318         Pitch& operator*=(Const Real x) {
00319                 Real hz = hertz() * x;
00320                 Return( *this = Pitch(hz) );
00321         }
00322 
00324         Pitch& operator/=(Const Pitch x) {
00325                 Integer d = degree() / x.degree();
00326                 Return( *this = Pitch(d) );
00327         }
00328 
00330         Pitch& operator/=(Const Integer x) {
00331                 Integer d = degree() / x;
00332                 Return( *this = Pitch(d) );
00333 
00334         }
00335 
00337         Pitch& operator/=(Const Real x) {
00338                 Real hz = hertz() / x;
00339                 Return( *this = Pitch(hz) );
00340         }
00341 
00343         Pitch operator+(Const Pitch& x) {
00344                 Return( degree() + x.degree() );
00345         }
00346 
00348         Pitch operator+(Const Integer x) {
00349                 Return( degree() + x );
00350         }
00351 
00353         Pitch operator+(Const Real x) {
00354                 Real hz = hertz() * x;
00355                 Return( Pitch(hz) );
00356         }
00357 
00359         Pitch operator-(Const Pitch& x) {
00360                 Return( degree() - x.degree() );
00361         }
00362 
00364         Pitch operator-(Const Integer x) {
00365                 Return( degree() - x );
00366         }
00367 
00369         Pitch operator-(Const Real x) {
00370                 Real hz = hertz() - x;
00371                 Return( hz );
00372         }
00373 
00375         Pitch operator*(Const Pitch& x) {
00376                 Return( degree() * x.degree() );
00377         }
00378 
00380         Pitch operator*(Const Integer x) {
00381                 Return( degree() * x );
00382         }
00383 
00385         Pitch operator*(Const Real x) {
00386                 Return( hertz() * x );
00387         }
00388 
00390         Pitch operator/(Const Pitch& x) {
00391                 Return( degree() / x.degree() );
00392         }
00393 
00395         Pitch operator/(Const Integer x) {
00396                 Return( degree() / x );
00397         }
00398 
00400         Pitch operator/(Const Real x) {
00401                 Real hz = hertz() / x;
00402                 Return( Pitch(hz) );
00403         }
00404 
00406         Pitch operator%(Const Pitch x) {
00407                 Integer d = Mod(degree(), x.degree());
00408                 Return( d );
00409         }
00410 
00412         Pitch operator%(Const Integer x) {
00413                 Integer d = Mod(degree(), x);
00414                 Return( d );
00415         }
00416 
00418         Pitch operator%(Const Real x) {
00419                 Real hz = Mod(hertz(), x);
00420                 Return( Pitch(hz) );
00421         }
00422 
00425         String print(String s = 0) Const {
00426                 If (s)
00427                         cout << s;
00428                 Character pc = s_pcNames[ m_pc ];
00429                 Character acc;
00430                 switch (m_acc) {
00431                 case 0: acc = 0; Break;                 // natural
00432                 case 1: acc = 's'; Break;               // sharp
00433                 case -1: acc = 'b'; Break;              // flat
00434                 case 2: acc = 'x'; Break;               // double-sharp
00435                 case -2: acc = 'v'; Break;              // double-flat
00436                 default: acc = 0; Break;                // natural
00437                 }
00438                 If (acc)
00439                         sprintf(s_buf, "%c%c%d", pc, acc, m_oct);
00440                 Else
00441                         sprintf(s_buf, "%c%d", pc, m_oct);
00442                 Return s_buf;
00443         }
00444 
00446         Integer pitchClass() Const { Return m_pc; }
00447 
00449         Integer accidental() Const { Return m_acc; }
00450 
00452         Integer octave() Const { Return m_oct; }
00453 
00455         Real hertz() Const {
00456                 Real R = s_HzReference;
00457                 Real k = pitchClass() + accidental() - 9.0;
00458                 Real o = octave() - 4.0;
00459                 Return( R * Pow(2.0, o + k / Real(s_nDegrees) ) );
00460         }
00461 
00463         Static Void HzReference( Real ref ) { s_HzReference = ref; }
00464 
00466         Static Real HzReference( ) { Return( s_HzReference); }
00467 
00469         Static Void SetLowestKey( Integer ref ) { s_lowestDegree = ref; }
00470 
00472         Static Void SetHighestKey( Integer ref ) { s_highestDegree = ref; }
00473 
00475         Static Void SetDegrees( Integer ref ) { s_nDegrees = ref; }
00476 
00480         Integer isPitchClass(char c) Const {
00481                 switch (c) {
00482                 case 'C': case 'c': Return 0; Break;
00483                 case 'D': case 'd': Return 2; Break;
00484                 case 'E': case 'e': Return 4; Break;
00485                 case 'F': case 'f': Return 5; Break;
00486                 case 'G': case 'g': Return 7; Break;
00487                 case 'A': case 'a': Return 9; Break;
00488                 case 'B': case 'b': Return 11; Break;
00489                 default: Return -1;
00490                 }
00491         }
00492 
00497         Integer isAccidental(char c) Const {
00498                 switch (c) {
00499                 case '#':           Return  1;  Break;  // sharp
00500                 case 'S': case 's': Return  1;  Break;  // sharp
00501                 case 'N': case 'n': Return  0;  Break;  // natural
00502                 case 'B': case 'b':     Return -1;      Break;  // flat
00503                 case 'F': case 'f':     Return -1;      Break;  // flat
00504                 case 'X': case 'x':     Return  2;      Break;  // double-sharp
00505                 case 'V': case 'v':     Return -2;      Break;  // double-flat
00506                 default: Return -3;             Break; // may be an octave spec. with no accidental
00507                 }
00508         }
00509 
00510 private:
00511         Integer m_pc;                                   
00512         Integer m_acc;                                  
00513         Integer m_oct;                                  
00514         Static Real s_HzReference;                              
00515         Static Integer s_lowestDegree;                  
00516         Static Integer s_highestDegree;         
00517         Static Integer s_nDegrees;                              
00518         Static String s_pcNames;                
00519         Static char s_buf[16];                  
00520 };
00521 
00522 
00523 
00527 inline Integer Accidental( Pitch p )
00528 {
00529         Return p.accidental();
00530 }
00531 
00535 inline Integer PitchClass( Integer i ) 
00536 {
00537         Return( Mod( (i - 3), 12 ) ); 
00538 }
00539 
00543 inline Integer PitchClass( Pitch p ) 
00544 {
00545         Return( p.pitchClass() ); 
00546 }
00547 
00551 inline Integer Octave( Integer i )
00552 {
00553         Return( (i - 3) / 12 + 1 ); 
00554 }
00555 
00559 inline Integer Octave( Pitch p )
00560 {
00561         Return( p.octave() ); 
00562 }
00563 
00567 inline Real PitchToHertz( Pitch p )
00568 {
00569         Return( p.hertz() );
00570 }
00571 
00575 inline Real KeyToHertz( Integer i ) 
00576 {
00577         Real R = Pitch::HzReference();
00578         Integer k = PitchClass( i );
00579         Integer o = Octave( i );
00580         Return( R * pow(2, ( (o - 4) + k / 12) ) );
00581 }
00582 
00585 inline Void SetDegrees( Integer ref )
00586 {
00587         Pitch::SetDegrees(ref); 
00588 }
00589 
00590 inline Pitch Mod(Pitch p, Integer len)
00591 {
00592         Return( p % len );
00593 }
00594 
00595 #endif // PITCH_H

Generated on Tue Sep 12 10:14:18 2006 for MusimatLib by  doxygen 1.4.7