aboutsummaryrefslogtreecommitdiff
path: root/sc4pd/source/PitchShift.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sc4pd/source/PitchShift.cpp')
-rw-r--r--sc4pd/source/PitchShift.cpp629
1 files changed, 629 insertions, 0 deletions
diff --git a/sc4pd/source/PitchShift.cpp b/sc4pd/source/PitchShift.cpp
new file mode 100644
index 0000000..8a3f265
--- /dev/null
+++ b/sc4pd/source/PitchShift.cpp
@@ -0,0 +1,629 @@
+/* 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: Bernhard Lang: Differenz / Wiederholung 2
+
+*/
+
+#include "sc4pd.hpp"
+
+/* ------------------------ PitchShift~ -----------------------------*/
+
+class PitchShift_ar
+ :public sc4pd_dsp
+{
+ FLEXT_HEADER(PitchShift_ar,sc4pd_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_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_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,"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 *dlybuf;
+ float pchratio;
+ float fdelaylen, slope;
+ long framesize, last;
+
+ //out = ZOUT(0);
+ //in = ZIN(0);
+ pchratio = m_pitchratio;
+
+ delaybufsize = (long)ceil(m_windowsize * 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)(m_windowsize * 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,
+ 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;
+ pchdisp = m_pitchdispersion;
+ timedisp = m_timedispersion;
+ timedisp = sc_clip(timedisp, 0.f, m_windowsize) * 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,
+ pchdisp, timedisp;
+ long remain, nsmps, idelaylen, irdphase, irdphaseb, iwrphase, mask, idsamp;
+ long counter, stage, framesize;
+
+ RGET;
+
+ nout = *out;
+ nin = *in;
+
+ pchratio = m_pitchratio;
+ pchdisp = m_pitchdispersion;
+ timedisp = m_timedispersion;
+
+ timedisp = sc_clip(timedisp, 0.f, m_windowsize) * 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;
+}
+
+
+/* a control rate PitchShift doesn't make sense */