From 305c08085dc742d591640f0078638b44878103be Mon Sep 17 00:00:00 2001
From: Tim Blechmann <timblech@users.sourceforge.net>
Date: Fri, 6 Aug 2004 08:34:42 +0000
Subject: checkin of PitchShift~

svn path=/trunk/externals/tb/; revision=1911
---
 sc4pd/make-files.txt        |   2 +-
 sc4pd/source/PitchShift.cpp | 638 ++++++++++++++++++++++++++++++++++++++++++++
 sc4pd/source/main.cpp       |   2 +-
 3 files changed, 640 insertions(+), 2 deletions(-)
 create mode 100644 sc4pd/source/PitchShift.cpp

(limited to 'sc4pd')

diff --git a/sc4pd/make-files.txt b/sc4pd/make-files.txt
index 3f9038d..3dc0de4 100755
--- a/sc4pd/make-files.txt
+++ b/sc4pd/make-files.txt
@@ -12,4 +12,4 @@ SRCS= \
 	LFPulse.cpp Impulse.cpp Integrator.cpp Decay.cpp Decay2.cpp Lag.cpp \
 	Lag2.cpp Lag3.cpp LinExp.cpp DelayUnit.cpp DelayN.cpp DelayL.cpp \
 	DelayC.cpp CombN.cpp CombL.cpp CombC.cpp AllpassN.cpp AllpassL.cpp \
-	AllpassC.cpp
+	AllpassC.cpp PitchShift.cpp
diff --git a/sc4pd/source/PitchShift.cpp b/sc4pd/source/PitchShift.cpp
new file mode 100644
index 0000000..d182681
--- /dev/null
+++ b/sc4pd/source/PitchShift.cpp
@@ -0,0 +1,638 @@
+/* sc4pd 
+   PitchShift~ 
+
+   Copyright (c) 2004 Tim Blechmann.                                       
+
+   This code is derived from:
+	SuperCollider real time audio synthesis system
+    Copyright (c) 2002 James McCartney. All rights reserved.
+	http://www.audiosynth.com
+
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,             
+   but WITHOUT ANY WARRANTY; without even the implied warranty of         
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+   Based on:
+     PureData by Miller Puckette and others.
+         http://www.crca.ucsd.edu/~msp/software.html
+     FLEXT by Thomas Grill
+         http://www.parasitaere-kapazitaeten.net/ext
+     SuperCollider by James McCartney
+         http://www.audiosynth.com
+     
+   Coded while listening to: 
+   
+*/
+
+#include "sc4pd.hpp"
+
+/* ------------------------ PitchShift~ -----------------------------*/
+
+class PitchShift_ar
+    :public flext_dsp
+{
+    FLEXT_HEADER(PitchShift_ar,flext_dsp);
+
+public:
+    PitchShift_ar(int argc,t_atom * argv);
+
+protected:
+    virtual void m_signal(int n, t_sample *const *in, t_sample *const *out)
+    {
+	m_signal_fun(n,in,out);
+    }
+    
+    virtual void m_dsp(int n, t_sample *const *in, t_sample *const *out);
+
+    void m_set_windowsize(float f)
+    {
+	m_windowsize = f;
+    }
+
+    void m_set_pitchratio (float f)
+    {
+	m_pitchratio = f;
+    }
+
+    void m_set_pitchdispersion (float f)
+    {
+	m_pitchdispersion = f;
+    }
+    
+    void m_set_timedispersion (float f)
+    {
+	m_timedispersion = f;
+    }
+
+private:
+    float m_windowsize, m_pitchratio,m_pitchdispersion,m_timedispersion;
+    RGen rgen;
+
+
+    float *m_dlybuf;
+    float m_dsamp1, m_dsamp1_slope, m_ramp1, m_ramp1_slope;
+    float m_dsamp2, m_dsamp2_slope, m_ramp2, m_ramp2_slope;
+    float m_dsamp3, m_dsamp3_slope, m_ramp3, m_ramp3_slope;
+    float m_dsamp4, m_dsamp4_slope, m_ramp4, m_ramp4_slope;
+    float m_fdelaylen, m_slope;
+    long m_iwrphase, m_idelaylen, m_mask;
+    long m_counter, m_stage, m_numoutput, m_framesize;
+
+    DEFSIGCALL(m_signal_fun);
+    DEFSIGFUN(m_signal_);
+    DEFSIGFUN(m_signal_z);
+    
+    FLEXT_CALLBACK_F(m_set_windowsize);
+    FLEXT_CALLBACK_F(m_set_pitchratio);
+    FLEXT_CALLBACK_F(m_set_pitchdispersion);
+    FLEXT_CALLBACK_F(m_set_timedispersion);
+};
+
+FLEXT_LIB_DSP_V("PitchShift~",PitchShift_ar);
+
+PitchShift_ar::PitchShift_ar(int argc,t_atom * argv)
+{
+    FLEXT_ADDMETHOD_(0,"windowSize",m_set_windowsize);
+    FLEXT_ADDMETHOD_(0,"pitchRatio",m_set_pitchratio);
+    FLEXT_ADDMETHOD_(0,"pitchDispersion",m_set_pitchdispersion);
+    FLEXT_ADDMETHOD_(0,"timeDispersion",m_set_timedispersion);
+
+    AtomList Args(argc,argv);
+
+    if (Args.Count() != 4)
+    {
+	post("4 arguments needed");
+	return;
+    }
+    m_windowsize = sc_getfloatarg(Args,0);
+    m_pitchratio = sc_getfloatarg(Args,1);
+    m_pitchdispersion = sc_getfloatarg(Args,2);
+    m_timedispersion = sc_getfloatarg(Args,3);
+
+    rgen.init(timeseed());
+    
+    AddOutSignal();
+	
+    SETSIGFUN(m_signal_fun,SIGFUN(m_signal_z));
+}
+
+void PitchShift_ar::m_dsp(int n, t_sample *const *in, t_sample *const *out)
+{
+    /* initialization from PitchShift_Ctor(PitchShift *unit) */
+
+    long delaybufsize;
+    float /* *out, *in,*/ *dlybuf;
+    float winsize, pchratio;
+    float fdelaylen, slope;
+    long framesize, last;
+    
+    //out = ZOUT(0);
+    //in = ZIN(0);
+    pchratio = m_pitchratio;
+    winsize = m_windowsize;
+	
+    delaybufsize = (long)ceil(winsize * SAMPLERATE * 3.f + 3.f);
+    fdelaylen = delaybufsize - 3;
+
+    delaybufsize = delaybufsize + BUFLENGTH;
+    delaybufsize = NEXTPOWEROFTWO(delaybufsize);  // round up to next power of two
+    dlybuf = new float[delaybufsize];
+         //(float*)RTAlloc(unit->mWorld, delaybufsize * sizeof(float));
+	
+    *dlybuf = 0;
+
+    m_dlybuf = dlybuf;
+    m_idelaylen = delaybufsize;
+    m_fdelaylen = fdelaylen;
+    m_iwrphase = 0;
+    m_numoutput = 0;
+    m_mask = last = (delaybufsize - 1);
+	
+    m_framesize = framesize = ((long)(winsize * SAMPLERATE) + 2) & ~3;
+    m_slope = slope = 2.f / framesize;
+    m_stage = 3;
+    m_counter = framesize >> 2;
+    m_ramp1 = 0.5;
+    m_ramp2 = 1.0;
+    m_ramp3 = 0.5;
+    m_ramp4 = 0.0;
+
+    m_ramp1_slope = -slope;
+    m_ramp2_slope = -slope;
+    m_ramp3_slope =  slope;
+    m_ramp4_slope =  slope;
+    
+    dlybuf[last  ] = 0.f; // put a few zeroes where we start the read heads
+    dlybuf[last-1] = 0.f;
+    dlybuf[last-2] = 0.f;
+    
+    m_numoutput = 0;
+
+    // start all read heads 2 samples behind the write head
+    m_dsamp1 = m_dsamp2 = m_dsamp3 = m_dsamp4 = 2.f;
+    // pch ratio is initially zero for the read heads
+    m_dsamp1_slope = m_dsamp2_slope = m_dsamp3_slope = m_dsamp4_slope = 1.f;
+}
+
+
+void PitchShift_ar::m_signal_z(int n, t_sample *const *in, 
+		      t_sample *const *out)
+{
+    
+    float *nout, *nin, *dlybuf;
+    float disppchratio, pchratio, pchratio1, value;
+    float dsamp1, dsamp1_slope, ramp1, ramp1_slope;
+    float dsamp2, dsamp2_slope, ramp2, ramp2_slope;
+    float dsamp3, dsamp3_slope, ramp3, ramp3_slope;
+    float dsamp4, dsamp4_slope, ramp4, ramp4_slope;
+    float fdelaylen, d1, d2, frac, slope, samp_slope, startpos, 
+	winsize, pchdisp, timedisp;
+    long remain, nsmps, idelaylen, irdphase, irdphaseb, iwrphase;
+    long mask, idsamp;
+    long counter, stage, framesize, numoutput;
+	
+    RGET;
+		
+    nout = *out;
+    nin = *in;
+    
+    pchratio = m_pitchratio;
+    winsize = m_windowsize;
+    pchdisp = m_pitchdispersion;
+    timedisp = m_timedispersion;
+    timedisp = sc_clip(timedisp, 0.f, winsize) * SAMPLERATE;
+	
+    dlybuf = m_dlybuf;
+    fdelaylen = m_fdelaylen;
+    idelaylen = m_idelaylen;
+    iwrphase = m_iwrphase;
+    numoutput = m_numoutput;
+
+    counter = m_counter;
+    stage = m_stage;
+    mask = m_mask;
+    framesize = m_framesize;
+    
+    dsamp1 = m_dsamp1;
+    dsamp2 = m_dsamp2;
+    dsamp3 = m_dsamp3;
+    dsamp4 = m_dsamp4;
+	
+    dsamp1_slope = m_dsamp1_slope;
+    dsamp2_slope = m_dsamp2_slope;
+    dsamp3_slope = m_dsamp3_slope;
+    dsamp4_slope = m_dsamp4_slope;
+	
+    ramp1 = m_ramp1;
+    ramp2 = m_ramp2;
+    ramp3 = m_ramp3;
+    ramp4 = m_ramp4;
+    
+    ramp1_slope = m_ramp1_slope;
+    ramp2_slope = m_ramp2_slope;
+    ramp3_slope = m_ramp3_slope;
+    ramp4_slope = m_ramp4_slope;
+    
+    slope = m_slope;
+	
+    remain = n;
+    while (remain) 
+    {
+	if (counter <= 0) 
+	{
+	    counter = framesize >> 2;
+	    m_stage = stage = (stage + 1) & 3;
+	    disppchratio = pchratio;
+	    if (pchdisp != 0.f) 
+	    {
+		disppchratio += (pchdisp * frand2(s1,s2,s3));
+	    }
+	    disppchratio = sc_clip(disppchratio, 0.f, 4.f);
+	    pchratio1 = disppchratio - 1.f;
+	    samp_slope = -pchratio1;
+	    startpos = pchratio1 < 0.f ? 2.f : framesize * pchratio1 + 2.f;
+	    startpos += (timedisp * frand(s1,s2,s3));
+	    switch(stage) 
+	    {
+	    case 0 :
+		m_dsamp1_slope = dsamp1_slope = samp_slope;
+		dsamp1 = startpos;
+		ramp1 = 0.0;
+		m_ramp1_slope = ramp1_slope =  slope;
+		m_ramp3_slope = ramp3_slope = -slope;
+		break;
+	    case 1 :
+		m_dsamp2_slope = dsamp2_slope = samp_slope;
+		dsamp2 = startpos;
+		ramp2 = 0.0;
+		m_ramp2_slope = ramp2_slope =  slope;
+		m_ramp4_slope = ramp4_slope = -slope;
+		break;
+	    case 2 :
+		m_dsamp3_slope = dsamp3_slope = samp_slope;
+		dsamp3 = startpos;
+		ramp3 = 0.0;
+		m_ramp3_slope = ramp3_slope =  slope;
+		m_ramp1_slope = ramp1_slope = -slope;
+		break;
+	    case 3 :
+		m_dsamp4_slope = dsamp4_slope = samp_slope;
+		dsamp4 = startpos;
+		ramp4 = 0.0;
+		m_ramp2_slope = ramp2_slope = -slope;
+		m_ramp4_slope = ramp4_slope =  slope;
+		break;
+	    }				
+	}
+	nsmps = sc_min(remain, counter);
+	remain -= nsmps;
+	counter -= nsmps;
+	
+	while (nsmps--) {
+	    numoutput++;
+	    iwrphase = (iwrphase + 1) & mask;
+	    
+	    dsamp1 += dsamp1_slope;
+	    idsamp = (long)dsamp1;
+	    frac = dsamp1 - idsamp;
+	    irdphase = (iwrphase - idsamp) & mask;
+	    irdphaseb = (irdphase - 1) & mask;
+	    if (numoutput < idelaylen) 
+	    {
+		if (irdphase > iwrphase) 
+		{
+		    value = 0.f;
+		} 
+		else if (irdphaseb > iwrphase) 
+		{
+		    d1 = dlybuf[irdphase];
+		    value = (d1 - frac * d1) * ramp1;
+		} 
+		else 
+		{
+		    d1 = dlybuf[irdphase];
+		    d2 = dlybuf[irdphaseb];
+		    value = (d1 + frac * (d2 - d1)) * ramp1;
+		}
+	    }
+	    else
+	    {
+		d1 = dlybuf[irdphase];
+		d2 = dlybuf[irdphaseb];
+		value = (d1 + frac * (d2 - d1)) * ramp1;
+	    }
+	    ramp1 += ramp1_slope;
+	    
+	    dsamp2 += dsamp2_slope;
+	    idsamp = (long)dsamp2;
+	    frac = dsamp2 - idsamp;
+	    irdphase = (iwrphase - idsamp) & mask;
+	    irdphaseb = (irdphase - 1) & mask;
+	    if (numoutput < idelaylen) 
+	    {
+		if (irdphase > iwrphase) 
+		{
+		    //value += 0.f;
+		} 
+		else if (irdphaseb > iwrphase) 
+		{
+		    d1 = dlybuf[irdphase];
+		    value += (d1 - frac * d1) * ramp2;
+		}
+		else 
+		{
+		    d1 = dlybuf[irdphase];
+		    d2 = dlybuf[irdphaseb];
+		    value += (d1 + frac * (d2 - d1)) * ramp2;
+		
+		}
+	    } 
+	    else 
+	    {
+		d1 = dlybuf[irdphase];
+		d2 = dlybuf[irdphaseb];
+		value += (d1 + frac * (d2 - d1)) * ramp2;
+	    }
+	    ramp2 += ramp2_slope;
+	    
+	    dsamp3 += dsamp3_slope;
+	    idsamp = (long)dsamp3;
+	    frac = dsamp3 - idsamp;
+	    irdphase = (iwrphase - idsamp) & mask;
+	    irdphaseb = (irdphase - 1) & mask;
+	    if (numoutput < idelaylen) 
+	    {
+		if (irdphase > iwrphase) 
+		{
+		    //value += 0.f;
+		} 
+		else if (irdphaseb > iwrphase) 
+		{
+		    d1 = dlybuf[irdphase];
+		    value += (d1 - frac * d1) * ramp3;
+		} 
+		else 
+		{
+		    d1 = dlybuf[irdphase];
+		    d2 = dlybuf[irdphaseb];
+		    value += (d1 + frac * (d2 - d1)) * ramp3;
+		}
+	    }
+	    else
+	    {
+		d1 = dlybuf[irdphase];
+		d2 = dlybuf[irdphaseb];
+		value += (d1 + frac * (d2 - d1)) * ramp3;
+	    }
+	    ramp3 += ramp3_slope;
+			
+	    dsamp4 += dsamp4_slope;
+	    idsamp = (long)dsamp4;
+	    frac = dsamp4 - idsamp;
+	    irdphase = (iwrphase - idsamp) & mask;
+	    irdphaseb = (irdphase - 1) & mask;
+	    
+	    if (numoutput < idelaylen) 
+	    {
+		if (irdphase > iwrphase) 
+		{
+		    //value += 0.f;
+		} else if (irdphaseb > iwrphase) {
+		    d1 = dlybuf[irdphase];
+		    value += (d1 - frac * d1) * ramp4;
+		}
+		else 
+		{
+		    d1 = dlybuf[irdphase];
+		    d2 = dlybuf[irdphaseb];
+		    value += (d1 + frac * (d2 - d1)) * ramp4;
+		}
+	    }
+	    else 
+	    {
+		d1 = dlybuf[irdphase];
+		d2 = dlybuf[irdphaseb];
+		value += (d1 + frac * (d2 - d1)) * ramp4;
+	    }
+	    ramp4 += ramp4_slope;
+			
+	    dlybuf[iwrphase] = ZXP(nin);
+	    ZXP(nout) = value *= 0.5;
+	}
+    }
+    
+    m_counter = counter;
+    m_stage = stage;
+    m_mask = mask;
+    
+    m_dsamp1 = dsamp1;
+    m_dsamp2 = dsamp2;
+    m_dsamp3 = dsamp3;
+    m_dsamp4 = dsamp4;
+    
+    m_ramp1 = ramp1;
+    m_ramp2 = ramp2;
+    m_ramp3 = ramp3;
+    m_ramp4 = ramp4;
+	
+    m_numoutput = numoutput;
+    m_iwrphase = iwrphase;
+	
+    if (numoutput >= idelaylen) 
+    {
+	SETSIGFUN(m_signal_fun,SIGFUN(m_signal_z));
+    }
+    RPUT;
+}
+    
+void PitchShift_ar::m_signal_(int n, t_sample *const *in, 
+		      t_sample *const *out)
+{
+    float *nout, *nin, *dlybuf;
+    float disppchratio, pchratio, pchratio1, value;
+    float dsamp1, dsamp1_slope, ramp1, ramp1_slope;
+    float dsamp2, dsamp2_slope, ramp2, ramp2_slope;
+    float dsamp3, dsamp3_slope, ramp3, ramp3_slope;
+    float dsamp4, dsamp4_slope, ramp4, ramp4_slope;
+    float fdelaylen, d1, d2, frac, slope, samp_slope, startpos, 
+	winsize, pchdisp, timedisp;
+    long remain, nsmps, idelaylen, irdphase, irdphaseb, iwrphase, mask, idsamp;
+    long counter, stage, framesize;
+    
+    RGET;
+    
+    nout = *out;
+    nin = *in;
+    
+    pchratio = m_pitchratio;
+    winsize = m_windowsize;
+    pchdisp = m_pitchdispersion;
+    timedisp = m_timedispersion;
+    
+    timedisp = sc_clip(timedisp, 0.f, winsize) * SAMPLERATE;
+    
+    dlybuf = m_dlybuf;
+    fdelaylen = m_fdelaylen;
+    idelaylen = m_idelaylen;
+    iwrphase = m_iwrphase;
+    
+    counter = m_counter;
+    stage = m_stage;
+    mask = m_mask;
+    framesize = m_framesize;
+    
+    dsamp1 = m_dsamp1;
+    dsamp2 = m_dsamp2;
+    dsamp3 = m_dsamp3;
+    dsamp4 = m_dsamp4;
+    
+    dsamp1_slope = m_dsamp1_slope;
+    dsamp2_slope = m_dsamp2_slope;
+    dsamp3_slope = m_dsamp3_slope;
+    dsamp4_slope = m_dsamp4_slope;
+    
+    ramp1 = m_ramp1;
+    ramp2 = m_ramp2;
+    ramp3 = m_ramp3;
+    ramp4 = m_ramp4;
+    
+    ramp1_slope = m_ramp1_slope;
+    ramp2_slope = m_ramp2_slope;
+    ramp3_slope = m_ramp3_slope;
+    ramp4_slope = m_ramp4_slope;
+    
+    slope = m_slope;
+    
+    remain = n;
+    while (remain) 
+    {
+	if (counter <= 0) 
+	{
+	    counter = framesize >> 2;
+	    m_stage = stage = (stage + 1) & 3;
+	    disppchratio = pchratio;
+	    if (pchdisp != 0.f) 
+	    {
+		disppchratio += (pchdisp * frand2(s1,s2,s3));
+	    }
+	    disppchratio = sc_clip(disppchratio, 0.f, 4.f);
+	    pchratio1 = disppchratio - 1.f;
+	    samp_slope = -pchratio1;
+	    startpos = pchratio1 < 0.f ? 2.f : framesize * pchratio1 + 2.f;
+	    startpos += (timedisp * frand(s1,s2,s3));
+	    switch(stage) 
+	    {
+	    case 0 :
+		m_dsamp1_slope = dsamp1_slope = samp_slope;
+		dsamp1 = startpos;
+		ramp1 = 0.0;
+		m_ramp1_slope = ramp1_slope =  slope;
+		m_ramp3_slope = ramp3_slope = -slope;
+		break;
+	    case 1 :
+		m_dsamp2_slope = dsamp2_slope = samp_slope;
+		dsamp2 = startpos;
+		ramp2 = 0.0;
+		m_ramp2_slope = ramp2_slope =  slope;
+		m_ramp4_slope = ramp4_slope = -slope;
+		break;
+	    case 2 :
+		m_dsamp3_slope = dsamp3_slope = samp_slope;
+		dsamp3 = startpos;
+		ramp3 = 0.0;
+		m_ramp3_slope = ramp3_slope =  slope;
+		m_ramp1_slope = ramp1_slope = -slope;
+		break;
+	    case 3 :
+		m_dsamp4_slope = dsamp4_slope = samp_slope;
+		dsamp4 = startpos;
+		ramp4 = 0.0;
+		m_ramp2_slope = ramp2_slope = -slope;
+		m_ramp4_slope = ramp4_slope =  slope;
+		break;
+	    }
+	}
+	
+	nsmps = sc_min(remain, counter);
+	remain -= nsmps;
+	counter -= nsmps;
+	
+	for (int i = 0; i!= nsmps;++i)
+	{
+	    iwrphase = (iwrphase + 1) & mask;
+	    
+	    dsamp1 += dsamp1_slope;
+	    idsamp = (long)dsamp1;
+	    frac = dsamp1 - idsamp;
+	    irdphase = (iwrphase - idsamp) & mask;
+	    irdphaseb = (irdphase - 1) & mask;
+	    d1 = dlybuf[irdphase];
+	    d2 = dlybuf[irdphaseb];
+	    value = (d1 + frac * (d2 - d1)) * ramp1;
+	    ramp1 += ramp1_slope;
+	    
+	    dsamp2 += dsamp2_slope;
+	    idsamp = (long)dsamp2;
+	    frac = dsamp2 - idsamp;
+	    irdphase = (iwrphase - idsamp) & mask;
+	    irdphaseb = (irdphase - 1) & mask;
+	    d1 = dlybuf[irdphase];
+	    d2 = dlybuf[irdphaseb];
+	    value += (d1 + frac * (d2 - d1)) * ramp2;
+	    ramp2 += ramp2_slope;
+	    
+	    dsamp3 += dsamp3_slope;
+	    idsamp = (long)dsamp3;
+	    frac = dsamp3 - idsamp;
+	    irdphase = (iwrphase - idsamp) & mask;
+	    irdphaseb = (irdphase - 1) & mask;
+	    d1 = dlybuf[irdphase];
+	    d2 = dlybuf[irdphaseb];
+	    value += (d1 + frac * (d2 - d1)) * ramp3;
+	    ramp3 += ramp3_slope;
+	
+	    dsamp4 += dsamp4_slope;
+	    idsamp = (long)dsamp4;
+	    frac = dsamp4 - idsamp;
+	    irdphase = (iwrphase - idsamp) & mask;
+	    irdphaseb = (irdphase - 1) & mask;
+	    d1 = dlybuf[irdphase];
+	    d2 = dlybuf[irdphaseb];
+	    value += (d1 + frac * (d2 - d1)) * ramp4;
+	    ramp4 += ramp4_slope;
+	    
+	    dlybuf[iwrphase] = ZXP(nin);
+	    ZXP(nout) = value *= 0.5;
+	}
+    }
+    
+    m_counter = counter;
+    
+    m_dsamp1 = dsamp1;
+    m_dsamp2 = dsamp2;
+    m_dsamp3 = dsamp3;
+    m_dsamp4 = dsamp4;
+    
+    m_ramp1 = ramp1;
+    m_ramp2 = ramp2;
+    m_ramp3 = ramp3;
+    m_ramp4 = ramp4;
+    
+    m_iwrphase = iwrphase;
+    
+    RPUT;
+}
+    
+
+/* todo: does a control rate PitchShift make sense? */
diff --git a/sc4pd/source/main.cpp b/sc4pd/source/main.cpp
index 77a620c..332afa8 100644
--- a/sc4pd/source/main.cpp
+++ b/sc4pd/source/main.cpp
@@ -62,7 +62,7 @@ void sc4pd_library_setup()
 	 "DelayN~,\n"
 	 "          DelayL~, DelayC~, CombN~, CombL~, CombC~, AllpassN~, "
 	 "AllpassL~,\n"
-	 "          AllpassC~"
+	 "          AllpassC~, PitchShift~"
 	 "\n"
 	 );
 
-- 
cgit v1.2.1