home/ atoms/ sc-spectral-tuning-partials-match

Aligning a synth's partials with a non-12 equal temperament increases the consonance of chords in that tuning

Perceived consonance depends not only on the interval ratios of a scale but on whether the timbre’s partials coincide with the scale’s available pitches. When you play an unfamiliar equal temperament (e.g. 7 equal steps per octave) with a plain harmonic timbre, beating between mistuned harmonics can sound rough. Chapter 17 addresses this by constructing a set of ‘virtual partials’ that lie on the temperament’s own grid — a function fills an array with 2.pow(i/stepsPerOctave) for each step, optionally octave-multiplied — and drives an additive SynthDef from that array. The synth’s spectrum is then matched to the tuning, so intervals that are in tune in the temperament also have coinciding partials and sound more fused. This is the SuperCollider realisation of Sethares-style timbre/tuning matching: change the tuning and you must re-derive the timbre to keep it consonant.

Examples

~harmsfunc = { |stepsperoctave=7| var harms = Array.fill(stepsperoctave, { |i| 2.pow(i/stepsperoctave) }); harms.size.do { |i| if(0.6.coin){ harms[i] = harms[i] * [1,2,4,8].choose } }; harms.sort }; ~harms = ~harmsfunc.value(7); // SynthDef \partials sums SinOsc.ar(freq * harms[i], …) so partials sit on the 7-EDO grid

Assessment

Play a 7-step-per-octave Pbind first with a plain harmonic saw, then with an additive synth whose partials are derived from 2.pow(i/7). Describe the change in roughness. Explain why re-deriving partials is required when stepsPerOctave changes.

“~harmsfunc = {arg stepsperoctave=7; var harms; // calculate each note from the tuning harms = Array.fill(stepsperoctave, {arg i; 2.pow(i/stepsperoctave)”
corpus · the-supercollider-book-official-code-examples-scbookcode-gpl · chunk 65