Issues with fractional intervals in crow's scales

I’ve been searching for days now and I can’t find enough documentation about the new crow ‘scale’ input and output modes. I’ve seen in other threads people just write scales like this {1/1, 3/2, 5/4} with no issue, but it seems to have no effect for me. basically the first 11 keys of an octave play only something like 900 cents from C to B and then the next C jumps a whole octave

1 Like

We do need to get that documentation updated! For now the best place for example usage is in the PRs for Input and Output.

Currently, the system is built to handle scales in ‘semitone’ form. There is an update (coming soon) to handle just-ratios like in your example. That will be part of the impending 3.0 release (which we’re currently beta-testing).

6 Likes

Will the just-ratios allow for microtuning, for example Arabic scales? That would be awesome!

microtuning is already available with the input[n].scale method. typically a scale would be {0,2,4,7,9} (major pentatonic), but you can microtune any scale element with a float: eg. {0,2.1,4,7,9} for a sharpened 2nd degree.

just-ratios are kind of their own tuning system where ‘microtuning’ as a concept doesn’t really make sense. typically in just intonation, you have to make decisions about how your intervals are tuned – eg. there are many ratios all considered to be a ‘major 3rd’, but with different tuning ratios giving different feelings of consonance and dissonance.

6 Likes

I’ve been using this script to work around it, with some added chord functionality to it. This is my first lua script so I have no idea about best practices and whatnot but it seems to be working fine

edit: I should add that this only works with tunings with 12 defined intervals, it used to work with differently sized tunings but I’ve since added the chord functionality and forgot to fix it

--tunes
--in1 equal temperament 1V/oct input
--out1-3 scale quantized intervals

--tunings
ptolemaic = {scale = {1/1, 16/15, 9/8, 6/5, 5/4, 4/3, 45/32, 3/2, 8/5, 5/3, 9/5, 15/8}, size = 12}
overtone = {scale = {1/1, 17/16, 9/8, 19/16, 5/4, 21/16, 11/8, 3/2, 13/8, 27/16, 7/4, 15/8}, size = 12}
edoisland = {scale = {1/1, 9/8, 15/13, 13/10, 4/3, 3/2, 17/11, 19/11, 16/9}, size = 9}
superpyth = {scale = {1/1, 24/23, 13/12, 20/17, 27/22, 4/3, 18/13, 13/9, 25/16, 31/19, 23/13, 24/13}, size = 12}

--scales
major = {1, nil, 2, nil, 3, 4, nil, 5, nil, 6, nil, 17}
minor = {1, nil , 2, 3, nil, 4, nil, 5, 6, nil, 17, nil}

--setup
tuning = superpyth
root = 5 --0   1    2   3    4   5   6    7   8    9   10   11
         --C - C# - D - D# - E - F - F# - G - G# - A - A# - B

--program
scale = minor
tunedNotes = tuning.scale
temperament = tuning.size

function quantize(volts, offset)
    volts = volts - (root / 12)
    interval = math.floor((volts % 1.0) * temperament) + offset
    octave = math.floor(volts)
    if interval > 11 then
        octave = octave + 1
        interval = interval - 12
    end
	return tunedNotes[interval + 1] - 1.0 + octave + (root / 12)
end

function chord(volts, first, second, third)
    return {first = quantize(volts, first), second = quantize(volts, second), third = quantize(volts, third)}
end

function scaler(volts, scaleType)
    interval = math.floor((volts % 1.0) * temperament)
    degree = scale[interval + 1]
    if scaleType == 'minor' then
        if degree == nil then
            notes = chord(volts, 0, 5, 7)
        elseif degree == 1 or degree == 4 or degree == 5 then
            notes = chord(volts, 0, 3, 7)
        elseif degree == 2 then
            notes = chord(volts, 0, 3, 6)
        else
            notes = chord(volts, 0, 4, 7)
        end
    elseif scaleType == 'major' then
        if degree == nil then
            notes = chord(volts, 0, 5, 7)
        elseif degree == 1 or degree == 4 or degree == 5 then
            notes = chord(volts, 0, 4, 7)
        elseif degree == 7 then
            notes = chord(volts, 0, 3, 6)
        else
            notes = chord(volts, 0, 3, 7)
        end
    end
    return notes
end

input[1].stream = function(s)
    notes = scaler(input[1].volts, 'minor')
    output[1].volts = notes.first
    output[2].volts = notes.second
    output[3].volts = notes.third
end

function init()
    input[1].mode('stream', 0.01)
    input[2].mode('none')
    for n = 1,4 do
        output[n].slew = 0
        output[n].volts = 0
    end
end

1 Like