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