after figuring a mistake in ftgen normalisation (should be -1) I'm getting sound and i just need to get the phasor mechanism working. changing the value of the linsey beginning point do not work as expected, if i ask to begin at the value of 1 I'm getting a short squeeki version of my sample. this is obviously not suppose to happen when only one sample offset is set. any ideas?
On Monday, April 22, 2013 at 6:03 AM, zohar argaman wrote:
> 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.