rationale behind n/r/noop
[email protected] ("Sean M. Burke") Sun, 20 May 2001 18:21:28 -0600
| Newsgroups | perl.midi |
|---|---|
| Message-ID | <[email protected]> |
The previous post explains how n/r/noop behave currently. However, to actually understand why they are that way, below I've pasted in exerpts from my TPJ article about MIDI-Perl, http://www.speech.cs.cmu.edu/~sburke/midi-perl/tpj_13_midi.html ...which I think I'll bundle in the next dist. The whole article is long, but quite worth reading and rereading, since it gives a lot of necessary backstory on MIDI-Perl. The typical event's [i.e., note's] parameters of duration, pitch, volume, and channel, are mostly the same from one event to the next. So, in the name of brevity, I decided that each note's properties should be inherited from the previous note, overridden with whatever new properties are defined in this call. [...] Now, at this point I noticed that the notes are thought of (at least for many purposes) not as each being on such-and-such octave, but instead that there's a notion of ``current octave'', which notes being composed are thought of as being in -- or as being in an octave above, or below. So I added yet another way to specify pitches: besides by number (``n25'') or by note-and-octave (``Cs2''), one can specify them in terms of just note-letter: ``Cs'' -- meaning, ``C sharp in the current octave''. I call this a ``relative'' note specification, in distinction to ``Cs2'' and ``n25'' which I call absolute. As to where the value ``current octave'' comes from: it's a number stored in a state variable called $Octave, which can be set directly, or which can be set by calling n or r with a parameter in the form ``o6'' (where ``6'' can be replaced by any number ``0'' to ``10''), and incidentally will be set as a side-effect of calling n or r with any absolute note specifications. [...] MIDI has a special reserved channel, channel 9, where numbers for pitches are interpreted as each a special percussive instrument-sound. For example, ``n35'' (i.e., ``B2'') on channel 9 doesn't mean a B2 on the current patch for channel 9, but instead it means a (basically untuneable) note on an acoustic bass drum. So, lines of code to generate bunches of percussion notes often look like this: n c9, ff, n41, qn; r; n; r; n; r; which adds to the score a quarter note, a quarter rest, a quarter note, and a quarter rest, all played on the acoustic bass drum. However, the way this is coded, above, looked to me a perfect violation of ``uniformity'', a concept I first saw expressed in Weinberg's The Psychology of Computer Programming, in the chapter ``Some Principles for Programming Language Design'' (1971:219). To Weinberg's way of thinking, uniformity is a psychological principle, where users/programmers expect that things that look similar should do similar things, and conversely that things that look different should do different things. But the first call to n, above, and the second and third calls to n, look very different, even though all they do the same thing. What I wanted was a way to set up all the state variables, and then be able to just say ``n;r;n;r;''. Now, I could just say: $Channel = 9; $Volume = 112; $Duration = 96; @Notes = (41); n; r; n; r; But that seemed inelegant. What I ended up doing was adding another function, called noop (for ``no-operation''), which parses options just the same as n and r, and thereby has all the side-effects, but doesn't actually affect the score. For example, consider these three lines of code: n qn, C3; # C3 = n36, by the way r qn, C3; noop qn, C3; The first one has the main effect of adding a note to the score, and incrementing $Time by the duration of a quarter note. The second one adds nothing to the score, but has the main effect of incrementing $Time (this is how I implement rests -- just time consumed). And the third one alters neither the score, nor $Time. But it does have all the same side-effects as the first two: it sets $Duration to the duration of a quarter note, and it sets @Notes to (36). With noop, you get to write code like: noop c9, ff, n41, qn; # The setup... n; r; n; r; # ...and the work. This not to say that you have to do it this way; but allowing for the organization of code to reflect different ways of organizing thought is the Perl way: ``there's more than one way to do it''. (Incidentally, I do not mean to imply that ``noop'' is to be used only for dealing with percussion; it's simply that ``noop'' is meant to solve the kinds of non-uniformity problems which became most apparent to me in percussion code.) -- Sean M. Burke [email protected] http://www.spinn.net/~sburke/