Skip to content

jpmaus/running-man

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

running-man

generates MIDI files from integer sequences

requirements

The running-man executable CDF requires a CDF Player. The running-man editable Wolfram notebook requires Mathematica.

1. pitch class integer notation

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}

2. basic functions

2.1 wolfram language functions

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 oxo + 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.

2.2 integer sequence functions

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

2.3 window function

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}]];
c.f., Mathematica Cookbook, Sal Mangano: 44

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}}

2.4 scale table function

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];

3. MIDI pitch event translations

3.1 mono function

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
3.1.1 variables of the mono function

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

3.1 harmonize function

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.

3.2 poly function

The Poly[] function runs a MovingWindow[] of Harmonize[] over the sets given by Mono[].

Poly[exp_] := MovingWindow[Harmonize, Mono[m], 3, 3];

future work

  • pitch duration / rhythmic generation.
  • harmonies of more than three voices
  • passing tones, suspensions, escape tones, etc.

Releases

No releases published

Packages

No packages published