• Main Page
  • Modules
  • Classes
  • Files
  • File List
  • File Members

/Users/garethloy/Musimathics/Musimat1.2/include/Pitch.h

Go to the documentation of this file.
00001 /* $Revision: 1.6 $ $Date: 2006/09/08 18:56:52 $ $Author: dgl $ $Name:  $ $Id: Pitch.h,v 1.6 2006/09/08 18:56:52 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 #ifdef _MSC_VER
00023 #define _CRT_SECURE_NO_WARNINGS
00024 #endif
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <iostream>
00029 #include <math.h>
00030 
00035 
00037 class Pitch
00038 {
00039         friend ostream& operator<<(ostream&, Pitch&);
00040         friend istream& operator>>(istream&, Pitch&);
00041 
00042         friend Bool operator==(Integer& i, Pitch& p) { Return i == p.degree(); }
00043         friend Bool operator==(Pitch& p, Integer& i) { Return p.degree() == i; }
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>=(Pitch& p, Integer& r) { Return p.degree() >= r; }
00047         friend Bool operator>=(Integer& i, Pitch& p) { Return i >= p.degree(); }
00048         friend Bool operator>(Pitch& p, Integer& i) { Return p.degree() > i; }
00049         friend Bool operator>(Integer& i, Pitch& p) { Return i > p.degree(); }
00050         friend Bool operator<=(Pitch& p, Integer& i) { Return p.degree() <= i; }
00051         friend Bool operator<=(Integer& i, Pitch& p) { Return i <= p.degree(); }
00052 
00053         friend Bool operator==(Real& r, Pitch& p) { Return r == p.hertz(); }
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>=(Pitch& p, Real& r) { Return p.hertz() >= r; }
00058         friend Bool operator>=(Real& r, Pitch& p) { Return r >= p.hertz(); }
00059         friend Bool operator>(Pitch& p, Real& r) { Return p.hertz() > r; }
00060         friend Bool operator>(Real& r, Pitch& p) { Return r > p.hertz(); }
00061         friend Bool operator<=(Pitch& p, Real& r) { Return p.hertz() <= r; }
00062         friend Bool operator<=(Real& r, Pitch& p) { Return r <= p.hertz(); }
00063 
00064 public:
00065 
00066         operator Integer() { Return degree(); }
00067         operator Real() { Return hertz(); }
00068 
00070         Pitch() : m_pc(0), m_acc(0), m_oct(0) { }
00071 
00074         Pitch(Integer degree) : m_pc(0), m_acc(0), m_oct(0) { 
00075                 transpose( degree, m_pc, m_acc, m_oct ); 
00076         }
00077 
00082         Pitch(Integer pitchClass, Integer accidental, Integer octave) : m_pc(pitchClass), m_acc(accidental), m_oct(octave) { }
00083 
00086         Pitch(String s);
00087 
00091         Pitch(Real hz) : m_pc(0), m_acc(0), m_oct(0) {
00092                 For(Integer pc = s_lowestDegree; pc < s_lowestDegree+s_highestDegree; pc++) {
00093                         Pitch p = Pitch(pc);
00094                         Real x = p.hertz(); // get the Hz equivalent of this pitch
00095                         If ( x > hz) {                          // have we passed our target?
00096                                 pc -= 1;
00097                                 *this = Pitch(pc); // return the pitch
00098                                 Return;
00099                         }
00100                 }
00101                 // If we get here, the hz value is out of range
00102                 *this = Pitch(s_highestDegree); // Pitch is out of range, clip at top of range
00103         }
00104 
00108         Integer degree() Const {
00109                 Return( degree(m_pc, m_acc, m_oct) ); 
00110         }
00111 
00117         Integer degree(Integer pc, Integer acc, Integer oct) Const {
00118                 Return((pc + acc) + s_nDegrees * oct); 
00119         }
00120 
00123         Integer pianoKey() Const {
00124                 Return( pianoKey(m_pc, m_acc, m_oct) ); 
00125         }
00126 
00132         Integer pianoKey(Integer pc, Integer acc, Integer oct) Const {
00133                 Return((pc + acc) + s_nDegrees * (oct - 1) + 3); 
00134         }
00135 
00142         Void transpose(Integer x, Integer& pc, Integer& acc, Integer& oct) {
00143                 pc += acc + x;  // add the pitch, its accidental and the transposition to get raw semitones
00144                 acc = 0; // clear the accidental
00145                 While ( pc >= s_nDegrees ) { pc = pc - s_nDegrees; oct++; }
00146                 While ( pc < 0 ) { pc = pc + s_nDegrees; oct--; }
00147                 // cvt. to diatonic
00148                 switch (pc) {                   // adjust for enharmonic spelling
00149                 case 0: Break;                                                                                                  // C
00150                 case 1: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // C# Db
00151                 case 2: Break;                                                                                                  // D
00152                 case 3: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // D# Eb
00153                 case 4: Break;                                                                                                  // E
00154                 case 5: Break;                                                                                                  // F
00155                 case 6: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // F# Gb
00156                 case 7: Break;                                                                                                  // G
00157                 case 8: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // G# Ab
00158                 case 9: Break;                                                                                                  // A
00159                 case 10:If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;  // A# Bb
00160                 case 11: Break;                                                                                                 // B
00161                 }
00162         }
00163 
00167         Void transModuloOctave(Integer x) {
00168                 Integer o = m_oct;
00169                 transpose( x, m_pc, m_acc, m_oct );
00170                 m_oct = o;
00171         }
00172 
00175         Void invert() {
00176                 Integer p = Mod( m_pc + m_acc, s_nDegrees );
00177                 p = Mod( s_nDegrees - p, s_nDegrees );
00178                 transpose( p, m_pc = 0, m_acc = 0, m_oct );
00179         }
00180 
00182         Bool operator==(Const Pitch& x) Const {
00183                 Return degree() == x.degree();
00184         }
00185 
00187         Bool operator==(Const Integer& x) Const {
00188                 Return degree() == x;
00189         }
00190 
00192         Bool operator==(Const Real& x) Const {
00193                 Return hertz() == x;
00194         }
00195 
00197         Bool operator!=(Const Pitch& x) Const {
00198                 Return degree() != x.degree();
00199         }
00200 
00202         Bool operator!=(Const Integer& x) Const {
00203                 Return degree() != x;
00204         }
00205 
00207         Bool operator!=(Const Real& x) Const {
00208                 Return hertz() != x;
00209         }
00210 
00212         Bool operator>=(Const Pitch& x) Const {
00213                 Return degree() >= x.degree();
00214         }
00215 
00217         Bool operator>=(Const Integer& x) Const {
00218                 Return degree() >= x;
00219         }
00220 
00222         Bool operator>=(Const Real& x) Const {
00223                 Return hertz() >= x;
00224         }
00225 
00227         Bool operator>(Const Pitch& x) Const {
00228                 Return degree() > x.degree();
00229         }
00230 
00232         Bool operator>(Const Integer& x) Const {
00233                 Return degree() > x;
00234         }
00235 
00237         Bool operator>(Const Real& x) Const {
00238                 Return hertz() > x;
00239         }
00240 
00242         Bool operator<(Const Pitch& x) Const {
00243                 Return degree() < x.degree();
00244         }
00245 
00247         Bool operator<(Const Integer& x) Const {
00248                 Return degree() < x;
00249         }
00250 
00252         Bool operator<(Const Real& x) Const {
00253                 Return hertz() < x;
00254         }
00255 
00257         Bool operator<=(Const Pitch& x) Const {
00258                 Return degree() <= x.degree();
00259         }
00260 
00262         Bool operator<=(Const Integer& x) Const {
00263                 Return degree() <= x;
00264         }
00265 
00267         Bool operator<=(Const Real& x) Const {
00268                 Return hertz() <= x;
00269         }
00270 
00272         Pitch& operator+=(Const Pitch x) {
00273                 transpose( x.degree(), m_pc, m_acc, m_oct );
00274                 Return( *this );
00275         }
00276 
00278         Pitch& operator+=(Const Integer x) {
00279                 transpose( x, m_pc, m_acc, m_oct );
00280                 Return( *this );
00281         }
00282 
00284         Pitch& operator+=(Const Real x) {
00285                 Real hz = hertz() + x;
00286                 *this = Pitch( hz );
00287                 Return( *this );
00288         }
00289 
00291         Pitch& operator-=(Const Pitch x) {
00292                 transpose( -x.degree(), m_pc, m_acc, m_oct );
00293                 Return( *this );
00294         }
00295 
00297         Pitch& operator-=(Const Integer x) {
00298                 transpose( -x, m_pc, m_acc, m_oct );
00299                 Return( *this );
00300         }
00301 
00303         Pitch& operator-=(Const Real x) {
00304                 Real hz = hertz() - x;
00305                 Return( *this = Pitch( hz ) );
00306         }
00307 
00309         Pitch& operator*=(Const Pitch x) {
00310                 Integer d = degree() * x.degree();
00311                 Return( *this = Pitch(d) );
00312         }
00313 
00315         Pitch& operator*=(Const Integer x) {
00316                 Integer d = degree() * x;
00317                 Return( *this = Pitch(d) );
00318         }
00319 
00321         Pitch& operator*=(Const Real x) {
00322                 Real hz = hertz() * x;
00323                 Return( *this = Pitch(hz) );
00324         }
00325 
00327         Pitch& operator/=(Const Pitch x) {
00328                 Integer d = degree() / x.degree();
00329                 Return( *this = Pitch(d) );
00330         }
00331 
00333         Pitch& operator/=(Const Integer x) {
00334                 Integer d = degree() / x;
00335                 Return( *this = Pitch(d) );
00336 
00337         }
00338 
00340         Pitch& operator/=(Const Real x) {
00341                 Real hz = hertz() / x;
00342                 Return( *this = Pitch(hz) );
00343         }
00344 
00346         Pitch operator+(Const Pitch& x) {
00347                 Return( degree() + x.degree() );
00348         }
00349 
00351         Pitch operator+(Const Integer x) {
00352                 Return( degree() + x );
00353         }
00354 
00356         Pitch operator+(Const Real x) {
00357                 Real hz = hertz() * x;
00358                 Return( Pitch(hz) );
00359         }
00360 
00362         Pitch operator-(Const Pitch& x) {
00363                 Return( degree() - x.degree() );
00364         }
00365 
00367         Pitch operator-(Const Integer x) {
00368                 Return( degree() - x );
00369         }
00370 
00372         Pitch operator-(Const Real x) {
00373                 Real hz = hertz() - x;
00374                 Return( hz );
00375         }
00376 
00378         Pitch operator*(Const Pitch& x) {
00379                 Return( degree() * x.degree() );
00380         }
00381 
00383         Pitch operator*(Const Integer x) {
00384                 Return( degree() * x );
00385         }
00386 
00388         Pitch operator*(Const Real x) {
00389                 Return( hertz() * x );
00390         }
00391 
00393         Pitch operator/(Const Pitch& x) {
00394                 Return( degree() / x.degree() );
00395         }
00396 
00398         Pitch operator/(Const Integer x) {
00399                 Return( degree() / x );
00400         }
00401 
00403         Pitch operator/(Const Real x) {
00404                 Real hz = hertz() / x;
00405                 Return( Pitch(hz) );
00406         }
00407 
00409         Pitch operator%(Const Pitch x) {
00410                 Integer d = Mod(degree(), x.degree());
00411                 Return( d );
00412         }
00413 
00415         Pitch operator%(Const Integer x) {
00416                 Integer d = Mod(degree(), x);
00417                 Return( d );
00418         }
00419 
00421         Pitch operator%(Const Real x) {
00422                 Real hz = Mod(hertz(), x);
00423                 Return( Pitch(hz) );
00424         }
00425 
00428         String print(String s = 0) Const {
00429                 If (s)
00430                         cout << s;
00431                 Character pc = s_pcNames[ m_pc ];
00432                 Character acc;
00433                 switch (m_acc) {
00434                 case 0: acc = 0; Break;                 // natural
00435                 case 1: acc = 's'; Break;               // sharp
00436                 case -1: acc = 'b'; Break;              // flat
00437                 case 2: acc = 'x'; Break;               // double-sharp
00438                 case -2: acc = 'v'; Break;              // double-flat
00439                 default: acc = 0; Break;                // natural
00440                 }
00441                 If (acc)
00442 #ifdef _MSC_VER
00443 // Disable Microsoft Visual Studio warning about sprintf()
00444 // until is universal agreement about how to handle its insecurities
00445 #pragma warning(push)
00446 #pragma warning(disable: 4996)
00447                         sprintf(s_buf, "%c%c%d", pc, acc, m_oct);
00448 #pragma warning(pop)
00449 #else
00450                         sprintf(s_buf, "%c%c%d", pc, acc, m_oct);
00451 #endif
00452                 Else
00453 #ifdef _MSC_VER
00454 // Disable Microsoft Visual Studio warning about sprintf()
00455 // until is universal agreement about how to handle its insecurities
00456 #pragma warning(push)
00457 #pragma warning(disable: 4996)
00458                         sprintf(s_buf, "%c%d", pc, m_oct);
00459 #pragma warning(pop)
00460 #else
00461                         sprintf(s_buf, "%c%d", pc, m_oct);
00462 #endif
00463                 Return s_buf;
00464         }
00465 
00467         Integer pitchClass() Const { Return m_pc; }
00468 
00470         Integer accidental() Const { Return m_acc; }
00471 
00473         Integer octave() Const { Return m_oct; }
00474 
00476         Real hertz() Const {
00477                 Real R = s_HzReference;
00478                 Real k = pitchClass() + accidental() - 9.0;
00479                 Real o = octave() - 4.0;
00480                 Return( R * Pow(2.0, o + k / Real(s_nDegrees) ) );
00481         }
00482 
00484         Static Void HzReference( Real ref ) { s_HzReference = ref; }
00485 
00487         Static Real HzReference( ) { Return( s_HzReference); }
00488 
00490         Static Void SetLowestKey( Integer ref ) { s_lowestDegree = ref; }
00491 
00493         Static Void SetHighestKey( Integer ref ) { s_highestDegree = ref; }
00494 
00496         Static Void SetDegrees( Integer ref ) { s_nDegrees = ref; }
00497 
00501         Integer isPitchClass(char c) Const {
00502                 switch (c) {
00503                 case 'C': case 'c': Return 0; Break;
00504                 case 'D': case 'd': Return 2; Break;
00505                 case 'E': case 'e': Return 4; Break;
00506                 case 'F': case 'f': Return 5; Break;
00507                 case 'G': case 'g': Return 7; Break;
00508                 case 'A': case 'a': Return 9; Break;
00509                 case 'B': case 'b': Return 11; Break;
00510                 default: Return -1;
00511                 }
00512         }
00513 
00518         Integer isAccidental(char c) Const {
00519                 switch (c) {
00520                 case '#':           Return  1;  Break;  // sharp
00521                 case 'S': case 's': Return  1;  Break;  // sharp
00522                 case 'N': case 'n': Return  0;  Break;  // natural
00523                 case 'B': case 'b':     Return -1;      Break;  // flat
00524                 case 'F': case 'f':     Return -1;      Break;  // flat
00525                 case 'X': case 'x':     Return  2;      Break;  // double-sharp
00526                 case 'V': case 'v':     Return -2;      Break;  // double-flat
00527                 default: Return -3;             Break; // may be an octave spec. with no accidental
00528                 }
00529         }
00530 
00531 private:
00532         Integer m_pc;                                   
00533         Integer m_acc;                                  
00534         Integer m_oct;                                  
00535         Static Real s_HzReference;                              
00536         Static Integer s_lowestDegree;                  
00537         Static Integer s_highestDegree;         
00538         Static Integer s_nDegrees;                              
00539         Static String s_pcNames;                
00540         Static char s_buf[16];                  
00541 };
00542 
00543 
00544 
00548 inline Integer Accidental( Pitch p )
00549 {
00550         Return p.accidental();
00551 }
00552 
00556 inline Integer PitchClass( Integer i ) 
00557 {
00558         Return( Mod( (i - 3), 12 ) ); 
00559 }
00560 
00564 inline Integer PitchClass( Pitch p ) 
00565 {
00566         Return( p.pitchClass() ); 
00567 }
00568 
00572 inline Integer Octave( Integer i )
00573 {
00574         Return( (i - 3) / 12 + 1 ); 
00575 }
00576 
00580 inline Integer Octave( Pitch p )
00581 {
00582         Return( p.octave() ); 
00583 }
00584 
00588 inline Real PitchToHertz( Pitch p )
00589 {
00590         Return( p.hertz() );
00591 }
00592 
00596 inline Real KeyToHertz( Integer i ) 
00597 {
00598         Real R = Pitch::HzReference();
00599         Integer k = PitchClass( i );
00600         Integer o = Octave( i );
00601         Return( R * pow(2.0, ( (o - 4) + k / 12) ) );
00602 }
00603 
00606 inline Void SetDegrees( Integer ref )
00607 {
00608         Pitch::SetDegrees(ref); 
00609 }
00610 
00611 inline Pitch Mod(Pitch p, Integer len)
00612 {
00613         Return( p % len );
00614 }
00615 
00616 #endif // PITCH_H

Generated on Fri Nov 26 2010 16:18:25 for MusimatLib by  doxygen 1.7.2