00001 #include "MusimatTutorial.h" 00002 MusimatTutorialSection(B0201a) { 00003 Print("*** Equal-Tempered Frequency ***"); 00004 /***************************************************************************** 00005 00006 Equal-Tempered Frequency 00007 00008 Pitch provides a representation of scale degrees and does not 00009 denote frequency. We can convert to frequency using any scale system we like, beginning with the 00010 equal-tempered scale. We can compute the equal-tempered frequency of a Pitch, assuming a 00011 reference such as A4 equals 440 Hz, by adapting equation (3.3), 00012 f(k, v) = fR * 2^(v + k / 12), 00013 to compute hertz values from chromatic scale degrees: 00014 *****************************************************************************/ 00015 00016 para1(); // Step into this function to continue the tutorial 00017 para2(); // Step into this function to continue the tutorial 00018 } 00019 00020 Real pitchToHz(Pitch p){ 00021 Real R = 440.0; // reference frequency 00022 Real key = PitchClass(p) + Accidental(p); // get key index 00023 Real oct = Octave(p); // get octave 00024 Return(R * Pow(2.0, (oct - 4) + (key - 9) / 12.0)); // return frequency 00025 } 00026 00027 Void para1() { 00028 00029 /***************************************************************************** 00030 A way to think about the expression in the Return() statement is as follows. Suppose the reference 00031 pitch is 440 Hz, corresponding to A4. So we want the value returned from this function to equal 00032 440.0 when p is A4. The triple for A4 is (9, 0, 4), so when pitchToHz() is called with A4, 00033 we want to evaluate fR * 2^0, which can be achieved by subtracting 9 from the pitch and 4 from the 00034 octave. Then, executing 00035 *****************************************************************************/ 00036 00037 Print(pitchToHz(A4)); 00038 00039 /***************************************************************************** 00040 prints 440.0, and substituting any other pitch, regardless of how it is spelled, will produce its 00041 proper hertz value. For example, A0 is 27.5 Hz, C4 is 261.63 Hz, and C8 is 4186.01 Hz. 00042 00043 What if we have a frequency x in hertz and want to find its corresponding pitch? The problem 00044 is that x may lie in between the pitches of the scale because x can be any frequency. One approach 00045 is to compare x to each semitone on the keyboard from lowest frequency to highest, and to stop 00046 when the keyboard frequency exceeds x. Then the key one semitone below is the closest corre- 00047 sponding pitch on the keyboard. 00048 *****************************************************************************/ 00049 } 00050 00051 Pitch hzToPitch(Real x) { // find pitch closest to x Hz 00052 For(Integer k = 9+1; k < 88+9; k = k + 1) { // test from As0 to C8 00053 Pitch p = Pitch(k); // get pitch of k 00054 Real f = pitchToHz(p); // get frequency of p 00055 If (f > x) // have we passed our target? 00056 Return(p - 1); // return previous pitch 00057 } 00058 // If we get here, the Hz value of x is beyond the end of the keyboard 00059 Return(C8); // out of range, clip at C8 00060 } 00061 00062 Void para2() { 00063 00064 /***************************************************************************** 00065 This code returns A0 if x is lower than or equal to A0, and it returns C8 if x is greater than or equal 00066 to C8. 00067 00068 Lists of Pitches 00069 00070 We can collect pitches into lists: 00071 *****************************************************************************/ 00072 00073 PitchList shave(C5, G4, G4, Ab4, G4, B4, C5); // shave and a haircut, 2 bits 00074 00075 /***************************************************************************** 00076 We can do arithmetic on all the pitches in a list. To transpose this pitch list up a whole step, 00077 *****************************************************************************/ 00078 00079 Print( shave = shave + 2 ); 00080 00081 /***************************************************************************** 00082 adds two degrees to every pitch in shave, and prints {D5, A4, A4, As4, A4, Cs5, D5}. 00083 To transpose by an octave, 00084 *****************************************************************************/ 00085 00086 Print( shave = shave * 2 ); 00087 00088 /***************************************************************************** 00089 multiplies every pitch in the list by 2 and prints {D6, A5, A5, As5, A5, Cs6, D6}. 00090 *****************************************************************************/ 00091 } 00092 00094 /* $Revision: 1.3 $ $Date: 2006/09/05 08:03:08 $ $Author: dgl $ $Name: $ $Id: B0201a.cpp,v 1.3 2006/09/05 08:03:08 dgl Exp $ */ 00095 // The Musimat Tutorial � 2006 Gareth Loy 00096 // Derived from Chapter 9 and Appendix B of "Musimathics Vol. 1" � 2006 Gareth Loy 00097 // and published exclusively by The MIT Press. 00098 // This program is released WITHOUT ANY WARRANTY; without even the implied 00099 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00100 // For information on usage and redistribution, and for a DISCLAIMER OF ALL 00101 // WARRANTIES, see the file, "LICENSE.txt," in this distribution. 00102 // "Musimathics" is available here: http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=10916 00103 // Gareth Loy's Musimathics website: http://www.musimathics.com/ 00104 // The Musimat website: http://www.musimat.com/ 00105 // This program is released under the terms of the GNU General Public License 00106 // available here: http://www.gnu.org/licenses/gpl.txt 00107