I'm implementing the Yin Algorithm in Python so as to extract the pitch of my voice when whistling or humming. My goal is to produce the Gate (Envelop Control) and CV (Pitch Control) signals which can be inputted to an analog synth. I'd also like to write a software synth which takes theses signals as input. That way I can play the synth with my voice.

The top graph below is the output of the YIN algorithm when I whistled a few notes:

enter image description here

I then tidied this up with a low pass filter to produce the signal in the second graph. Finally and perhaps naively, I produced the third signal as follows:

from scipy.io.wavfile import write
sr = 16000 # sample rate
f = [518.8087307738297, 518.9079938888592, 518.9177212823167, 519.8298830180304, 522.3027794382949, 523.8695096842832, 524.859458031283, 525.4703986196301, 525.4431662533539, 525.6859351990167, 525.6523745060124, 525.9697551477367, ...]
out = [math.cos(2*math.pi*f[i]*(i/sr)) for i in range(len(f))] 

So in other words:

cos(2 pi f t)

where f(t) is the signal in the second graph. I expected this to produce a signal similar to that of my whistling recording put with constant amplitude. However, I get a really chirpy sounding signal that doesn't remind me at all of my original recording. If I use the first signal in my graph as f(t) I get noise when I apply it to cos(2 pi f t). What am I misunderstanding here? Here are the signals from samples 20000 to 30000. How should I reproduce a signal reminiscent of my original recording if I have the instantaneous frequency?

enter image description here

  • 4
    $\begingroup$ Try $\cos(2\pi \int_0^t f(t) dt )$ instead. $\endgroup$ – Jazzmaniac Sep 19 at 21:23
  • $\begingroup$ good to see you back, Jazz. $\endgroup$ – robert bristow-johnson Sep 20 at 3:23
  • $\begingroup$ I'm not "back" and I won't be contributing any answer apart from the occasional comment. $\endgroup$ – Jazzmaniac Sep 20 at 9:21
  • $\begingroup$ @Jazzmaniac Thanks for the comment. Why does integrating f(t) work? $\endgroup$ – Baz Sep 20 at 10:17
  • 1
    $\begingroup$ @Baz the instantaneous frequency of a sinusoid is the rate of change of its argument (which is called the phase of the sinusoid). The time derivative of your argument would be $2\pi( f'(t)*t + f(t) )$, which is not what you want. The time-derivative of my argument is just $2\pi f(t)$. $\endgroup$ – Jazzmaniac Sep 20 at 12:37

The f[i] * i together determine the phase and frequency at every i so sine wave is only rendered correctly if there is no speed change, so the algorithm must be changed to allow for continuous time i and any change in frequency must not cause a phase jump.

So try a phase accumulator approach, where phase for each i is incremented as required by the frequency.

| improve this answer | |
  • $\begingroup$ I'm now calculating the integral of the pitch, f(t), using integral = scipy.integrate.cumtrapz(np.array(f), dx=1/sr, initial = 0) and then I can use cos(2*pi*integral[t]) $\endgroup$ – Baz Sep 20 at 20:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.