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 #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();
00095 If ( x > hz) {
00096 pc -= 1;
00097 *this = Pitch(pc);
00098 Return;
00099 }
00100 }
00101
00102 *this = Pitch(s_highestDegree);
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;
00144 acc = 0;
00145 While ( pc >= s_nDegrees ) { pc = pc - s_nDegrees; oct++; }
00146 While ( pc < 0 ) { pc = pc + s_nDegrees; oct--; }
00147
00148 switch (pc) {
00149 case 0: Break;
00150 case 1: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00151 case 2: Break;
00152 case 3: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00153 case 4: Break;
00154 case 5: Break;
00155 case 6: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00156 case 7: Break;
00157 case 8: If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00158 case 9: Break;
00159 case 10:If (x>0) { pc--; acc++; } Else { pc++; acc--; } Break;
00160 case 11: Break;
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;
00435 case 1: acc = 's'; Break;
00436 case -1: acc = 'b'; Break;
00437 case 2: acc = 'x'; Break;
00438 case -2: acc = 'v'; Break;
00439 default: acc = 0; Break;
00440 }
00441 If (acc)
00442 #ifdef _MSC_VER
00443
00444
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
00455
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;
00521 case 'S': case 's': Return 1; Break;
00522 case 'N': case 'n': Return 0; Break;
00523 case 'B': case 'b': Return -1; Break;
00524 case 'F': case 'f': Return -1; Break;
00525 case 'X': case 'x': Return 2; Break;
00526 case 'V': case 'v': Return -2; Break;
00527 default: Return -3; Break;
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