- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

    00001 /* $Revision: 1.2 $ $Date: 2006/09/09 06:22:53 $ $Author: dgl $ $Name:  $ $Id: _pitch_8h-source.html,v 1.2 2006/09/09 06:22:53 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