00001
00002 #ifndef PITCH_H
00003 #define PITCH_H
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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();
00092 If ( x > hz) {
00093 pc -= 1;
00094 *this = Pitch(pc);
00095 Return;
00096 }
00097 }
00098
00099 *this = Pitch(s_highestDegree);
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;
00141 acc = 0;
00142 While ( pc >= s_nDegrees ) { pc = pc - s_nDegrees; oct++; }
00143 While ( pc < 0 ) { pc = pc + s_nDegrees; oct--; }
00144
00145 switch (pc) {
00146 case 0: Break;
00147 case 1: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00148 case 2: Break;
00149 case 3: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00150 case 4: Break;
00151 case 5: Break;
00152 case 6: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00153 case 7: Break;
00154 case 8: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00155 case 9: Break;
00156 case 10:If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00157 case 11: Break;
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;
00432 case 1: acc = 's'; Break;
00433 case -1: acc = 'b'; Break;
00434 case 2: acc = 'x'; Break;
00435 case -2: acc = 'v'; Break;
00436 default: acc = 0; Break;
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;
00500 case 'S': case 's': Return 1; Break;
00501 case 'N': case 'n': Return 0; Break;
00502 case 'B': case 'b': Return -1; Break;
00503 case 'F': case 'f': Return -1; Break;
00504 case 'X': case 'x': Return 2; Break;
00505 case 'V': case 'v': Return -2; Break;
00506 default: Return -3; Break;
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