• Main Page
  • Files
  • File List
  • File Members

/Users/garethloy/Musimathics/Musimat1.2/MusimatTutorial/B0202.cpp

Go to the documentation of this file.
00001 #include "MusimatTutorial.h"
00002 MusimatTutorialSection(B0202) {
00003         Print("*** B.2.2 Rhythm ***");
00004         /*****************************************************************************
00005          
00006          B.2.2 Rhythm
00007          
00008          Duration in common music notation is expressed as a fraction of a whole note. For example a whole 
00009          note equals four quarter notes:
00010          
00011          w  = q + q + q + q
00012          
00013          /*****************************************************************************
00014          We could write this mathematically as follows:
00015          
00016          1   1 1 1 1
00017          - = -,-,-,-
00018          1   4 4 4 4
00019          
00020          which suggests using rational fractions to represent rhythmic durations. A rational fraction is a 
00021          ratio of integers. Musimat comes with a built-in data type called Rhythm, which emulates com-
00022          mon musical notation conventions regarding rhythm. For example, the quarter note is defined as
00023          *****************************************************************************/
00024         
00025         Rhythm Q = Rhythm( 1, 4 );
00026         
00027         /*****************************************************************************
00028          The first number is the numerator of the rational fraction, the second is the denominator. Note that 
00029          we can't write Rhythm(1/4) because the integer quotient of 1/4 is 0 with a remainder of 1; integer 
00030          division is performed if both the numerator and denominator are integers, which won't work here. 
00031          Specifying the numerator and denominator separately avoids this problem and has some other 
00032          numerical advantages as well. Executing Print(Q); prints (1, 4). Internally, Rhythm() 
00033          keeps the integer numerator and denominator values separately.
00034          
00035          Rhythmic duration can also be given as a real expression. 
00036          *****************************************************************************/
00037         
00038         Print(Rhythm(0.5)); 
00039         
00040         /*****************************************************************************
00041          prints (1, 2). How does Rhythm() convert this real expression into a ratio of integers? It does so by 
00042          calling the following function internally:
00043          *****************************************************************************/
00044         
00045         para1();  // Step into this function to continue the tutorial
00046         para2();  // Step into this function to continue the tutorial
00047 }
00048 
00049 Void realToRational(Real f, Integer Reference num, Integer Reference den) {
00050         Const Integer iterations = 3000000;
00051         Const Real limit = 0.000000000001;
00052         num = den = 1; // start off with ratio of 1/1
00053         For (Integer i = 0; i < iterations; i = i + 1) {
00054                 If (Abs( Real(num) / Real(den) - f ) < limit)
00055                         Return; // we have reached the limit
00056                 Else {
00057                         Real x = Abs(Real(num+1) / Real(den) - f);
00058                         Real y = Abs(Real(num) / Real(den+1) - f);
00059                         If (x < y)
00060                                 num = num + 1;
00061                         Else
00062                                 den = den + 1;
00063                 }
00064         }
00065         Return; // if we get here, we've not converged on the limit
00066 }
00067 
00068 Static Void para1() {
00069         
00070         /*****************************************************************************
00071          Function realToRational() takes a Real value f and attempts to find a rational fraction 
00072          num/den that is as close as possible to it. It starts by setting num = den = 1 and asking whether 
00073          num/den is already close enough to f. If so, it returns. Otherwise, it asks whether (num+1) / den 
00074          is closer than num / (den+1). If so, it increments num; otherwise it increments den and repeats the 
00075          process. Because num and den are Reference arguments, any changes to these variables within 
00076          realToRational() are reflected in the value of the actual arguments supplied to it.
00077          
00078          This method can be used to find rational approximations to most any real value. For example,
00079          *****************************************************************************/
00080         
00081         Real Pi = 3.14159265;
00082         Print(Rhythm(Pi));
00083         
00084         /*****************************************************************************
00085          prints (1953857, 621932). Note that 1953857/621932 = 3.14159265, which is 
00086          pretty close to the value of Pi. This method is limited by the precision of the computer hardware. 
00087          The precision of a rational approximation depends upon the value of the built-in variables 
00088          iterations and limit. For example, with the values shown in the preceding code, it took 
00089          realToRational() 2,575,787 trials to come up with its best approximation of Pi, requiring 
00090          about 1 second on my computer. The iteration and limit parameters can be set to whatever 
00091          values produce the optimal performance/accuracy cost/benefit ratio. Barring obscure rhythms 
00092          (nothing, say, beyond triplet eights), iterations = 240 and limit = 1.0/480 should be 
00093          satisfactory.
00094          
00095          Although the details go beyond the scope of this book, here is a sketch of how Rhythm() uses 
00096          realToRational():
00097          
00098          Rhythm(Real x) {
00099          Integer num, den; // internal parameters for Rhythm
00100          realToRational( x, num, den ); // convert x to num / den rational fraction
00101          // . . .
00102          }
00103          
00104          When called with a Real argument, Rhythm() calls realToRational() to set its internal integer 
00105          rational fraction values.
00106          
00107          Musimat provides built-in definitions for standard binary divisions of a whole note:
00108          *****************************************************************************/
00109         
00110         Rhythm Whole = Rhythm(1.0/1.0);
00111         Rhythm Half = Rhythm(1.0/2.0);
00112         Rhythm Quarter = Rhythm(1.0/4.0);
00113         Rhythm Eighth = Rhythm(1.0/8.0);
00114         Rhythm Sixteenth = Rhythm(1.0/16.0);
00115         
00116         /*****************************************************************************
00117          It is easy to define ternary divisions as well. For example, a triplet eighth is Rhythm(1.0/12.0) 
00118          because there are  triplet eighths per whole note. By the same reasoning, a quintuplet 
00119          eighth is 
00120          *****************************************************************************/
00121         
00122         Rhythm Qe = Rhythm(1.0/20.0);
00123         
00124         /*****************************************************************************
00125          We can express compound rhythms by addition. For example, a dotted half note is
00126          *****************************************************************************/
00127         
00128         Rhythm Hd = Rhythm(1.0/2.0 + 1.0/4.0);                                  // dotted half
00129         
00130         /*****************************************************************************
00131          Equivalently,
00132          *****************************************************************************/
00133         
00134         Rhythm H1 = Rhythm(3.0 / 4.0);                                                  // also a dotted half
00135         
00136         /*****************************************************************************
00137          We can also do arithmetic directly with rhythms. For example, 
00138          *****************************************************************************/
00139         
00140         Print(Eighth+Sixteenth); 
00141         
00142         /*****************************************************************************
00143          prints (3, 16). 
00144          
00145          Also, 
00146          *****************************************************************************/
00147         
00148         Print(Whole - Sixteenth);
00149         
00150         /*****************************************************************************
00151          prints (15,16), 
00152          *****************************************************************************/
00153         
00154         Print(Quarter * Sixteenth);
00155         
00156         /*****************************************************************************
00157          prints (1,64), and 
00158          *****************************************************************************/
00159         
00160         Print(Quarter / Sixteenth);
00161         
00162         /*****************************************************************************
00163          prints (4,1). The last value corresponds to a duration of four whole notes.
00164          
00165          We can extract the numerator and denominator from Rhythm():
00166          *****************************************************************************/
00167         
00168         Integer num, den;
00169         Rhythm z = Rhythm(Eighth + Sixteenth, num, den); // assigns rational fraction for E+S to num and den
00170         
00171         /*****************************************************************************
00172          Used this way, Rhythm() calculates the rational fraction of its first argument and sets num and 
00173          den by reference to the result. For the preceding example, num is set to 3 and den is set to 16. We 
00174          can leverage this capability to obtain the duration of a rhythm as a real number:
00175          *****************************************************************************/
00176 }
00177 
00178 Real realRhythm(Rhythm x) {
00179         Integer num, den;
00180         Rhythm(x, num, den); // find rational fraction for x and set num and den
00181         Return(Real(num)/Real(den)); // convert num and den to reals and divide
00182 }
00183 
00184 Void para2() {
00185 
00186         /*****************************************************************************
00187          Then, for example, executing Print(realRhythm(E + S)); prints 0.1875.
00188          As with pitches, we can make lists of rhythms.
00189          *****************************************************************************/
00190         
00191         RhythmList RL = RhythmList(Quarter, Eighth, Eighth, Eighth, Sixteenth, Sixteenth, Quarter);
00192         Print(RL);
00193         
00194         /*****************************************************************************
00195          prints {(1,4), (1,8), (1,8), (1,8), (1,16), (1,16), (1,4)}.
00196          *****************************************************************************/
00197 }
00198 
00200 /* $Revision: 1.3 $ $Date: 2006/09/05 08:03:08 $ $Author: dgl $ $Name:  $ $Id: B0202.cpp,v 1.3 2006/09/05 08:03:08 dgl Exp $ */
00201 // The Musimat Tutorial © 2006 Gareth Loy
00202 // Derived from Chapter 9 and Appendix B of "Musimathics Vol. 1" © 2006 Gareth Loy 
00203 // and published exclusively by The MIT Press.
00204 // This program is released WITHOUT ANY WARRANTY; without even the implied 
00205 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
00206 // For information on usage and redistribution, and for a DISCLAIMER OF ALL
00207 // WARRANTIES, see the file, "LICENSE.txt," in this distribution.
00208 // "Musimathics" is available here:     http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=10916
00209 // Gareth Loy's Musimathics website:    http://www.musimathics.com/
00210 // The Musimat website:                 http://www.musimat.com/
00211 // This program is released under the terms of the GNU General Public License
00212 // available here:                      http://www.gnu.org/licenses/gpl.txt
00213 

Generated on Fri Nov 26 2010 16:18:25 for Musimat Tutorial by  doxygen 1.7.2