back to list

my micro.CAL program

🔗Joe Monzo <joe_monzo@xxxxxxx.xxxx>

3/31/1999 11:45:04 PM

***************************************
***************************************
** **
** ATTENTION CAKEWALK USERS **
** **
***************************************
***************************************

Especially those (like me) who do step-time,
one-note-at-a-time sequencing right on the computer.

----------------------------

Below is a working version 1.0 of my "micro.CAL"
Cakewalk Application Language microtonal input
program.

It allows the user to input, step-time, microtonal
notes into a MIDI or Cakewalk file.

Right now I only have microtonal input capability for
numerator and denominator of ratios. I'm working on
prime-factor input, and also ETs. (actually ETs were
already crudely implemented before I made it JI).

Also in the works is a better note-duration input
interface, more like musical notation (1/4-notes,
1/8-notes, tuplets, etc.)

The program takes your input of 12-Eq degree of tonic,
start time, duration (in timebase ppq units), and numerator
and denominator of ratio, and inserts a MIDI-note with
the proper pitch-bend into your Cakewalk file.

It only does one note per run right now.

CAL uses only integer math and does not have logarithms,
so I had to work around both of those limitations.

The integer math was easy - just multiply all the
important numbers by 10^4 or 10^6, then divide back down
at the end. But actually, this was where the problem
lay which stopped the program from running - it was
"seeing" 10000 as an integer data-type and truncating
the calculation. It works fine now.

The lack of logarithms was a little more difficult,
and I solved it by using Ellis's augmented bimodulus
calculation as presented in his translation of Helmholtz,
_On the Sensations of Tone_, p. 447. It is accurate
to within less than 2 cents.

Everything in the program between the "do" under
START PROGRAM and the closing parenthesis as the end
should be *indented*. If you paste this into Cakewalk
or a text editor and a word or line is not indented,
an email program along the way has added a carriage
return at the end of the preceeding line. Delete this,
so that the non-indented words end up at the end of the
previous line where they belong. Otherwise the program
may not run.

CAL's syntax is like a combination of C and LISP:
lots of parentheses. Indenting helps keep track of them.

Anyone is welcome to add their own improvements, or
implement mine, for that matter. I've left in many
comments and also some commented-out code that works to
some extent. Feel free to finish it. One important note -
if you send *me* an improvement, make sure it will work
on my machine - I'm running Cakewalk 2.01 Pro for Windows
and this is CAL version 21 (it's dinosaur software).
If you include parts of the language that were added in
a later version of CAL, it won't run for me.

There are four "pause" statements that have been
commented out. They are for debugging purposes and
are clearly marked. The double-semicolons may be removed
if you would like CAL to furnish this information to you
while you are improving the program.

Enjoy!

-monzo

;;===================================================
;; B E G I N N I N G O F P R O G R A M
;;===================================================
;;
;; MICRO.CAL v. 1.0 (c) 1999 by Joe Monzo
;;
;; 1999-3-25
;;
;; CAL routine to calculate pitch-bend from a ratio
;; and insert it, with a note, into a Cakewalk file
;;
;; The user may change the NOW time for the insertion.
;;
;; - still needs if-then for "ET or JI?" routines
;; - still needs ratio calculation procedure for ETs
;; - figure out how to indicate octaves with exp2
;; - a loop is necessary, so whole phrases can be entered
;;
;;====================================================
;; 1999-3-31 *** THIS VERSION WORKS ****
;;
;;====================================================
;; START PROGRAM

(do

;;================================
;; DECLARATIONS

;;--------------------------------------------
;; Declare constants

(long bendcalc (/ (* 2 1000000) 8192)) ;; 2 multiplied for int math
(dword bimodulus1 3477)
(dword multiplier 10000)
(dword bimodulus (* bimodulus1 multiplier)) ;; Ellis's bimodulus 3477
multiplied for int math

;;--------------------------------------------
;; Declare variables for user input

(dword Time Now) ;; these are all simply
(int ScaleSize 12) ;; default initial values -
(int Degree 0) ;; they can be changed
(int MaxDegree 11) ;;
(int WhlAmt 0) ;;
(int Duration 120) ;;

(word numerator 1)
(word denom 1)

;; These variables will be used when
;; prime-factor notation is implemented
;;
;; (int exp2 0)
;; (int exp3 0)
;; (int exp5 0)
;; (int exp7 0)
;; (int exp11 0)
;; (int exp13 0)

;;--------------------------------------------
;; declare variables for cents calculation
(word larger 0)
(word smaller 0)
(long cents 0)
(long centsadd 0)

;;--------------------------------------------
;; declare variables for pitch-bend calculation

(long semitones)
(long hisemitones)
(long closest12eq)
(long eqerror)
(long pitchbend)
(int midinote 60)
(int tonic 0)

;;========================
;; INPUT

;;--------------------------------------------
;; User input

;;---------------
;; timing info

(getInt tonic "Key or tonic (0=C, 1=Db, 2=D, 3=Eb, 4=E, 5=F, 6=F#, 7=G,
8=Ab, 9=A, 10=Bb, 11=B) :" 0 11)
(getTime Time "Starting Time of note:")
(getInt Duration "Duration (240 = half, 120 = quarter, 60 = 8th, 40 =
triplet 8th, 30 = 16th, 20 = triplet 16th):" 1 4800)

;;----------------
;; ET or JI?

;; THIS STILL NEEDS TO BE DONE for combined ET/JI version

;;----------------
;; ET section now used only in ET-only version of program
;;
;;(getInt ScaleSize "Number of EQ steps in scale:" 5 72)
;;(= MaxDegree (- ScaleSize 1))

;;(getInt Degree "What is the Degree of this note:" 0 MaxDegree)

;;----------------
;; JI section - to be combined with ET in future version

(getWord numerator "Numerator of ratio:" 1 65000)
(getWord denom "Denominator of ratio:" 1 65000)

;;========================
;; CALCULATIONS

;;--------------------------------------------
;; calculate cents, without logarithms
;; using Ellis's augmented bimodulus method
;; see Helmholtz, "On the Sensations of Tone", p 447

;; THIS IS BASIC - I DON'T KNOW HOW TO GOTO IN CAL:
;;IF numerator = denom THEN cents = 0: GOTO ending:

;; First determine which is larger and which is smaller,
;; the numerator or the denominator.

(if (> numerator denom)
(do
(= larger numerator)
(= smaller denom)
)
)

(if (< numerator denom)
(do
(= smaller numerator)
(= larger denom)
)
)

(if (= numerator denom)
(do
(= smaller numerator)
(= larger denom)
)
)

;;*******************************************************
;;FOR DEBUGGING - TO BE DELETED
;;(pause "larger = " larger "smaller = " smaller)
;;*******************************************************

;;> "If the greater number of the ratio be more than twice
;;> the smaller, divide the greater (or else multiply the less)
;;> by 2 until the greater number is not more than twice
;;> the smaller." [to octave-reduce] [-Ellis]

(while (> larger (* 2 smaller) )

(if (== (% larger 2) 0)

(do (= larger (/ larger 2) ) )
(do (= smaller (* smaller 2) ) )

)
)

;;> "If the reduced interval ratio be such that 3 times
;;> the larger number is greater than 4 times the smaller,
;;> but twice the larger number is less than 3 times the
;;> smaller number, then multiply the larger number by 3,
;;> and the smaller number by 4, for a new interval ratio,
;;> and add 498 cents to the result." [-Ellis]

(while (> (* 3 larger) (* 4 smaller) )

(if (< (* 2 larger) (* 3 smaller) )

(do
(= larger (* 3 larger) )
(= smaller (* 4 smaller) )
(= cents (* 498 multiplier) )
)

(do
(= larger (* 2 larger) )
(= smaller (* 3 smaller) )
(= cents (* 702 multiplier) )
)
)
)

;;*******************************************************
;;FOR DEBUGGING - TO BE DELETED
;;(pause "cents = " cents)
;;*******************************************************

;;> "Multiply 3477 by the difference of the numbers of the
;;> reduced interval ratio, and divide the result by their
;;> sum to the nearest whole number, . . ." [-Ellis]
;;
;; 3477 must be multiplied by 10^4 for integer math

(do
(= centsadd
(/
(* (- larger smaller) bimodulus)
(+ larger smaller)
)
)
)

;;*******************************************************
;;FOR DEBUGGING - TO BE DELETED
;;(pause "larger = " larger "smaller = " smaller "centsadd = "
centsadd)
;;*******************************************************

;;> ". . . and if the quotient is more than 450 add 1." [-Ellis]

(if (> centsadd (* 450 multiplier) )
(do
(= centsadd (+ centsadd (* 1 multiplier) ) )
)
)

;;> "To the result add the numbers of cents from [above]." [-Ellis]

(do
(= cents (+ cents centsadd) )
)

;;--------------------------------------------
;; calculate pitch-bend and midi-note
;;
;; all numbers multiplied by 10^6 for integer math
;; MIDI-notes calculated from "middle-C"

(do
(= semitones cents)
(= hisemitones (+ cents 500000) )
(= closest12eq (- hisemitones (% hisemitones 1000000) ) )
(= eqerror (- semitones closest12eq) )
(= pitchbend (/ eqerror bendcalc) )
(= midinote (+ (+ 60 tonic) (/ closest12eq 1000000) ) )
)

;;*******************************************************
;;FOR DEBUGGING - TO BE DELETED
;;(pause "closest12eq = " closest12eq " eqerror + " eqerror)
;;*******************************************************

;;========================
;; OUTPUT

;;--------------------------------------------
;; Insert the new event into Cakewalk file

(do
(insert Time 1 WHEEL pitchbend)
(insert (+ Time 1) 1 NOTE midinote 64 Duration)
)

)

;; END PROGRAM
;;=======================================================
;; E N D O F P R O G R A M
;;=======================================================

Get Your Private, Free Email at http://www.hotmail.com