Play sample with transposition

I am trying to make a sample playback, with a frequency of my choice. So that if I have a sample (a recording), I want to detect it’s pitch first and then transform that pitch by an amount I want (say N semitones). Here is what I have tried:

(
SynthDef(\x, {
	arg kn, buf;
	var sndForPch, snd, freq, hasFreq;
	// Create an input for the pitch detector
	sndForPch = PlayBuf.ar(1, buf, 1, doneAction: 2, rate: BufRateScale.ir(buf));
	# freq, hasFreq = Pitch.kr(sndForPch, minFreq: 20, maxFreq: 20000);
	// Adjust the playback rate
	snd = PlayBuf.ar(1, buf, 1, rate: BufRateScale.ir(buf) * (kn.midicps / freq), doneAction: 2);
	Out.ar(0, snd)
}).add
)

Synth(\x, [buf:c, kn: 60])

The buffer I am using (c) is a percussion sound with (to some degree) recognizable pitch. But the sound I get from my synth seems to me not to be exactly the middle c.
Any ideas, how I could improve my synth?

Maybe try Tartini instead of Pitch for pitch detection.
https://doc.sccode.org/Classes/Tartini.html

I actually am making good experience with Pitch

TL;DR I would hand-tune the sample: Listen to it and you decide what pitch it is. Then the transposition is more likely to match your expectation.

Pitch may be “hearing” the pitch differently from your brain. Pitch may also need time to stabilize – it isn’t safe to assume you’ll get a valid result immediately at sample 0 in the synth.

(
{
	var sig = SinOsc.ar(100);
	var pitch, hf;
	#pitch, hf = Pitch.kr(sig);
	pitch.poll(20);
	Line.kr(0, 1, 0.5, doneAction: 2);
	Silent.ar(1)
}.play;
)

UGen(OutputProxy): 440  -- nope, so your attack will be pitch-smeared
UGen(OutputProxy): 98.8077
UGen(OutputProxy): 100.001
UGen(OutputProxy): 98.8082  -- "stable" = oscillating pitch
UGen(OutputProxy): 100.001
UGen(OutputProxy): 98.8082
UGen(OutputProxy): 100.001
UGen(OutputProxy): 98.8092
UGen(OutputProxy): 100.001
UGen(OutputProxy): 98.8086

I really wouldn’t try to automate this, tbh.

hjh

1 Like