While continuing to ponder tuning, I realized that it would be possible to create a dissonance curve for just intonation. Instead of judging how close the frequencies are to each other to look for roughness, you would look at what tuning ratio they described. If one frequency was 1.5 times the other, then that’s a ratio of 3 / 2. Then add the numerator and denominator to get 5. Then scale by amplitude.

In Sethares’ dissonance curves, you get scale degrees by searching for minima in the curve, but that approach is not a meaningful way to sort just ratios. Instead, they can be sorted by their relative dissonance.

I’ve updated my class, DissonanceCurve.sc (and fixed the url. sorry) so it can do just curves also. I ran it with the following (rough draft-ish) code:

b = Buffer.alloc(s,1024); // use global buffers for plotting the data
c = BufferTool.open(s, "sounds/a11wlk01.wav");
// when that's loaded, evaluate the following
(
Task({
d = SynthDef(foo,
{ FFT(b, PlayBuf.ar(1, c.bufnum, BufRateScale.kr(c.bufnum))); 0.0 }).play;
0.2.rand(3.7).wait;
e = DissonanceCurve.newFromFFT(b, 1024, highInterval: 2, action: {arg dis;
var degr, top5;
d.free;
dis.scale.do({ |deg|
postf(" % / %,",
deg.numerator, deg.denominator);
});
"n---just---".postln;
dis.scale.size.max(25).do({ |index|
degr = dis.just_scale[index];
postf(" % / %,",
degr.numerator, degr.denominator);
});
});
}).play
)

And, after seriously heating up my computer, and waiting a bit, I got the following output:

1 / 1, 29 / 28, 6 / 5 , 5 / 4 , 33 / 26, 4 / 3, 15 / 11, 29 / 21, 7 / 5, 10 / 7,
3 / 2 , 8 / 5, 5 / 3, 27 / 16, 49 / 29, 12 / 7, 67 / 39, 7 / 4, 17 / 9, 2 / 1,
---just---
1 / 1, 3 / 2, 2 / 1, 4 / 3, 5 / 4, 6 / 5, 7 / 6, 9 / 8, 8 / 7, 10 / 9, 5 / 3,
12 / 11, 15 / 14, 13 / 12, 11 / 10, 16 / 15, 9 / 7, 7 / 5, 14 / 13, 22 / 21, 7 / 4,
10 / 7, 21 / 20, 11 / 8, 11 / 9,

The top section is the Sethares algorithm dissonance curve. I made a minor adjustment so that it looks at fractions one cent on either side of them minima and grabs the simpler one if it exists. (This is optional, add “simplify: false” to the method invokation to turn it off.)

The bottom section is the 25 least dissonant just ratios. Looking first at those, note that 1/1 is the least dissonant,as one would expect. Usually, 2/1 would be next, but note that in this case, it’s 3/2 instead. The algorithm does favor low number ratios, which is logical. Notice, also, that it tends to favor smaller numbers. There are a lot of (d+1)/d fractions: 4/3, 5/4, 6/5, 7/6, 9/8. It hugely favors these numbers. The top half of the octave is under represented. I do not know why this is so.

But Sethares’ algorithm, because it uses the critical band, tends to favor higher pitches as more consonant. However, since we search for minima rather than order the intervals by dissonance, this tendency’s effect on the results is reduced.

Both of these computations of dissonance seem to give meaningful data that does seem to have some kind of correlation to each other. On both lists we find, 6/5, 5/4, 4/3, etc. However, the length of the list of just ratios is arbitrary. If we take only the Sethares intervals that are in the top 5% most consonant (least dissonant) just intervals, we are left with:

1/1, 29/28, 6/5, 5/4, 4/3, 15/11, 7/5, 10/7, 3/2, 8/5, 5/3, 12/7, 7/4,
2/1

Of those, 29/28 is the most dissonant, by both measures, so it may not be a the best scale degree. If that’s the case, then the top 5% is not the best cutoff. So what is? How do we choose it?

On the other hand, one way that just intonation is corralled is through factorization limits. For example, 7-limit tuning means that all the numbers in the ratios must be multiples of numbers that are less than 7. So 14 is ok (7 * 2), but 11 and 13 are not, as they’re prime and greater than 7. If we were to apply a 7-limit to the Sethares curve, the scale we would have is

1/1, 6/5, 5/4, 4/3, 7/5, 10/7, 3/2, 8/5, 5/3, 27/16, 12/7, 7/4, 2/1

Is that better? Does the 27/16 (aka: (3*3*3)/(4*4)) impact that?

Alas, we can’t use our ears because we don’t know what moment of the source was measured. But we can use our ears with a synthetic sound whose frequency content is known.

f = [50] ++ ( [50/27, 18/7, 54/25, 25/27, 9/7, 27/25, 25/54, 9/14, 27/50] * 300);
a = [0.055, 0.1, 0.1, 0.1, 0.105, 0.105, 0.105, 0.11, 0.11, 0.11];
e = DissonanceCurve.new(f, a, 2);

With some print statements, abbreviated for the sake of not being too boring, we get a Sethares scale of 1, 7/6, 25/21, 25/18, 36/25, 42/25, 12/7, 2, which, note, falls within a 7-limit. For the top 8 just results, we get, 1, 3/2, 6/5, 5/4, 7/5, 5/3, 34/27, 10/9. A list which does not include 2! And if we do the top 5% thing described above, we get, 1, 7/6, 25/21, 25/18, 36/25, 2. And we can compare these aurally:

(
SynthDef("space", {|out = 0, freq = 440, amp 0.2, dur = 1, pan = 0|
var cluster, env, panner;
// detune
freq = freq + 2.0.rand2;
cluster =
SinOsc.ar(50, 1.0.rand, 0.055 * amp) +
SinOsc.ar((freq * 50/27) + 1.0.rand2, 1.0.rand, 0.1 * amp) +
SinOsc.ar((freq * 18/7) + 1.0.rand2, 1.0.rand, 0.1 * amp) +
SinOsc.ar((freq * 54/25) + 1.0.rand2, 1.0.rand, 0.1 * amp) +
SinOsc.ar((freq * 25/27) + 1.0.rand2, 1.0.rand, 0.105 * amp) +
SinOsc.ar((freq * 9/7) + 1.0.rand2, 1.0.rand, 0.105 * amp) +
SinOsc.ar((freq * 27/25) + 1.0.rand2, 1.0.rand, 0.105 * amp) +
SinOsc.ar((freq * 25/54) + 1.0.rand2, 1.0.rand, 0.11 * amp) +
SinOsc.ar((freq * 9/14) + 1.0.rand2, 1.0.rand, 0.11 * amp) +
SinOsc.ar((freq * 27/50) + 1.0.rand2, 1.0.rand, amp * 0.11);
env = EnvGen.kr(Env.perc(0.05, dur + 1.0.rand, 1, -4), doneAction: 2);
panner = Pan2.ar(cluster, pan, env);
Out.ar(out, panner);
}).send(s);
)
(
Pbind(
//Sethares
freq, Prand([1, 7/6, 25/21, 25/18, 36/25, 42/25, 12/7, 2] *300, 27),
dur, 0.3,
instrument, space,
amp, 0.2,
pan, 0
).play
)
(
Pbind(
// Just
freq, Prand([1, 3/2, 6/5, 5/4, 7/5, 5/3, 34/27, 10/9] *300, 27),
dur, 0.3,
instrument, space,
amp, 0.2,
pan, 0
).play
)
(
Pbind(
// Top 5%
freq, Prand([1, 7/6, 25/21, 25/18, 36/25, 2] *300, 27),
dur, 0.3,
instrument, space,
amp, 0.2,
pan, 0
).play
)

Which of those pbinds do you think sounds best? Leave a comment.