Harpsichord synth - individual detune array for each frequency

Hi!

I am trying to create a harpsichord synth in which the strings for each note would be hit at small onset different times (50-90ms) also with a small detuning between each string freq * {rrand(1-percentDetune, 1+percentDetune)}.dup(4) .

(
SynthDef(\harpsi, { |outbus = 0, freq = 440, amp = 1.0, percentDetune = 0.003, detuneRand = 0.002, atk=0.001, rel=0.5 |
	var out, env, sig;
	env = EnvGen.ar(Env.perc(atk, rel), doneAction: Done.freeSelf) * amp;
	sig = DelayN.ar(
		Pulse.ar(freq * {rrand(1-percentDetune, 1+percentDetune)}.dup(4), 0.125, 0.75),
		0.090, {rrand(0.050, 0.090)}.dup(4)).sum;
	out =  sig * env;
	Out.ar(outbus, LeakDC.ar(out ! 2));
}).add;
)

Pbind(\instrument, \harpsi, \amp, 0.25, \degree, Pseries(0, 1, 8), \dur, 0.25).play;

I manage to have a global detune for each harpsichord key as well as a global difference in the attack onset. How would it be possible to have a unique detuning for each harpsichord key (freq) as well as unique onset difference for each key?

Any other considerations about how to improve the synthesis model of a harpsichord?

Hi John,
you can do everything you have described directly inside a pattern!

(
s.waitForBoot {
	SynthDef(\harpsi, { 
		var env = Env.perc(\atk.kr(0.01), \rel.kr(1.0)) .ar(2, \gate.kr(1));
		var sig = Pulse.ar(\freq.kr(220));
		var out = sig * env * \amp.kr(0.2);
		OffsetOut.ar(\out.kr(0), out!2)
	}).add;
	
	s.sync;
	
	Pbind(
		\instrument, \harpsi, 
		\amp, 0.25, 
		\degree, Pn(Pseries(0, 1, 8), inf),
		\dur, 1,
		\mtranspose, [0, 0.013, -0.011, 0.023, -0.032], // detune in cents
		\strum, 0.005 // time between each detuned freq - make it big to see the effect
	).play;
}
)

If you want to change the \mtranspose or \strum for each note, you could use a Pfunc or Pwhite, like this:

\mtranspose, Pfunc({   {0.01.rand2}!4   }).trace, 
\strum, Pwhite(0.001, 0.1)

This, isn’t a ‘a global detune for each harpsichord key’, but a global detune for all harpsichords as the randomness is only evaluated when the synthdef is defined.

1 Like

Thanks a lot!

From my little knowledge on patterns, I think that you can’t pass an array for the key \strum because it won’t multichannel expand, right? Or is there another built-in key to treat onsets like initial phase and not as a global different time between strummed notes?

Regarding the Hasher, is it possible to multichannel expand twice? For instance, here are four different detuned versions of a Pulse.

Pulse.ar(freq * {Hasher.kr(freq).range(1-(percentDetune+Rand(0, detuneRand)), 1+percentDetune+Rand(0, detuneRand))}.dup(4), 0.125, 0.75)

If I use [freq,freq*2] I am going to get this?

[
Pulse.ar(freq * {Hasher.kr(freq).range(1-(percentDetune+Rand(0, detuneRand)), 1+percentDetune+Rand(0, detuneRand))}.dup(4), 0.125, 0.75),
Pulse.ar(freq*2 * {Hasher.kr(freq).range(1-(percentDetune+Rand(0, detuneRand)), 1+percentDetune+Rand(0, detuneRand))}.dup(4), 0.125, 0.75),
]

and each octave will have their own singular 4 detuned oscillators?