Hi guys, first post for me. let me say, i love CSound! Hans Mikelson posted on CSound magazine this interesting Time Domain TimeScale algorithm based on SOLA http://www.csounds.com/ezine/spring2000/processing/ I love his explanation and the sound is good, but i needed a dynamic pitch shifting, that is, one that can change pitch in k-rate, i messed around with his code but i made more mess than i can cleanup, so i need your help. this is Mikelson's version. very clear and neat ;--------------------------------------------------------------- ; Pitch and Time Scaling ;--------------------------------------------------------------- instr 11 idur = p3 ; Duration iamp = p4 ; Amplitude ;1 ipshft = p5 ; Pitch scaling factor itstr = p6 ; Time scaling factor iaph = p7*sr ; Amplitude of the phasor in seconds converted to samples ;.1 itab = p8 ; Sample ismth = p9 ; Smoothing factor ;2 ipval = (ipshft-1) ; Setup for pitch shifting ifph = sr/iaph*((itstr-1)/itstr + ipval) ; Frequency for phasor prints "P-Coef:%f ipval:%f, ifph:%f%R%R",ipshft,ipval,ifph aphas1 phasor ifph ; Phasor 1 aphas2 phasor ifph, .5 ; Phasor 2 shifted by 180 degrees apos linseg 0, idur, idur/itstr*sr ; Scan this many samples of the table. kph1 downsamp aphas1 kph2 downsamp aphas2 printks "kph1:%f kph2:%f%R",0.1,kph1,kph2 kdclk1 oscil 1, ifph, 1 ; Declick envelope matches phasor frequency kdclk2 oscil 1, ifph, 1, .5 ; Another one shifted by 180 degrees kdclk1 = (tanh(kdclk1*ismth)+1)*.5 ; Flatten the sine waves and offset kdclk2 = (tanh(kdclk2*ismth)+1)*.5 ; Same for other stream ashft1 table3 iaph*aphas1+apos, itab ; Scan the table with cubic interpolation ashft2 table3 iaph*aphas2+apos, itab ; second stream aout = ashft1*kdclk1 + ashft2*kdclk2 ; Combine the two streams with declicking outs aout*iamp, aout*iamp ; Output the result endin now, how would you make a auto-tuner out of this? youll have to have a pitch detection algorithm (PDA) and the complicated thing is i want to scale a sample that runs in a loop, so... this is my code with event flow at the bottom: , sr =44100 ksmps = 64 nchnls = 2 ;vocal sample #define Filename #vocal_sample.aif# instr Init ;Calculate important global vars and load FT giproperLen filelen "$Filename" giftsnd ftgen 0, 0, 2^(inbase), 1, "$Filename", 0, 0, 1 giftlen =ftlen(giftsnd) endin ;--------------------------------------------------------------- ; Pitch and Time Scaling - modified to play loop and support initial samp offset ;TIME STRETCH - DISABLED ;--------------------------------------------------------------- instr SOLA idur = p3 ; Duration iamp = p4 ; Amplitude ;1 inote = p5 ; note- convert to Pitch scaling factor itstr = p6 ; Time scaling factor iaph = p7*sr ; Amplitude of the phasor in seconds converted to samples ;.1 itab = p8 ; Sample ismth = p9 ; Smoothing factor ;2 ilenSamp = p11 ;length of loop in samples knote =k(p5) ;scale factor kpshft = knote/gkAMDFcps reinit PhsDeter ;extract phase from phasor and store it while a note is played PhsDeter: iSampOffset = int(i(gkeepPhs)*sr) rireturn printks "knote:%d kpshft:%f iSampOffset%f gkPhs:%f%R",0.1,knote,kpshft,iSampOffset,gkeepPhs kpval = (kpshft-1) ; Setup for pitch shifting gkfph = sr/iaph*(kpval) ; Frequency for phasor aphas1 phasor gkfph ; Phasor 1 aphas2 phasor gkfph, .5 ; Phasor 2 shifted by 180 degrees apos linseg 0, idur, idur*sr ; Scan this many samples of the table. gashft1 table3 (iaph*aphas1+apos+iSampOffset)%ilenSamp, itab ; Scan the table with cubic interpolation gashft2 table3 (iaph*aphas2+apos+iSampOffset)%ilenSamp, itab ; second stream krms rms gashft1 outvalue "rms", krms endin ;Notes - No Live Input, Orchestrated :( instr 1 ivel = p5 a1 subinstr "SOLA" ,1 ,p4,1,0.1,giftsnd,2,1,giproperLen*sr endin ;delay vocal until sample will hit the beat instr Setup event "i", "Process",0 , 65 turnoff endin instr Process ;Read loop a1 lposcil 0dbfs, 1,0,giproperLen*sr, giftsnd ;Start Phasor to keep track with pitch, reset every sample Length in seconds gkeepPhs phasor 1/giproperLen ;AMDF PDA - send global to instr SOLA gkAMDFcps, krms pitchamdf a1, 50, 700 ,130 ;fade mini-samples of SOLA kdclk1 oscil 1, gkfph, 1 ; Declick envelope matches phasor frequency kdclk2 oscil 1, gkfph, 1, .5 ; Another one shifted by 180 degrees iamp=1 ismth=2 kdclk1 = (tanh(kdclk1*ismth)+1)*.5 ; Flatten the sine waves and offset kdclk2 = (tanh(kdclk2*ismth)+1)*.5 ; Same for other stream aout = gashft1*kdclk1 + gashft2*kdclk2 ; Combine the two streams with declicking outs aout*iamp, aout*iamp ; Output the result endin f 1 0 16384 10 1 s i "Init" 0 1 s f0 70 i "Setup" 0 0.003 i1 0.503628 20 146.828242 120 it became kind of global variable - p-rate nightmare ;/ the Init method initialize any global variable so the compiler wont be angry. setup initializes the Process instrument that runs as the Always On instr while performance. Pseudo Midi given by the note in i1. i1 trigger the SOLA instr. the SOLA instr takes global params from Process like the pitch of the current k-frame, and creates global signal gashft1 that is picked up by Process and mixes with the fade mechanism and heads out. the original sound is a loop, since its beeing read by a table3 opcode, i used a phasor to keep track of where is the pointer of the sample should be on the table. the thing is, that phasor must stop running when activating a note on SOLA, so the reinit section was added with hope to solve this. now, what is the problem? simple, no sound! i tried measuring rms of the ga coming out of SOLA, it measured 0.2 RMS. that's wierd. im i reading the table wrong? what can cause this behavior? how is best to debug this? what tools to use? is this idea possible anyway? thanks to all readers and answerers.