Let’s start by all admitting that Equal Temperament is a compromise and that computers can do better. They’re fast at math and nothing physical needs to move, so we can can do better and be more in tune. (The next admission is that I haven’t had the attention span to actually read all the way through the Just Intonation Primer, although it is a very informative book and everyone should buy a copy and actually read it. Nor have a I read Tuning Timbre Spectrum Scale, alas.)
When we say “in tune,” what does that actually mean? On the one hand, we are talking about beating. You know that when you’re trying to tune two sound-generating objects playing the same note, there’s weird phasing and stuff that happens until you get it right. The beating sound you get when tuning a guitar. There’s also just a sort of roughness you hear when you play two notes that are really close to each other, like a C and a C# together. Both of these things seem to have something to do with being in tune and both suggest possible approaches.
Just Intonation, seem to be all about beating and zero crossings. Note relationships described with ratios in which the numerator and denominator are small, whole numbers have less beating. This is because when the waveforms cross, it’s at the low energy position, so they don’t interfere. 3/2 is thus very in tune. You can compute the amount of dissonance by adding the numerator to the denominator. Lower numbers are more in tune.
Bill Sethares, though, likes ten tone equal temperament (and writing songs in Klingon) and came up with some timbres that sound good in such a strange tuning. He’s got some math about dissonance curves. The roughness mentioned above has to do with how our ears work and critical bandwidth. If we hear two tones that are close to each other in pitch, the ear hairs they stimulate overlap, so the interfere with each other and create roughness. We can take a timbre and see how much internal roughness it has and then transpose it a bit and measure the roughness of the original and the transposed version played at the same time. Do this a bunch of times and you get a curve. The minima on the curve are good scale degrees.
Both of these approaches are perceptual and both seem to be in conflict. They both seem to use different parts of our perception, one more around critical band and the other more around amplitude and phase. So I wonder how to get them to work together? I can compute a dissonance curve that goes from 1 -1200 cents, but if I do it from a FFT’s spectrogram, the data I’m putting in is inexact. It only knows 512 frequencies, each of them slightly blurred and I’m using it with 1200 transpositions. Also, the transpositions are appropriately logarithmic, but the bins of the FFT are not, they’re linear. Should I do a similarly linear comparison and save myself a lot of unnecessary computation or does it make sense to do it by cents? Since I know there are artifacts in the spectrogram, should I find the minima and then search for “good” tuning ratios near them? Should the internal dissonance in the sample change the approach that I use?
I ported Sethares’ code to SuperCollider. You can download a working draft of DissonanceCurve.sc, if you desire. It’s quite math intensive for FFTs, but I have a synthDef made up of SinOsc, which is easy to analyze, since all the frequencies and amplitudes are known and there aren’t many of them. The freqs are in f and the amps are in a:
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); e.scale.do({ |deg| postf("Interval % - Dissonance %tRatio % / % n", deg.interval, deg.dissonance, deg.numerator, deg.denominator); });
Which prints
Interval 1 - Dissonance 0.93194694734913 Ratio 1 / 1 Interval 1.1667536657322 - Dissonance 1.1967977845161 Ratio 7 / 6 Interval 1.1905817347928 - Dissonance 1.1395899373121 Ratio 25 / 21 Interval 1.3883134504798 - Dissonance 0.92933737113208 Ratio 118 / 85 Interval 1.4405968618317 - Dissonance 0.95473900132736 Ratio 85 / 59 Interval 1.6798510690642 - Dissonance 0.79165734602377 Ratio 42 / 25 Interval 1.7141578884562 - Dissonance 0.80288033573481 Ratio 12 / 7 Interval 2 - Dissonance 0.49046268655094 Ratio 2 / 1
118 / 85 is not a ratio of small, whole numbers, but it’s apparently less dissonant than 7 / 6 or even 85/59 or even the internal dissonance of the source sound! But, if we look in the curve, we can find the ratios 1 cent distant on either side of 118 / 85:
Interval 1.3875117607442 - Dissonance 0.9386025721761 Ratio 111 / 80 Interval 1.3883134504798 - Dissonance 0.929337371132 Ratio 118 / 85 Interval 1.3891156034233 - Dissonance 0.92966297781753 Ratio 25 / 18
25 / 18 is a much smaller ratio and a distance of 1 cent is not perceivable, so it’s probably a better number. But I am still slightly confused / unconvinced. Note also, that sounds closer to 2/1 are all, in general, less dissonant that sounds closer to 1/1, because of the nature of the algorithm / critical bandwidth. But for just intonation, an inversion is barely more or less dissonant than it’s non-inverted form.
Also, an issue: the width of the critical band changes in different frequency ranges and I think it might help to use the Bark scale or something in the Dissonance Curve code, but the math is, as yet, a bit beyond me.
For the purposes of showing off, here’s a silly example with FFTs, which is not at all real time:(WARNING: THIS IS SLOW!)
b = Buffer.alloc(s,1024); // use global buffers for plotting the data c = BufferTool.open(s, "sounds/a11wlk01.wav"); d = { FFT(b, PlayBuf.ar(1, c.bufnum, BufRateScale.kr(c.bufnum))); 0.0 }.play; // when that's playing, evaluate the following e = DissonanceCurve.newFromFFT(b, 1024, highInterval: 2, action: {arg dis; dis.scale.do({ |deg| postf("Interval % - Dissonance %tRatio % / % n", deg.interval, deg.dissonance, deg.numerator, deg.denominator); }); });
Go and get a snack while that’s going. Make a cup of tea. You won’t be able to do anything else with SuperCollider until it finishes, so leave some comments about tuning. How should I be trying to combine dissonances curves and Just Intonation?
(My result for the code above (timing matters) was:
Interval 1 - Dissonance 2.4284846123288 Ratio 1 / 1 Interval 1.0346671040459 - Dissonance 2.9055490440413 Ratio 30 / 29 Interval 1.0557976305092 - Dissonance 2.9396229209406 Ratio 19 / 18 Interval 1.0588513011885 - Dissonance 2.9394283497832 Ratio 18 / 17 Interval 1.0625273666152 - Dissonance 2.9404120579786 Ratio 17 / 16 Interval 1.0767375682475 - Dissonance 2.9248076874065 Ratio 14 / 13 Interval 1.1114938763335 - Dissonance 2.8528563216285 Ratio 10 / 9 Interval 1.1250584846888 - Dissonance 2.8384180012931 Ratio 9 / 8 Interval 1.1302693892732 - Dissonance 2.8422250578475 Ratio 26 / 23 Interval 1.1335384537169 - Dissonance 2.8404168678269 Ratio 17 / 15 Interval 1.1667536657322 - Dissonance 2.773742908553 Ratio 7 / 6 Interval 1.2002486666653 - Dissonance 2.6741210623142 Ratio 6 / 5 Interval 1.2497735102289 - Dissonance 2.5747254321313 Ratio 5 / 4 Interval 1.2628354511916 - Dissonance 2.5907859768328 Ratio 24 / 19 Interval 1.2664879348481 - Dissonance 2.5910058160679 Ratio 19 / 15 Interval 1.2856518332381 - Dissonance 2.5784271202225 Ratio 9 / 7 Interval 1.3332986770912 - Dissonance 2.4554262314412 Ratio 4 / 3 Interval 1.3503499461682 - Dissonance 2.4863589672953 Ratio 27 / 20 Interval 1.3573881591926 - Dissonance 2.4874055968135 Ratio 19 / 14 Interval 1.3755418181397 - Dissonance 2.469278592016 Ratio 11 / 8 Interval 1.3811148862791 - Dissonance 2.4674194148261 Ratio 29 / 21 Interval 1.3843096285337 - Dissonance 2.4676720796587 Ratio 18 / 13 Interval 1.3891156034233 - Dissonance 2.4680185402198 Ratio 25 / 18 Interval 1.4003945316219 - Dissonance 2.4587789993728 Ratio 7 / 5 Interval 1.4289941397411 - Dissonance 2.432946313225 Ratio 10 / 7 Interval 1.5000389892858 - Dissonance 2.2587031579717 Ratio 3 / 2 Interval 1.5262592089606 - Dissonance 2.3003029027958 Ratio 29 / 19 Interval 1.529789693524 - Dissonance 2.299895874529 Ratio 26 / 17 Interval 1.5333283446696 - Dissonance 2.2993307022943 Ratio 23 / 15 Interval 1.555631119012 - Dissonance 2.2871143779032 Ratio 14 / 9 Interval 1.5619338268699 - Dissonance 2.2878440907054 Ratio 25 / 16 Interval 1.6002899594453 - Dissonance 2.2385589006945 Ratio 8 / 5 Interval 1.6114208563635 - Dissonance 2.2381572659306 Ratio 29 / 18 Interval 1.6188844330948 - Dissonance 2.236239217168 Ratio 34 / 21 Interval 1.625443414535 - Dissonance 2.2331690259349 Ratio 13 / 8 Interval 1.6663213678518 - Dissonance 2.1624083601251 Ratio 5 / 3 Interval 1.68763159226 - Dissonance 2.1765673941027 Ratio 27 / 16 Interval 1.7141578884562 - Dissonance 2.1648475763908 Ratio 12 / 7 Interval 1.7501759894904 - Dissonance 2.1359651045669 Ratio 7 / 4 Interval 1.8004197968362 - Dissonance 2.0659411117752 Ratio 9 / 5 Interval 1.8340080864093 - Dissonance 2.0362153732133 Ratio 11 / 6 Interval 2 - Dissonance 1.6432830079835 Ratio 2 / 1
Yikes)
tuning in the western sense was defined by Pythagorus. it is based upon whole-integer divisions of the length of a string vibrating creating the overtones. these overtones suggested the 12 tones the west settled on for the scale.
just intonation has to do with not trying to temper the scale to the twleve keys, but rather just play in one key and tune for that.
to further complicate things, I learned from tuning pianos that when a string divides into partials, the nodes petween the partials effectively shorten the length of the string, such that the partials “stretch” sharper from the mathematical model as they go up!
Cheers!
The thing about the nodal points shortening the piano strings is really interesting! Thanks for sharing!
Thanks for coding this up, I'm looking forward to playing with it. I have some timbres for which I'd like to map out some candidate ratios for building up layered & sustained textures.