Created
November 13, 2011 15:47
-
-
Save andrewcsmith/1362240 to your computer and use it in GitHub Desktop.
helmholtz-ellis string parsing for supercollider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Basic idea of string parsing comes from Marc Sabat and Wolfgang Von Schweinitz's "Helmholtz-Ellis" set of accidentals. These accidentals take all uninflected ("normal") accidentals like naturals, sharps and flats as 3-limit Pythatgorean alterations. Further alterations include small arrows (for the 5-limit 81/80), Tartini-inspired 7s (for 7-limit 64/63), and quarter-tones for the unidecimal alteration 33/32. | |
I've found that while SuperCollider is great at creating scales and tunings, it's tough to really sequence a full pattern without cycling through a bunch of different tunings--it still seems conceptually tied to MIDI in that sense. So in order to sequence extended just intonation, it's important to have an easy, legible way of reading these pitches. | |
I've transported my Lilypond definitions to SuperCollider. "aflatUfDs" (the test String) is a Pythagorean a-flat, up a five-limit 81/80, down a seven-limit 63/64. This creates the interval 14/15, or a perfect fourth above the septimal tri-tone against an uninflected "a". | |
*/ | |
HETuner { | |
var <>base, <>octave; | |
*new { |tuning_base, starting_octave| | |
^super.new.init(tuning_base, starting_octave); | |
} | |
init { |tuning_base, starting_octave| | |
this.base = tuning_base; | |
this.octave = starting_octave; | |
} | |
parse {|note_string| | |
var pitch = List.new(0); | |
var ratio = 1; | |
// Find the note name | |
pitch.add(note_string.findRegexp("^[abcdefg]")); | |
// Find sharps or flats | |
pitch.add(note_string.findRegexp("sharp|flat")); | |
// Find microtonal alterations | |
pitch.add(note_string.findRegexp("[UD][fset]")); | |
// Find any octave alterations | |
pitch.add(note_string.findRegexp("[,']")); | |
// Flatten the list and remove the indexes (just want a bunch of strings) | |
pitch = pitch.flatten.flatten; | |
pitch.do({|item, index| | |
if(item.class == Integer, | |
{pitch.removeAt(index)})}); | |
// Find the intitial pitch, relative to A = 1/1 | |
pitch.do({|item, index| | |
switch (item, | |
"a", {ratio = 1;}, | |
"b", {ratio = 1.125;}, | |
"c", {ratio = 1.1851851851852;}, | |
"d", {ratio = 1.3333333333333;}, | |
"e", {ratio = 1.5;}, | |
"f", {ratio = 1.5802469135802;}, | |
"g", {ratio = 1.7777777777778;}) | |
}); | |
pitch.do({|item, index| | |
switch (item, | |
",", {ratio = ratio * 0.5;}, | |
"'", {ratio = ratio * 2.0;} | |
) | |
}); | |
// Calculate all accidentals (pythagorean & microtonal) | |
pitch.do({|item, index| | |
switch (item, | |
"flat", {ratio = ratio * 0.93644261874343;}, | |
"sharp", {ratio = ratio * 1.06787109;}, | |
"Df", {ratio = ratio * 0.98765432098765;}, | |
"Uf", {ratio = ratio * 1.0125;}, | |
"Ds", {ratio = ratio * 0.984375;}, | |
"Us", {ratio = ratio * 1.015873015873;}, | |
"De", {ratio = ratio * 0.96969696969697;}, | |
"Ue", {ratio = ratio * 1.03125;}, | |
"Dt", {ratio = ratio * 0.96296296296296;}, | |
"Ut", {ratio = ratio * 1.0384615384615;} ) | |
}); | |
// Return the final altered pitch | |
^(ratio*base*(2**octave)); | |
} | |
parse_list { |note_list| | |
var seq = List.new(0); | |
note_list.do({|item, index| | |
seq.add(this.parse(item)); | |
}); | |
^seq; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI, my score looks something like this (\guitar is sort of my all-purpose instrument):