diff options
author | IOhannes m zmölnig <zmoelnig@iem.at> | 2015-10-14 15:14:38 +0200 |
---|---|---|
committer | IOhannes m zmölnig <zmoelnig@iem.at> | 2015-10-14 15:14:38 +0200 |
commit | 28b7e464fd119b8c848753a1f41070422c463c41 (patch) | |
tree | 07449abdf85d8f1fd4068839b974242b429720ca /sc4pd/source/Convolution.cpp | |
parent | 90c6018a9401e38859f733b3521c919e042322b7 (diff) | |
parent | 6932ee2d22511226378218992b0005cb01eb235e (diff) |
Merge branchesHEADsvn2git-headmaster
- abstractions/tb
- externals/tb
Diffstat (limited to 'sc4pd/source/Convolution.cpp')
-rw-r--r-- | sc4pd/source/Convolution.cpp | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/sc4pd/source/Convolution.cpp b/sc4pd/source/Convolution.cpp new file mode 100644 index 0000000..0026b01 --- /dev/null +++ b/sc4pd/source/Convolution.cpp @@ -0,0 +1,222 @@ +/* sc4pd + Convolution~ + + 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: Ambarchi/Muller/Voice Crack: Oystered + +*/ + +#include "sc4pd.hpp" +#include "fftlib.h" + +/* ------------------------ Convolution~ -------------------------------*/ + +class Convolution_ar: + public sc4pd_dsp +{ + FLEXT_HEADER(Convolution_ar,sc4pd_dsp); + +public: + Convolution_ar(int argc, t_atom *argv); + ~Convolution_ar(); + +protected: + virtual void m_signal(int n, t_sample *const *in, t_sample *const *out); + virtual void m_dsp(int n, t_sample *const *in, t_sample *const *out); + +private: + int m_pos, m_insize, m_fftsize,m_mask; + int m_log2n; + + float *m_inbuf1,*m_inbuf2, *m_fftbuf1, *m_fftbuf2, *m_outbuf,*m_overlapbuf; + +}; + +FLEXT_LIB_DSP_V("Convolution~",Convolution_ar); + +Convolution_ar::Convolution_ar(int argc, t_atom *argv) +{ + + //parse arguments + AtomList Args(argc,argv); + + m_insize = sc_getfloatarg(Args,0); + + AddInSignal("signal"); + AddInSignal("kernel"); + AddOutSignal(); + + + //require size N+M-1 to be a power of two + + m_fftsize=2*(m_insize); + + //just use memory for the input buffers and fft buffers + int insize = m_insize * sizeof(float); + int fftsize = m_fftsize * sizeof(float); + + m_inbuf1 = new float[m_insize]; + m_inbuf2 = new float[m_insize]; + + m_fftbuf1 = new float[m_fftsize]; + m_fftbuf2 = new float[m_fftsize]; + + m_outbuf = new float[m_fftsize]; + m_overlapbuf = new float[m_insize]; + + memset(m_outbuf, 0, fftsize); + memset(m_overlapbuf, 0, insize); + + m_log2n = LOG2CEIL(m_fftsize); + + //test for full input buffer + m_mask = m_insize; + m_pos = 0; +} + +Convolution_ar::~Convolution_ar() +{ + delete m_inbuf1; + delete m_inbuf2; + + delete m_fftbuf1; + delete m_fftbuf2; + + delete m_outbuf; + delete m_overlapbuf; +} + +void Convolution_ar::m_dsp(int n, t_sample *const *in, + t_sample *const *out) +{ + +} + +extern float* cosTable[32]; + +void Convolution_ar::m_signal(int n, t_sample *const *in, + t_sample *const *out) +{ + float *in1 = in[0]; + float *in2 = in[1]; + + float *out1 = m_inbuf1 + m_pos; + float *out2 = m_inbuf2 + m_pos; + + int numSamples = 2*n; //??? mWorld->mFullRate.mBufLength; + + // copy input + CopySamples(out1, in1, numSamples); + CopySamples(out2, in2, numSamples); + + m_pos += numSamples; + + if (m_pos & m_insize) + { + + //have collected enough samples to transform next frame + m_pos = 0; //reset collection counter + + // copy to fftbuf + + uint32 insize=m_insize * sizeof(float); + memcpy(m_fftbuf1, m_inbuf1, insize); + memcpy(m_fftbuf2, m_inbuf2, insize); + + //zero pad second part of buffer to allow for convolution + memset(m_fftbuf1+m_insize, 0, insize); + memset(m_fftbuf2+m_insize, 0, insize); + + int log2n = m_log2n; + + + // do windowing + DoWindowing(log2n, m_fftbuf1, m_fftsize); + DoWindowing(log2n, m_fftbuf2, m_fftsize); + + // do fft +/* #if __VEC__ + ctoz(m_fftbuf1, 2, outbuf1, 1, 1L<<log2n); ctoz(m_fftbuf2, 2, outbuf2, 1, 1L<<log2n); + #else */ + +//in place transform for now + rffts(m_fftbuf1, log2n, 1, cosTable[log2n]); + rffts(m_fftbuf2, log2n, 1, cosTable[log2n]); +//#endif + +//complex multiply time + int numbins = m_fftsize >> 1; //m_fftsize - 2 >> 1; + + float * p1= m_fftbuf1; + float * p2= m_fftbuf2; + + p1[0] *= p2[0]; + p1[1] *= p2[1]; + + //complex multiply + for (int i=1; i<numbins; ++i) { + float real,imag; + int realind,imagind; + realind= 2*i; imagind= realind+1; + real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind]; + imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind]; + p1[realind] = real; //p2->bin[i]; + p1[imagind]= imag; + } + + //copy second part from before to overlap + memcpy(m_overlapbuf, m_outbuf+m_insize, m_insize * sizeof(float)); + + //inverse fft into outbuf + memcpy(m_outbuf, m_fftbuf1, m_fftsize * sizeof(float)); + + //in place + riffts(m_outbuf, log2n, 1, cosTable[log2n]); + + DoWindowing(log2n, m_outbuf, m_fftsize); + } + + //write out samples copied from outbuf, with overlap added in + + float *output = out[0]; + float *nout= m_outbuf+m_pos; + float *overlap= m_overlapbuf+m_pos; + + for (int i=0; i<numSamples; ++i) + { + *++output = *++nout + *++overlap; + } + +} + + + + |