Smoke Music Magnitude Models

Smoke uses objects called music magnitudes to represent the basic "units of measure" of musical sound: duration, pitch, amplitude, etc. MusicMagnitude objects are characterized by their identity, class, species, and value (e.g., the pitch object that represents 'c3' has its object identity, the class SymbolicPitch, the species Pitch, and the value 'c3' [a string]). MusicMagnitude behaviors distinguish between class membership and species in a multiple-inheritance-like scheme that allows the object representing "440.0 Hz" to have pitch-like and limited-precision-real-number-like behaviors. This means that its behavior can depend on what it represents (a pitch), or how its value is stored (a floating-point number).

The mixed-mode music magnitude arithmetic is defined using the technique of species-based coercion, i.e., class Pitch knows whether a note name or Hertz value is more general. This provides capabilities similar to those of systems that use the techniques of multiple inheritance and multiple polymorphism (such as C++ and the Common Lisp Object System), but in a much simpler and scalable manner. All meaningful coercion messages (e.g., (440.0 Hz) asMIDIKeyNumber)), and mixed-mode operations (e.g., (1/4 beat + 80 msec)) are defined.

The basic model classes include Pitch, Loudness, and Duration; exemplary extensions include Length, Sharpness, Weight, and Breath for composition- or notation-specific magnitudes. The handling of time as a parameter is finessed via the abstraction of duration. All times are durations of events or delays, so that no "real" or "absolute" time object is needed. Duration objects can have simple numerical or symbolic values, or they can be conditions (e.g., the duration until some event X occurs), Boolean expressions of other durations, or arbitrary blocks of Smalltalk-80 code.

Functions of one or more variables are yet another type of signal-like music magnitude. The MODE Function class hierarchy includes line segment, exponential segment, spline segment and Fourier summation functions.

In the verbose SmOKe format music magnitudes, events and event lists are created by instance creation messages sent to the appropriate classes. The first three expressions in the examples below create various music magnitudes and coerce them into other representations.

The terse form for music magnitude creation uses post-operators (unary messages) such as 440 hz or 250 msec, as shown in the examples below.

Users can extend the music magnitude framework with their own classes that refine the existing models of define totally new kinds of musical metrics.

Basic MusicMagnitude Models

Pitches
   HertzPitch -- 440.0 hz
   MIDIPitch -- 60 pitch -- can be non-integer for microtonal tunings (use #asFracMIDI)
   SymbolicPitch -- 'c#3' pitch -- can have a remainder for microtonal tunings
   RatioPitch -- 11/9 of: anotherPitch -- used for fraction-oriented tunings
   
Durations
   SecondDuration -- 1 sec
   MSecondDuration -- 100 msec
   RatioDuration -- 1/4 beat
   ConditionalDuration -- until: [ :t | block]

Amplitude/Loudness Objects
   DBLoudness -- -3 dB -- can be relative to 0 dB or positive-valued
   RatioLoudness -- 0.7071 ampl
   SymbolicLoudness -- 'fff' ampl
   MIDIVelocity -- 96 vel

Other Music Magnitudes
   OrdinalMagnitudes -- have order but no explicit value
   PField -- name/slot/value -- used for note lists

MusicMagnitude Examples

Verbose MusicMagnitude Creation and Coercion Messages

   (Duration value: 1/16) asMsec         "Answers Duration 62 msec."
   (Pitch value: 60) asHertz             "Answers Pitch 261.623 Hz."
   (Amplitude value: 'ff') asMIDI         "Answers MIDI key velocity 100."

Terse MusicMagnitude Creation using post-operators

   440 Hz               "a HertzPitch"
   'c#3' pitch            "a SymbolicPitch"
   60 pitch               "a MIDIPtch"
   250 msec            "a MSecondDuration"
   1/4 beat               "a RatioDuration"

MusicMagnitude Coercion Examples

   440 Hz asSymbol      "--> 'a3' pitch"
   (1/4 beat) asMsec      "--> 250 msec"
   #mf ampl asMIDI         "--> 70 vel"

Duration Coercion Example--create a 1/8 beat duration and coerce it into msec, printing the result to the Smalltalk transcript. (To execute this, double-click just inside the open-bracket to select the entire expression and use the pop-up menu of command key to "do it.")

   [ | me |
   me := Duration value: 1/8.
   Transcript cr; show: me printString, ' = ',
      me asSec printString; cr] d

Pitch Coercion Example--create a named pitch (middle C) and print it to the transcript as Hz and as a MIDI key number.

   [ | me |
   me := Pitch value: 'c3'.
   Transcript show: me printString, ' = ',
      me asHertz printString, ' = ',
      me asMIDI printString; cr.
   "me inspect"] d

Amplitude Coercion Example--create a named dynamic value and print it as an amplitude ratio and a MIDI velocity.

   [ | me |
   me := Amplitude value: #mf.
   Transcript show: me printString, ' = ',
      me asRatio printString, ' = ',
      me asMIDI printString; cr.
   "me inspect"] d

Mixed-mode Arithmetic--demonstrate adding beats and msec, or note names and Hertz values. Select and print these.

   [(1/2 beat) + 100 msec]         " (0.6 beat")
   ['a4' pitch + 25 Hz]            " (465.0 Hz)"
   [('a4' pitch + 100 Hz) asMIDI]      " (73 key)"
   [('a4' pitch + 100 Hz) asFracMIDI]   " (72.5455 key)"
   ['mp' ampl + 3 dB]               " (-4.6 dB)"

Alberto de Campo's microtonal extensions allow MIDI pitches to be floating-point numbers (e.g., MIDI key 60.25) and named pitches to have "remainder" values (e.g., c3 + 25 cents) as in the following examples.

   [438 Hz asSymbol]        "rounds to nearest chromatic note, a3."
   [443.5 Hz asMIDI]      "ditto."
   [265 Hz asFracMIDI]      "converts to float chromatics; can be rounded, used
                     for MIDI pitch bend or for precise synthesis in Hz."
   [61.26 key asHertz]      "float chromatics can also be used directly; for
                     microtonal scales this is clearer than Hz (to me at least)."
   [260.0 Hz asFracSymbol]    "is rounded, but keeps track of offsets in
                     an inst var (fracPitch); survives conversions etc."

Note that asMIDI and asSymbol can now be used to round pitches to chromatics, while the messages asFracMIDI and asFracSymbol keep the full microtonal precision.