generates MIDI files from integer sequences
The running-man executable CDF requires a CDF Player. The running-man editable Wolfram notebook requires Mathematica.
running-man uses integer notation which represents notes as pitch classes (PCs). For example, C♮ Major Triad {0, 4, 7}, D♮ Minor Triad {2, 5, 9}, F♮ Major Seventh Chord {5, 9, 0, 4}; etc. In PC integer notation each pitch is included in the same class regardless its octave position (e.g., C4 = 0, C5 = 0; D3 = 2, D6 = 2; etc.).
Letter Notation | Pitch Class |
---|---|
C♮ | 0 |
C♯ | 1 |
D♮ | 2 |
D♯ | 3 |
E♮ | 4 |
F♮ | 5 |
F♯ | 6 |
G♮ | 7 |
G♯ | 8 |
A♮ | 9 |
A♯ | 10 |
B♮ | 11 |
E♮ Minor Triad | {4, 5, 9} |
C♮ Major Scale | {0, 2, 4, 5, 7, 9, 11} |
running-man makes frequent use of these basic Wolfram Language functions. For more detailed explanations of these functions, visit the Reference Site.
- Range[n] gives the set {1, 2, ..., n}.
- Table[f, n] gives the set of n values of f.
- With[{a=x, b=y, ...}, expr] replaces all a, b, ... in expr with x, y, ...
- Take[set, n] gives the first n elements belonging to set.
- Mod[m, n, o] gives the remainder after division of dividend m by divisor n (i.e., m mod n), defining the optional offset o argument gives the x such that o ≤ x ≥ o + n and x mod n = m mod n.
- Map[f, set ] or f/@set applies f to each element belonging to set.
- Flatten[set] gives the set of subsets and atomic elements (elements that do not belong to a subset) belonging to set.
- Differences[set] gives the successive differences between each element belonging to set.
- LinearRecurrence[ker, int ,n] gives the set of n values of the linear recurrence relation with kernel ker and initial values int.
The Wolfram Language contains an extensive collection of integer sequence functions. For example, the 4th number of the Fibonacci sequence (i.e., 1, 1, 2, 3, 5, ...) can be given by entering:
In[]:= Fibonoacci[4]
Out[]:= 3
and iterative functions (e.g, Table[], Range[]) will generate a set of each sucessive element in the sequence:
In[]:= Fibonacci[Range[12]]
Out[]:= {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144}
In[]:= Table[Fibonacci[x], {x, 1, 12}]
Out[]:= {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144}
The Online Encyclopedia of Interger Sequences also contains formulae for generating integer sequences in the Wolfram Language. For example, the OEIS entry for the square numbers OEIS A000290 contains the following code for generating the square numbers using the LinearRecurrence[] function:
In[]:= LinearRecurrence[{3, -3, 1}, {0, 1, 4}, 12]
Out[]:= 0,1,4,9,16,25,36,49,64,81,100,121,144
running-man uses a moving window function to position and/or aggregate succesive integers along a time axis:
MovingWindow[f_, exp_, n_, o_] :=
Module[{len = Length[exp], end}, end = Min[n, len] - 1;
Table[Apply[f, {exp[[i ;; i + end]]}], {i, 1, len - end, o}]];
The MovingWindow[f, set, n, o] function positions and/or aggregates elements generated by f by groups of n at an offset of o. For example, using the MovingWindow[] with function Take[set,n], and a group and offset of 3 gives:
In[]:= MovingWindow[Take, Fibonacci[Range[9]], 3, 3]
Out[]:={{1, 1, 2}, {3, 5, 8}, {13, 21, 34}}
a group of 3 and an offset of 1 gives:
In[]:= MovingWindow[Take, Fibonacci[Range[9]], 3, 1]
Out[]:= {{1, 1, 2}, {1, 2, 3}, {2, 3, 5}, {3, 5, 8}}
a group of 1 and an offset of 3 gives:
In[]:=MovingWindow[Take, Fibonacci[Range[9]], 1, 3]
Out[]:={{1}, {3}, {13}}
running-man provides a function for generating tables of scale sequences for ease of adding new modes:
ScaleTable[seq_, max_, final_: 12] :=
Append[Flatten[Table[seq, max]], final];
For example:
ionian = ScaleTable[{0, 2, 4, 5, 7, 9, 11}, 36];
running-man uses the Mono[] function to translate the integer sequences into MIDI pitch events in the scale m:
Mono[m_] :=
With[{arb = exp}, Take[arb, {#}] & /@ Mod[d@F[ln], mB, mI]];
c.f., Programming Avro Part, link
In the exceutable CDF, variables of the Mono[] function are assigned by way of GUI. When running-man is initialized, the variables of the Mono[] function (e.g., d, F, len, ...) are automatically assigned the following values:
variable | assignment |
---|---|
mB = 7 | The Modular Divisor |
mI = 1 | The Modular Offset |
d = Flatten | If d = Flatten[], pitches are generated from successive cardinalities. If d = Differences[], pitches are generated from successive differences. |
F = Fibonacci[] | The integer sequence function (e.g., Prime, Square, Odd, etc) used to generate pitches. |
len = 100 | The length of the pitch set to be generated |
m = {0, 2, 3, 5, 7, 9, 10, 0, 2, 3, 5, 7, 9, 10} | The integer notation for the Dorian mode |
In[]:= Mono[dorian]
Out[]:= {0, 0, 2, 3, 7, 0, 9, 10, 9, 9, 7, 5}
change a variable to generate pitches from differences rather than from cardinalities:
In[]:= d = Differences;
Out[]:= {10, 0, 0, 2, 3, 7, 0, 9, 10, 9, 9}
change a variable to generate pitches from ionian scale rather than from the dorian scale:
In[]:= Mono[ionian]
Out[]:= {11, 0, 0, 2, 4, 7, 0, 9, 11, 9, 9}
The table below illusrates how Mono[dorian] with F defined as the Fibonacci sequence (1, 1, 2, 3, 5, ...) translates the sequence into pitch events in the dorian scale.
function | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
dorian PCs | 0 | 2 | 3 | 5 | 7 | 9 | 10 | 0 | 2 | 3 | 5 | 7 |
Fn+1 mod 7 | 1 | 1 | 2 | 3 | 5 | 1 | 6 | 7 | 6 | 6 | 5 | 4 |
Fn+1 mod 7 /@ dor PCs | 0 | 0 | 2 | 3 | 7 | 0 | 9 | 10 | 9 | 9 | 7 | 5 |
Δ Fn+1 mod 7 /@ dor PCs | N/A | 10 | 0 | 0 | 2 | 3 | 7 | 0 | 9 | 10 | 9 | 9 |
The Harmonize[] function gives a nested subset (i.e., aggregate, a chord) of any three consecutive PCs constituting a major or a minor triad.
Harmonize[exp_] :=
With[{n1 = Take[exp, {1}], n2 = Take[exp, {2}],
n3 = Take[exp, {3}]},
If[n2 == (n1 + 0) && n3 == (n1 + 0) ||
n2 == (n1 + 0) && n3 == (n1 + 3) ||
n2 == (n1 + 0) && n3 == (n1 + 7) ||
etc. etc.
The Poly[] function runs a MovingWindow[] of Harmonize[] over the sets given by Mono[].
Poly[exp_] := MovingWindow[Harmonize, Mono[m], 3, 3];
- pitch duration / rhythmic generation.
- harmonies of more than three voices
- passing tones, suspensions, escape tones, etc.