Hey List,

I made a UDO over the weekend implementing Yin pitch detection algorithm, with a good bit of help from looking at the Aubio library's version, it seems to work pretty well and is comparable in accuracy with the pvspitch and ptrack opcodes, it doesn't use too much cpu either. Anyways heres the code with an example, the threshold value for the opcode is a number between 0 and 1,


<CsoundSynthesizer>
<CsOptions>
</CsOptions>
<CsInstruments>

sr = 44100
ksmps = 1024
nchnls = 2
0dbfs  = 1



opcode QuadraticInterpolation, k, ik

i_YinBuffer, k_Period xin

k_x0 = k_Period < 1 ? k_Period : k_Period - 1

k_x2 =  k_Period + 1 < ftlen(i_YinBuffer) ? k_Period + 1 : k_Period 
if k_x0 == k_Period then
k_bufferAtPeriod tab k_Period, i_YinBuffer
k_bufferAtx2 tab k_x2, i_YinBuffer
k_Pitch = k_bufferAtPeriod <= k_bufferAtx2 ? k_Period : k_x2
elseif k_x2 == k_Period then
k_bufferAtPeriod tab k_Period, i_YinBuffer
k_bufferAtx0 tab k_x0, i_YinBuffer
k_Pitch = k_bufferAtPeriod <= k_bufferAtx0 ? k_Period : k_x0
else
k_s0 tab k_x0, i_YinBuffer
k_s1 tab k_Period, i_YinBuffer
k_s2 tab k_x2, i_YinBuffer
k_Pitch = k_Period + 0.5 * (k_s2 - k_s0) / (k_s2 - 2.0 * k_s1 + k_s0)
endif


xout k_Pitch


endop



opcode Yin, k, aii

a_In, i_YinBuffer, i_Threshold xin
k_tmp2 = 0
k_Tau = 1
k_PitchFound = 0

until k_Tau >= ftlen(i_YinBuffer) || k_PitchFound == 1 do 
k_Index = 0
until k_Index >= ftlen(i_YinBuffer) do
k_1 vaget k_Index, a_In
k_2 vaget k_Index + k_Tau, a_In
k_tmp = k_1 - k_2
k_3 tab k_Tau, i_YinBuffer
tabw k_3 + (k_tmp * k_tmp), k_Tau, i_YinBuffer 
k_Index = k_Index + 1
od
k_1 tab k_Tau, i_YinBuffer

k_tmp2 = k_tmp2 + k_1
k_2 = k_1 * (k_Tau / k_tmp2)
tabw k_2, k_Tau, i_YinBuffer
k_Period = k_Tau - 3

if k_Tau > 4 then
k_BufferAtPeriod tab k_Period, i_YinBuffer
k_BufferAtPeriodPlusOne tab k_Period + 1, i_YinBuffer
if k_BufferAtPeriod < i_Threshold && k_BufferAtPeriod < k_BufferAtPeriodPlusOne then
k_Pitch QuadraticInterpolation i_YinBuffer, k_Period
k_Pitch = sr / k_Pitch
k_PitchFound = 1

else
k_PitchFound = 0
endif
endif
k_Tau = k_Tau + 1 
od
if k_PitchFound == 0 then
k_Index = 0
k_Period = 0
k_tmp tab 0, i_YinBuffer
until k_Index >= ftlen(i_YinBuffer) do
k_0 tab k_Index, i_YinBuffer
k_Period = k_tmp < k_0 ? k_Period : k_Index
k_tmp = k_tmp < k_0 ? k_tmp : k_0
k_Index = k_Index + 1
od
k_Pitch QuadraticInterpolation i_YinBuffer, k_Period
endif

xout k_Pitch

endop


instr Init, 1
i_WindowSize = ksmps 
i_Threshold = .04
gi_AudioBuffer ftgen 0, 0, i_WindowSize, 16, 0, 0
gi_YinBuffer ftgen 0, 0, i_WindowSize / 2, 16, 0, 0
Sfile = "Sound.wav"
i_Length filelen Sfile

gi_AudioIn ftgen 0, 0, -(sr * i_Length), 1, Sfile, 0, 0, 0
a_Line line 0, i_Length, ftlen(gi_AudioIn)
a_Out table a_Line, gi_AudioIn
k_Pitch Yin a_Out, gi_YinBuffer, i_Threshold

k_Pitch tonek k_Pitch, 10

a_Tone vco2 .2, k_Pitch , 12
outs a_Out, a_Tone
endin



</CsInstruments>
<CsScore>

i "Init" 0 10

</CsScore>
</CsoundSynthesizer>


Cheers,

Ed