Update of /cvsroot/pure-data/externals/sc4pd/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16321/source
Modified Files: main.cpp Added Files: PitchShift.cpp Log Message: checkin of PitchShift~
Index: main.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/sc4pd/source/main.cpp,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** main.cpp 4 Aug 2004 18:23:15 -0000 1.19 --- main.cpp 6 Aug 2004 08:34:42 -0000 1.20 *************** *** 63,67 **** " DelayL~, DelayC~, CombN~, CombL~, CombC~, AllpassN~, " "AllpassL~,\n" ! " AllpassC~" "\n" ); --- 63,67 ---- " DelayL~, DelayC~, CombN~, CombL~, CombC~, AllpassN~, " "AllpassL~,\n" ! " AllpassC~, PitchShift~" "\n" );
--- NEW FILE: PitchShift.cpp --- /* 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? */