diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2003-01-08 04:37:20 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2003-01-08 04:37:20 +0000 |
commit | 900871454af06db1d751e28cea56f59dc43d3c17 (patch) | |
tree | f0056d2f328953865d8882a6c8c5e3c673cf1254 /externals/grill/fftease/src | |
parent | b8510c87be3a74307f4ad6122d75a353d350b84c (diff) |
""
svn path=/trunk/; revision=328
Diffstat (limited to 'externals/grill/fftease/src')
-rw-r--r-- | externals/grill/fftease/src/burrow~.cpp | 125 | ||||
-rw-r--r-- | externals/grill/fftease/src/cross~.cpp | 236 | ||||
-rw-r--r-- | externals/grill/fftease/src/dentist~.cpp | 272 | ||||
-rw-r--r-- | externals/grill/fftease/src/disarray~.cpp | 286 | ||||
-rw-r--r-- | externals/grill/fftease/src/drown~.cpp | 227 | ||||
-rw-r--r-- | externals/grill/fftease/src/ether~.cpp | 251 | ||||
-rw-r--r-- | externals/grill/fftease/src/main.cpp | 15 | ||||
-rw-r--r-- | externals/grill/fftease/src/main.h | 4 |
8 files changed, 1345 insertions, 71 deletions
diff --git a/externals/grill/fftease/src/burrow~.cpp b/externals/grill/fftease/src/burrow~.cpp index ffb6c90a..aef5e7aa 100644 --- a/externals/grill/fftease/src/burrow~.cpp +++ b/externals/grill/fftease/src/burrow~.cpp @@ -3,8 +3,6 @@ FFTease - A set of Live Spectral Processors Originally written by Eric Lyon and Christopher Penrose for the Max/MSP platform -This flext port is based on the jMax port of Christian Klippel - Copyright (c)Thomas Grill (xovo@gmx.net) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. @@ -30,22 +28,23 @@ protected: I blsz; BL _invert; - I _inCount; - I *_bitshuffle; F _threshold,_multiplier; F _thresh_dB,_mult_dB; - F *_Wanal; - F *_Wsyn; - F *_inputOne,*_inputTwo; - F *_Hwin; - F *_bufferOne,*_bufferTwo; - F *_channelOne,*_channelTwo; + F *_input1,*_input2; + F *_buffer1,*_buffer2; + F *_channel1,*_channel2; F *_output; F *_trigland; + I *_bitshuffle; + F *_Wanal,*_Wsyn,*_Hwin; + + I _inCount; private: + enum { _MULT_ = 4 }; + V Clear(); V Delete(); @@ -103,8 +102,8 @@ burrow::burrow(I argc,const t_atom *argv): Clear(); - AddInSignal("Commands and original signal"); - AddInSignal("Modulating signal"); + AddInSignal("Messages and input signal"); + AddInSignal("Reference signal"); AddOutSignal("Transformed signal"); } @@ -117,11 +116,11 @@ V burrow::Clear() { _bitshuffle = NULL; _trigland = NULL; - _inputOne = _inputTwo = NULL; + _input1 = _input2 = NULL; _Hwin = NULL; _Wanal = _Wsyn = NULL; - _bufferOne = _bufferTwo = NULL; - _channelOne = _channelTwo = NULL; + _buffer1 = _buffer2 = NULL; + _channel1 = _channel2 = NULL; _output = NULL; } @@ -129,15 +128,15 @@ V burrow::Delete() { if(_bitshuffle) delete[] _bitshuffle; if(_trigland) delete[] _trigland; - if(_inputOne) delete[] _inputOne; - if(_inputTwo) delete[] _inputTwo; + if(_input1) delete[] _input1; + if(_input2) delete[] _input2; if(_Hwin) delete[] _Hwin; if(_Wanal) delete[] _Wanal; if(_Wsyn) delete[] _Wsyn; - if(_bufferOne) delete[] _bufferOne; - if(_bufferTwo) delete[] _bufferTwo; - if(_channelOne) delete[] _channelOne; - if(_channelTwo) delete[] _channelTwo; + if(_buffer1) delete[] _buffer1; + if(_buffer2) delete[] _buffer2; + if(_channel1) delete[] _channel1; + if(_channel2) delete[] _channel2; if(_output) delete[] _output; } @@ -152,23 +151,25 @@ V burrow::m_dsp(I n,S *const *in,S *const *out) Delete(); /* preset the objects data */ - const I _N = _D*4,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; + const I _N = _D*_MULT_,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; _inCount = -_Nw; /* assign memory to the buffers */ + _input1 = new F[_Nw]; + _input2 = new F[_Nw]; + _buffer1 = new F[_N]; + _buffer2 = new F[_N]; + _channel1 = new F[_N+2]; + _channel2 = new F[_N+2]; + _output = new F[_Nw]; + _bitshuffle = new I[_N*2]; _trigland = new F[_N*2]; - _inputOne = new F[_Nw]; - _inputTwo = new F[_Nw]; + _Hwin = new F[_Nw]; _Wanal = new F[_Nw]; _Wsyn = new F[_Nw]; - _bufferOne = new F[_N]; - _bufferTwo = new F[_N]; - _channelOne = new F[_N+2]; - _channelTwo = new F[_N+2]; - _output = new F[_Nw]; /* initialize pv-lib functions */ init_rdft( _N, _bitshuffle, _trigland); @@ -178,75 +179,75 @@ V burrow::m_dsp(I n,S *const *in,S *const *out) V burrow::m_signal(I n,S *const *in,S *const *out) { - const S *inOne = in[0],*inTwo = in[1]; - S *outOne = out[0]; - /* declare working variables */ I i, j; - const I _D = blsz,_N = _D*4,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; + const I _D = blsz,_N = _D*_MULT_,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; /* fill our retaining buffers */ _inCount += _D; for(i = 0; i < _N-_D ; i++ ) { - _inputOne[i] = _inputOne[i+_D]; - _inputTwo[i] = _inputTwo[i+_D]; + _input1[i] = _input1[i+_D]; + _input2[i] = _input2[i+_D]; } for(j = 0; i < _N; i++,j++) { - _inputOne[i] = inOne[j]; - _inputTwo[i] = inTwo[j]; + _input1[i] = in[0][j]; + _input2[i] = in[1][j]; } /* apply hamming window and fold our window buffer into the fft buffer */ - fold( _inputOne, _Wanal, _Nw, _bufferOne, _N, _inCount ); - fold( _inputTwo, _Wanal, _Nw, _bufferTwo, _N, _inCount ); + fold( _input1, _Wanal, _Nw, _buffer1, _N, _inCount ); + fold( _input2, _Wanal, _Nw, _buffer2, _N, _inCount ); /* do an fft */ - rdft( _N, 1, _bufferOne, _bitshuffle, _trigland ); - rdft( _N, 1, _bufferTwo, _bitshuffle, _trigland ); + rdft( _N, 1, _buffer1, _bitshuffle, _trigland ); + rdft( _N, 1, _buffer2, _bitshuffle, _trigland ); + + // ---- BEGIN -------------------------------- - /* convert to polar coordinates from complex values */ for ( i = 0; i <= _N2; i++ ) { const I even = i<<1,odd = even+1; + + /* convert to polar coordinates from complex values */ register F a,b; - a = ( i == _N2 ? _bufferOne[1] : _bufferOne[even] ); - b = ( i == 0 || i == _N2 ? 0. : _bufferOne[odd] ); + a = ( i == _N2 ? _buffer1[1] : _buffer1[even] ); + b = ( i == 0 || i == _N2 ? 0. : _buffer1[odd] ); - _channelOne[even] = hypot( a, b ); - _channelOne[odd] = -atan2( b, a ); + _channel1[even] = hypot( a, b ); + _channel1[odd] = -atan2( b, a ); - a = ( i == _N2 ? _bufferTwo[1] : _bufferTwo[even] ); - b = ( i == 0 || i == _N2 ? 0. : _bufferTwo[odd] ); + a = ( i == _N2 ? _buffer2[1] : _buffer2[even] ); + b = ( i == 0 || i == _N2 ? 0. : _buffer2[odd] ); - _channelTwo[even] = hypot( a, b ); + _channel2[even] = hypot( a, b ); /* use simple threshold from second signal to trigger filtering */ - if (_invert?(_channelTwo[even] < _threshold):(_channelTwo[even] > _threshold) ) - _channelOne[even] *= _multiplier; - } - - /* convert back to complex form, read for the inverse fft */ - for ( i = 0; i <= _N2; i++ ) { - const I even = i<<1,odd = even+1; + if (_invert?(_channel2[even] < _threshold):(_channel2[even] > _threshold) ) + _channel1[even] *= _multiplier; - _bufferOne[even] = _channelOne[even] * cos( _channelOne[odd] ); + /* convert back to complex form, read for the inverse fft */ + _buffer1[even] = _channel1[even] * cos( _channel1[odd] ); if ( i != _N2 ) - _bufferOne[odd] = -_channelOne[even] * sin( _channelOne[odd] ); + _buffer1[odd] = -_channel1[even] * sin( _channel1[odd] ); } + + // ---- END -------------------------------- + + /* do an inverse fft */ - rdft( _N, -1, _bufferOne, _bitshuffle, _trigland ); + rdft( _N, -1, _buffer1, _bitshuffle, _trigland ); /* dewindow our result */ - overlapadd( _bufferOne, _N, _Wsyn, _output, _Nw, _inCount); + overlapadd( _buffer1, _N, _Wsyn, _output, _Nw, _inCount); /* set our output and adjust our retaining output buffer */ - F mult = 1./_N; + const F mult = 1./_N; for ( j = 0; j < _D; j++ ) - outOne[j] = _output[j] * mult; + out[0][j] = _output[j] * mult; for ( j = 0; j < _N-_D; j++ ) _output[j] = _output[j+_D]; diff --git a/externals/grill/fftease/src/cross~.cpp b/externals/grill/fftease/src/cross~.cpp new file mode 100644 index 00000000..52874127 --- /dev/null +++ b/externals/grill/fftease/src/cross~.cpp @@ -0,0 +1,236 @@ +/* + +FFTease - A set of Live Spectral Processors +Originally written by Eric Lyon and Christopher Penrose for the Max/MSP platform + +Copyright (c)Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +#include "main.h" + + +class cross: + public flext_dsp +{ + FLEXT_HEADER_S(cross,flext_dsp,setup) + +public: + cross(I argc,const t_atom *argv); + ~cross(); + +protected: + + virtual V m_dsp(I n,S *const *in,S *const *out); + virtual V m_signal(I n,S *const *in,S *const *out); + + I blsz; + F smprt; + + F *_input1,*_input2; + F *_buffer1,*_buffer2; + F *_channel1,*_channel2; + F *_output; + F *_trigland; + I *_bitshuffle; + F *_Wanal,*_Wsyn,*_Hwin; + + I _inCount; + +private: + enum { _MULT_ = 2 }; + + V Clear(); + V Delete(); + + static V setup(t_classid c); +}; + +FLEXT_LIB_DSP_V("fftease, cross~",cross) + + +V cross::setup(t_classid c) +{ +} + + +cross::cross(I argc,const t_atom *argv): + blsz(0),smprt(0) +{ + Clear(); + + AddInSignal("Messages and driver signal"); + AddInSignal("Filter signal"); + AddInSignal("Threshold signal for cross synthesis"); + AddOutSignal("Transformed signal"); +} + +cross::~cross() +{ + Delete(); +} + +V cross::Clear() +{ + _input1 = _input2 = NULL; + _buffer1 = _buffer2 = NULL; + _channel1 = _channel2 = NULL; + _output = NULL; + + _bitshuffle = NULL; + _trigland = NULL; + + _Hwin = NULL; + _Wanal = _Wsyn = NULL; +} + +V cross::Delete() +{ + if(_input1) delete[] _input1; + if(_input2) delete[] _input2; + if(_buffer1) delete[] _buffer1; + if(_buffer2) delete[] _buffer2; + if(_channel1) delete[] _channel1; + if(_channel2) delete[] _channel2; + if(_output) delete[] _output; + + if(_bitshuffle) delete[] _bitshuffle; + if(_trigland) delete[] _trigland; + + if(_Wanal) delete[] _Wanal; + if(_Wsyn) delete[] _Wsyn; + if(_Hwin) delete[] _Hwin; + + // --------------------------------------------- + +#if 0 + // T.G. These are not used + if(c_lastphase_in1) delete[] c_lastphase_in1; + if(c_lastphase_in2) delete[] c_lastphase_in2; + if(c_lastphase_out) delete[] c_lastphase_out; +#endif +} + + + +V cross::m_dsp(I n,S *const *in,S *const *out) +{ + const I _D = Blocksize(); + const F _R = Samplerate(); + + if(_D != blsz || _R != smprt) { + blsz = _D; + smprt = _R; + + Delete(); + + const int _N = _D*_MULT_,_Nw = _N,_N2 = _N>>1,_Nw2 = _Nw>>1; + + _inCount = -_Nw; + + _input1 = new F[_Nw]; + _input2 = new F[_Nw]; + _buffer1 = new F[_N]; + _buffer2 = new F[_N]; + _channel1 = new F[_N+2]; + _channel2 = new F[_N+2]; + _output = new F[_Nw]; + + _bitshuffle = new I[_N*2]; + _trigland = new F[_N*2]; + + _Wanal = new F[_Nw]; + _Wsyn = new F[_Nw]; + _Hwin = new F[_Nw]; + + init_rdft( _N, _bitshuffle, _trigland); + + // makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); + makehanning( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0,0); + + // --------------------------------------------- + +#if 0 + // T.G. These are not used + /* for convert */ + c_lastphase_in1 = new F[_N2+1]; + c_lastphase_in2 = new F[_N2+1]; + c_lastphase_out = new F[_N2+1]; + c_fundamental = _R/( _N2<<1 ); + c_factor_in = _R/(_D * __TWOPI); + c_factor_out = __TWOPI * _D/_R; +#endif + } +} + +V cross::m_signal(I n,S *const *in,S *const *out) +{ + /* declare working variables */ + I i, j; + const I _D = blsz,_N = _D*_MULT_,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; + + _inCount += _D; + + for ( j = 0 ; j < _N-_D ; j++ ) { + _input1[j] = _input1[j+_D]; + _input2[j] = _input2[j+_D]; + } + for (i = 0; j < _N; j++,i++ ) { + _input1[j] = in[0][i]; + _input2[j] = in[1][i]; + } + + fold( _input1, _Wanal, _Nw, _buffer1, _N, _inCount ); + fold( _input2, _Wanal, _Nw, _buffer2, _N, _inCount ); + + rdft( _N, 1, _buffer1, _bitshuffle, _trigland ); + rdft( _N, 1, _buffer2, _bitshuffle, _trigland ); + + + // ---- BEGIN -------------------------------- + + // TG: filled only once per signal vector!! + float threshie = *in[2]; + + for ( i = 0; i <= _N2; i++ ) { + const I even = i<<1,odd = even+1; + + F a = ( i == _N2 ? _buffer1[1] : _buffer2[even] ); + F b = ( i == 0 || i == _N2 ? 0. : _buffer2[odd] ); + F gainer = hypot( a, b ) ; + + a = ( i == _N2 ? _buffer1[1] : _buffer1[even] ); + b = ( i == 0 || i == _N2 ? 0. : _buffer1[odd] ); + + if( gainer > threshie ) + _channel1[even] = hypot( a, b ) * gainer; + // else + // channel1[even] = hypot( a, b); + + _channel1[odd] = -atan2( b, a ); + _buffer1[even] = _channel1[even] * cos( _channel1[odd] ); + + if ( i != _N2 ) + _buffer1[odd] = -_channel1[even] * sin( _channel1[odd] ); + } + + // ---- END -------------------------------- + + rdft( _N, -1, _buffer1, _bitshuffle, _trigland ); + + overlapadd( _buffer1, _N, _Wsyn, _output, _Nw, _inCount); + + const F mult = 1./_N; + for ( j = 0; j < _D; j++ ) + out[0][j] = _output[j] * mult; + + for ( j = 0; j < _N-_D; j++ ) + _output[j] = _output[j+_D]; + for (; j < _N; j++ ) + _output[j] = 0.; +} + + + diff --git a/externals/grill/fftease/src/dentist~.cpp b/externals/grill/fftease/src/dentist~.cpp new file mode 100644 index 00000000..8c9a0379 --- /dev/null +++ b/externals/grill/fftease/src/dentist~.cpp @@ -0,0 +1,272 @@ +/* + +FFTease - A set of Live Spectral Processors +Originally written by Eric Lyon and Christopher Penrose for the Max/MSP platform + +Copyright (c)Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +#include "main.h" +#include <stdlib.h> + +class dentist: + public flext_dsp +{ + FLEXT_HEADER_S(dentist,flext_dsp,setup) + +public: + dentist(I argc,const t_atom *argv); + ~dentist(); + +protected: + + virtual V m_dsp(I n,S *const *in,S *const *out); + virtual V m_signal(I n,S *const *in,S *const *out); + + I blsz; + F smprt; + + F *_input1,*_input2; + F *_buffer1,*_buffer2; + F *_channel1,*_channel2; + F *_output; + F *_trigland; + I *_bitshuffle; + F *_Wanal,*_Wsyn,*_Hwin; + + I _inCount; + + // ----------------------------- + + I *_bin_selection; + I _tooth_count; + F _knee; + I _max_bin; // determined by _knee and fundamental frequency + + V reset_shuffle(); + +private: + enum { _MULT_ = 4 }; + + V Clear(); + V Delete(); + + V ms_knee(F knee); + V ms_teeth(I teeth) { _tooth_count = teeth; reset_shuffle(); } + + + static V setup(t_classid c); + + FLEXT_CALLBACK(reset_shuffle) + FLEXT_ATTRGET_F(_knee) + FLEXT_CALLSET_F(ms_knee) + FLEXT_ATTRGET_I(_tooth_count) + FLEXT_CALLSET_I(ms_teeth) +}; + +FLEXT_LIB_DSP_V("fftease, dentist~",dentist) + + +V dentist::setup(t_classid c) +{ + FLEXT_CADDBANG(c,0,reset_shuffle); + + FLEXT_CADDATTR_VAR(c,"knee",_knee,ms_knee); + FLEXT_CADDATTR_VAR(c,"teeth",_tooth_count,ms_teeth); +} + + +dentist::dentist(I argc,const t_atom *argv): + blsz(0),smprt(0), + _knee(500),_tooth_count(10) +{ + /* parse and set object's options given */ + if(argc >= 1) { + if(CanbeFloat(argv[0])) + _knee = GetAFloat(argv[0]); + else + post("%s - Knee must be a float value - set to %0f",thisName(),_knee); + } + if(argc >= 2) { + if(CanbeInt(argv[1])) + _tooth_count = GetAInt(argv[1]); + else + post("%s - Teeth must be an integer value - set to %0i",thisName(),_tooth_count); + } + + Clear(); + + AddInSignal("Messages and input signal"); + AddOutSignal("Transformed signal"); +} + +dentist::~dentist() +{ + Delete(); +} + +V dentist::Clear() +{ + _input1 = _input2 = NULL; + _buffer1 = _buffer2 = NULL; + _channel1 = _channel2 = NULL; + _output = NULL; + + _bitshuffle = NULL; + _trigland = NULL; + + _Hwin = NULL; + _Wanal = _Wsyn = NULL; + + // ----------------------------- + + _bin_selection = NULL; +} + +V dentist::Delete() +{ + if(_input1) delete[] _input1; + if(_buffer1) delete[] _buffer1; + if(_channel1) delete[] _channel1; +/* + if(_input2) delete[] _input2; + if(_buffer2) delete[] _buffer2; + if(_channel2) delete[] _channel2; +*/ + if(_output) delete[] _output; + + if(_bitshuffle) delete[] _bitshuffle; + if(_trigland) delete[] _trigland; + + if(_Wanal) delete[] _Wanal; + if(_Wsyn) delete[] _Wsyn; + if(_Hwin) delete[] _Hwin; + + // ----------------------------- + + if(_bin_selection) delete[] _bin_selection; +} + + +V dentist::ms_knee(F f) +{ + _knee = f; // store original + + const F funda = Samplerate()/(2*_MULT_*Blocksize()); + + // TG: This is a different, but steady correction than in original fftease + if( f < funda ) f = funda; + else if(f > funda/2) f = funda/2; + + _max_bin = 1; + for(F curfreq = 0; curfreq < f; curfreq += funda) ++_max_bin; +} + + +V dentist::m_dsp(I n,S *const *in,S *const *out) +{ + const I _D = Blocksize(); + const F _R = Samplerate(); + if(_D != blsz || _R != smprt) { + blsz = _D; + smprt = _R; + + Delete(); + // --------------------------------------------- + + const int _N = _D*_MULT_,_Nw = _N,_Nw2 = _Nw>>1,_N2 = _N>>1; + + _inCount = -_Nw; + + _input1 = new F[_Nw]; + _buffer1 = new F[_N]; + _channel1 = new F[_N+2]; + /* + _input2 = new F[_Nw]; + _buffer2 = new F[_N]; + _channel2 = new F[_N+2]; + */ + + _output = new F[_Nw]; + + _bitshuffle = new I[_N*2]; + _trigland = new F[_N*2]; + + _Wanal = new F[_Nw]; + _Wsyn = new F[_Nw]; + _Hwin = new F[_Nw]; + + init_rdft( _N, _bitshuffle, _trigland); + makewindows( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0); + + // --------------------------------------------- + + // calculation of _max_bin + ms_knee(_knee); + + _bin_selection = new I[_N2]; + reset_shuffle(); + } +} + +V dentist::m_signal(I n,S *const *in,S *const *out) +{ + /* declare working variables */ + I i, j; + const I _D = blsz,_N = _D*_MULT_,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; + + _inCount += _D; + + for ( j = 0 ; j < _N-_D ; j++ ) + _input1[j] = _input1[j+_D]; + for (i = 0; j < _N; j++,i++ ) + _input1[j] = in[0][i]; + + fold( _input1, _Wanal, _Nw, _buffer1, _N, _inCount ); + rdft( _N, 1, _buffer1, _bitshuffle, _trigland ); + + // ---- BEGIN -------------------------------- + + leanconvert( _buffer1, _channel1, _N2 ); + + for( i = 0; i < _N2 ; i++){ + if( !_bin_selection[i] ) _channel1[i*2] = 0; + } + + leanunconvert( _channel1, _buffer1, _N2 ); + + // ---- END -------------------------------- + + rdft( _N, -1, _buffer1, _bitshuffle, _trigland ); + overlapadd( _buffer1, _N, _Wsyn, _output, _Nw, _inCount); + + const F mult = 1./_N; + for ( j = 0; j < _D; j++ ) + out[0][j] = _output[j] * mult; + + for ( j = 0; j < _N-_D; j++ ) + _output[j] = _output[j+_D]; + for (; j < _N; j++ ) + _output[j] = 0.; +} + + +V dentist::reset_shuffle() +{ + const I _N2 = Blocksize()*_MULT_/2; + I teeth = _tooth_count; + + // check number of teeth + if( teeth < 0 ) teeth = 0; + else if( teeth > _N2 ) teeth = _N2; + + // clear and set random bins + I i; + for( i = 0; i < _N2; i++ ) + _bin_selection[i] = 0; + for( i = 0; i < _tooth_count; i++ ) + _bin_selection[rand()%_max_bin] = 1; +} diff --git a/externals/grill/fftease/src/disarray~.cpp b/externals/grill/fftease/src/disarray~.cpp new file mode 100644 index 00000000..428fe2d6 --- /dev/null +++ b/externals/grill/fftease/src/disarray~.cpp @@ -0,0 +1,286 @@ +/* + +FFTease - A set of Live Spectral Processors +Originally written by Eric Lyon and Christopher Penrose for the Max/MSP platform + +Copyright (c)Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +#include "main.h" +#include <stdlib.h> + +class disarray: + public flext_dsp +{ + FLEXT_HEADER_S(disarray,flext_dsp,setup) + +public: + disarray(I argc,const t_atom *argv); + ~disarray(); + +protected: + + virtual V m_dsp(I n,S *const *in,S *const *out); + virtual V m_signal(I n,S *const *in,S *const *out); + + I blsz; + F smprt; + + F *_input1,*_input2; + F *_buffer1,*_buffer2; + F *_channel1,*_channel2; + F *_output; + F *_trigland; + I *_bitshuffle; + F *_Wanal,*_Wsyn,*_Hwin; + + I _inCount,_nmult; + + // ----------------------------- + + BL _qual; + I _shuffle_count,_max_bin; + F _freq; + I *_shuffle_in,*_shuffle_out; + + + V reset_shuffle(); + +private: + V Clear(); + V Delete(); + + V ms_freq(F f); + + static V setup(t_classid c); + + FLEXT_CALLBACK(reset_shuffle) + FLEXT_ATTRGET_F(_freq) + FLEXT_CALLSET_F(ms_freq) +}; + +FLEXT_LIB_DSP_V("fftease, disarray~",disarray) + + +V disarray::setup(t_classid c) +{ + FLEXT_CADDBANG(c,0,reset_shuffle); + + FLEXT_CADDATTR_VAR(c,"freq",_freq,ms_freq); +} + + +disarray::disarray(I argc,const t_atom *argv): + blsz(0),smprt(0), + _freq(1300),_qual(false),_shuffle_count(20) +{ + /* parse and set object's options given */ + if(argc >= 1) { + if(CanbeFloat(argv[0])) + _freq = GetAFloat(argv[0]); + else + post("%s - Freq must be a float value - set to %0f",thisName(),_freq); + } + if(argc >= 2) { + if(CanbeBool(argv[1])) + _qual = GetABool(argv[1]); + else + post("%s - Quality must be a boolean value - set to %0i",thisName(),_qual?1:0); + } + if(argc >= 3) { + if(CanbeInt(argv[2])) + _shuffle_count = GetAInt(argv[2]); + else + post("%s - Shufflecount must be an integer value - set to %0i",thisName(),_shuffle_count); + } + + _nmult = _qual?4:2; + + Clear(); + + AddInSignal("Messages and input signal"); + AddOutSignal("Transformed signal"); +} + +disarray::~disarray() +{ + Delete(); +} + +V disarray::Clear() +{ + _input1 = _input2 = NULL; + _buffer1 = _buffer2 = NULL; + _channel1 = _channel2 = NULL; + _output = NULL; + + _bitshuffle = NULL; + _trigland = NULL; + + _Hwin = NULL; + _Wanal = _Wsyn = NULL; + + // ----------------------------- + + _shuffle_in = _shuffle_out = NULL; +} + +V disarray::Delete() +{ + if(_input1) delete[] _input1; + if(_buffer1) delete[] _buffer1; + if(_channel1) delete[] _channel1; +/* + if(_input2) delete[] _input2; + if(_buffer2) delete[] _buffer2; + if(_channel2) delete[] _channel2; +*/ + if(_output) delete[] _output; + + if(_bitshuffle) delete[] _bitshuffle; + if(_trigland) delete[] _trigland; + + if(_Wanal) delete[] _Wanal; + if(_Wsyn) delete[] _Wsyn; + if(_Hwin) delete[] _Hwin; + + // ----------------------------- + + if(_shuffle_in) delete[] _shuffle_in; + if(_shuffle_out) delete[] _shuffle_out; +} + + +V disarray::ms_freq(F f) +{ + _freq = f; // store original + + const F funda = Samplerate()/(2*_nmult*Blocksize()); + + // TG: This is a different, but steady correction than in original fftease + if( f < funda ) f = funda; + else if(f > funda/2) f = funda/2; + + _max_bin = 1; + for(F curfreq = 0; curfreq < f; curfreq += funda) ++_max_bin; +} + + +V disarray::m_dsp(I n,S *const *in,S *const *out) +{ + const I _D = Blocksize(); + const F _R = Samplerate(); + + if(_D != blsz || _R != smprt) { + blsz = _D; + smprt = _R; + + Delete(); + // --------------------------------------------- + + const int _N = _D*_nmult,_Nw = _N,_Nw2 = _Nw>>1,_N2 = _N>>1; + + _inCount = -_Nw; + + _input1 = new F[_Nw]; + _buffer1 = new F[_N]; + _channel1 = new F[_N+2]; + /* + _input2 = new F[_Nw]; + _buffer2 = new F[_N]; + _channel2 = new F[_N+2]; + */ + + _output = new F[_Nw]; + + _bitshuffle = new I[_N*2]; + _trigland = new F[_N*2]; + + _Wanal = new F[_Nw]; + _Wsyn = new F[_Nw]; + _Hwin = new F[_Nw]; + + init_rdft( _N, _bitshuffle, _trigland); + + if(_qual) + makewindows( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0); + else + makehanning( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0,0); + + // --------------------------------------------- + + _shuffle_in = new I[_N2]; + _shuffle_out = new I[_N2]; + + // calculate _max_bin + ms_freq(_freq); + + reset_shuffle(); + } +} + +V disarray::m_signal(I n,S *const *in,S *const *out) +{ + /* declare working variables */ + I i, j; + const I _D = blsz,_N = _D*_nmult,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; + + _inCount += _D; + + for ( j = 0 ; j < _N-_D ; j++ ) + _input1[j] = _input1[j+_D]; + for (i = 0; j < _N; j++,i++ ) + _input1[j] = in[0][i]; + + fold( _input1, _Wanal, _Nw, _buffer1, _N, _inCount ); + rdft( _N, 1, _buffer1, _bitshuffle, _trigland ); + + // ---- BEGIN -------------------------------- + + leanconvert( _buffer1, _channel1, _N2 ); + + for( i = 0; i < _shuffle_count ; i++){ + F tmp = _channel1[ _shuffle_in[ i ] * 2 ]; + _channel1[ _shuffle_in[ i ] * 2] = _channel1[ _shuffle_out[ i ] * 2]; + _channel1[ _shuffle_out[ i ] * 2] = tmp; + } + + leanunconvert( _channel1, _buffer1, _N2 ); + + // ---- END -------------------------------- + + rdft( _N, -1, _buffer1, _bitshuffle, _trigland ); + overlapadd( _buffer1, _N, _Wsyn, _output, _Nw, _inCount); + + const F mult = 1./_N; + for ( j = 0; j < _D; j++ ) + out[0][j] = _output[j] * mult; + + for ( j = 0; j < _N-_D; j++ ) + _output[j] = _output[j+_D]; + for (; j < _N; j++ ) + _output[j] = 0.; +} + + +V disarray::reset_shuffle() +{ + const I _N2 = Blocksize()*_nmult/2; + + I i; + for( i = 0; i < _N2; i++ ) + _shuffle_out[i] = _shuffle_in[i] = i ; + + for( i = 0; i < 10000; i++ ) { + int p1 = _shuffle_out[ rand()%_max_bin ]; + int p2 = _shuffle_out[ rand()%_max_bin ]; + int temp = _shuffle_out[ p1 ]; + _shuffle_out[ p1 ] = _shuffle_out[ p2 ]; + _shuffle_out[ p2 ] = temp; + } + +} + diff --git a/externals/grill/fftease/src/drown~.cpp b/externals/grill/fftease/src/drown~.cpp new file mode 100644 index 00000000..0e4ee4a8 --- /dev/null +++ b/externals/grill/fftease/src/drown~.cpp @@ -0,0 +1,227 @@ +/* + +FFTease - A set of Live Spectral Processors +Originally written by Eric Lyon and Christopher Penrose for the Max/MSP platform + +Copyright (c)Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +#include "main.h" +#include <stdlib.h> + +class drown: + public flext_dsp +{ + FLEXT_HEADER_S(drown,flext_dsp,setup) + +public: + drown(I argc,const t_atom *argv); + ~drown(); + +protected: + + virtual V m_dsp(I n,S *const *in,S *const *out); + virtual V m_signal(I n,S *const *in,S *const *out); + + I blsz; + F smprt; + + F *_input1,*_input2; + F *_buffer1,*_buffer2; + F *_channel1,*_channel2; + F *_output; +// F *_trigland; + // I *_bitshuffle; + F *_Wanal,*_Wsyn,*_Hwin; + + I _inCount,_nmult; + + // ----------------------------- + +private: + V Clear(); + V Delete(); + + static V setup(t_classid c); +}; + +FLEXT_LIB_DSP_V("fftease, drown~",drown) + + +V drown::setup(t_classid c) +{ +} + + +drown::drown(I argc,const t_atom *argv): + blsz(0),smprt(0),_nmult(4) +{ + Clear(); + + AddInSignal("Messages and input signal"); + AddInSignal("Threshold generator signal"); + AddInSignal("Multiplier signal for weak bins"); + AddOutSignal("Transformed signal"); +} + +drown::~drown() +{ + Delete(); +} + +V drown::Clear() +{ + _input1 = _input2 = NULL; + _buffer1 = _buffer2 = NULL; + _channel1 = _channel2 = NULL; + _output = NULL; +/* + _bitshuffle = NULL; + _trigland = NULL; +*/ + _Hwin = NULL; + _Wanal = _Wsyn = NULL; + + // ----------------------------- + +} + +V drown::Delete() +{ + if(_input1) delete[] _input1; + if(_buffer1) delete[] _buffer1; + if(_channel1) delete[] _channel1; +/* + if(_input2) delete[] _input2; + if(_buffer2) delete[] _buffer2; + if(_channel2) delete[] _channel2; +*/ + if(_output) delete[] _output; +/* + if(_bitshuffle) delete[] _bitshuffle; + if(_trigland) delete[] _trigland; +*/ + if(_Wanal) delete[] _Wanal; + if(_Wsyn) delete[] _Wsyn; + if(_Hwin) delete[] _Hwin; + + // ----------------------------- + +} + + +V drown::m_dsp(I n,S *const *in,S *const *out) +{ + const I _D = Blocksize(); + const F _R = Samplerate(); + + if(_D != blsz || _R != smprt) { + blsz = _D; + smprt = _R; + + Delete(); + // --------------------------------------------- + + const int _N = _D*_nmult,_Nw = _N,_Nw2 = _Nw>>1,_N2 = _N>>1; + + _inCount = -_Nw; + + _input1 = new F[_Nw]; + _buffer1 = new F[_N]; + _channel1 = new F[_N+2]; + /* + _input2 = new F[_Nw]; + _buffer2 = new F[_N]; + _channel2 = new F[_N+2]; + */ + + _output = new F[_Nw]; + + /* + _bitshuffle = new I[_N*2]; + _trigland = new F[_N*2]; + init_rdft( _N, _bitshuffle, _trigland); + */ + + _Wanal = new F[_Nw]; + _Wsyn = new F[_Nw]; + _Hwin = new F[_Nw]; + makewindows( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0); + } +} + + +/* helper function */ +static void nudist( float *_S, float *_C, float threshold, float fmult, int N2 ) +{ + int real, imag, amp, phase; + int i; + float maxamp = 1.; + for ( i = 0; i <= N2; i++ ) { + imag = phase = ( real = amp = i<<1 ) + 1; + F a = ( i == N2 ? _S[1] : _S[real] ); + F b = ( i == 0 || i == N2 ? 0. : _S[imag] ); + + _C[amp] = hypot( a, b ); + if( _C[amp] < threshold) _C[amp] *= fmult; + + _C[phase] = -atan2( b, a ); + } + + for ( i = 0; i <= N2; i++ ) { + imag = phase = ( real = amp = i<<1 ) + 1; + _S[real] = _C[amp] * cos( _C[phase] ); + if ( i != N2 ) + _S[imag] = -_C[amp] * sin( _C[phase] ); + } +} + + +V drown::m_signal(I n,S *const *in,S *const *out) +{ + /* declare working variables */ + I i, j; + const I _D = blsz,_N = _D*_nmult,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; + + _inCount += _D; + + for ( j = 0 ; j < _N-_D ; j++ ) + _input1[j] = _input1[j+_D]; + for (i = 0; j < _N; j++,i++ ) + _input1[j] = in[0][i]; + + fold( _input1, _Wanal, _Nw, _buffer1, _N, _inCount ); + +// rdft( _N, 1, _buffer1, _bitshuffle, _trigland ); + rfft( _buffer1, _N2, 1); + + // ---- BEGIN -------------------------------- + + { + // only first value of the signal vectors + const F thresh = in[1][0],mult = in[2][0]; + + nudist( _buffer1, _channel1, thresh, mult, _N2 ); + } + + // ---- END -------------------------------- + + rfft( _buffer1, _N2, 0); +// rdft( _N, -1, _buffer1, _bitshuffle, _trigland ); + + overlapadd( _buffer1, _N, _Wsyn, _output, _Nw, _inCount); + + const F mult = 1./_N; + for ( j = 0; j < _D; j++ ) + out[0][j] = _output[j] * mult; + + for ( j = 0; j < _N-_D; j++ ) + _output[j] = _output[j+_D]; + for (; j < _N; j++ ) + _output[j] = 0.; +} + + diff --git a/externals/grill/fftease/src/ether~.cpp b/externals/grill/fftease/src/ether~.cpp new file mode 100644 index 00000000..16fbaaff --- /dev/null +++ b/externals/grill/fftease/src/ether~.cpp @@ -0,0 +1,251 @@ +/* + +FFTease - A set of Live Spectral Processors +Originally written by Eric Lyon and Christopher Penrose for the Max/MSP platform + +Copyright (c)Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +#include "main.h" +#include <stdlib.h> + +class ether: + public flext_dsp +{ + FLEXT_HEADER_S(ether,flext_dsp,setup) + +public: + ether(I argc,const t_atom *argv); + ~ether(); + +protected: + + virtual V m_dsp(I n,S *const *in,S *const *out); + virtual V m_signal(I n,S *const *in,S *const *out); + + I blsz; + F smprt; + + F *_input1,*_input2; + F *_buffer1,*_buffer2; + F *_channel1,*_channel2; + F *_output; + F *_trigland; + I *_bitshuffle; + F *_Wanal,*_Wsyn,*_Hwin; + + I _inCount,_nmult; + + // ----------------------------- + + BL _qual,_invert; + F _threshMult; + +private: + V Clear(); + V Delete(); + + static V setup(t_classid c); + + + FLEXT_ATTRVAR_B(_invert) + FLEXT_ATTRVAR_F(_threshMult) +}; + +FLEXT_LIB_DSP_V("fftease, ether~",ether) + + +V ether::setup(t_classid c) +{ + FLEXT_CADDATTR_VAR1(c,"invert",_invert); + FLEXT_CADDATTR_VAR1(c,"thresh",_threshMult); +} + + +ether::ether(I argc,const t_atom *argv): + blsz(0),smprt(0), + _qual(false),_threshMult(0),_invert(false) +{ + /* parse and set object's options given */ + if(argc >= 1) { + if(CanbeBool(argv[0])) + _qual = GetABool(argv[0]); + else + post("%s - Quality must be a boolean value - set to %0i",thisName(),_qual?1:0); + } + + _nmult = _qual?4:2; + + Clear(); + + AddInSignal("Messages and input signal"); + AddInSignal("Reference signal"); + AddOutSignal("Transformed signal"); +} + +ether::~ether() +{ + Delete(); +} + +V ether::Clear() +{ + _input1 = _input2 = NULL; + _buffer1 = _buffer2 = NULL; + _channel1 = _channel2 = NULL; + _output = NULL; + + _bitshuffle = NULL; + _trigland = NULL; + + _Hwin = NULL; + _Wanal = _Wsyn = NULL; + + // ----------------------------- +} + +V ether::Delete() +{ + if(_input1) delete[] _input1; + if(_buffer1) delete[] _buffer1; + if(_channel1) delete[] _channel1; + + if(_input2) delete[] _input2; + if(_buffer2) delete[] _buffer2; + if(_channel2) delete[] _channel2; + + if(_output) delete[] _output; + + if(_bitshuffle) delete[] _bitshuffle; + if(_trigland) delete[] _trigland; + + if(_Wanal) delete[] _Wanal; + if(_Wsyn) delete[] _Wsyn; + if(_Hwin) delete[] _Hwin; + + // ----------------------------- + +} + + +V ether::m_dsp(I n,S *const *in,S *const *out) +{ + const I _D = Blocksize(); + const F _R = Samplerate(); + + if(_D != blsz || _R != smprt) { + blsz = _D; + smprt = _R; + + Delete(); + // --------------------------------------------- + + const int _N = _D*_nmult,_Nw = _N,_Nw2 = _Nw>>1,_N2 = _N>>1; + + _inCount = -_Nw; + + _input1 = new F[_Nw]; + _buffer1 = new F[_N]; + _channel1 = new F[_N+2]; + + _input2 = new F[_Nw]; + _buffer2 = new F[_N]; + _channel2 = new F[_N+2]; + + _output = new F[_Nw]; + + _bitshuffle = new I[_N*2]; + _trigland = new F[_N*2]; + + _Wanal = new F[_Nw]; + _Wsyn = new F[_Nw]; + _Hwin = new F[_Nw]; + + init_rdft( _N, _bitshuffle, _trigland); + + if(_qual) + makewindows( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0); + else + makehanning( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0,0); + } +} + +V ether::m_signal(I n,S *const *in,S *const *out) +{ + /* declare working variables */ + I i, j; + const I _D = blsz,_N = _D*_nmult,_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2; + + _inCount += _D; + + for ( j = 0 ; j < _N-_D ; j++ ) { + _input1[j] = _input1[j+_D]; + _input2[j] = _input2[j+_D]; + } + for (i = 0; j < _N; j++,i++ ) { + _input1[j] = in[0][i]; + _input2[j] = in[1][i]; + } + + fold( _input1, _Wanal, _Nw, _buffer1, _N, _inCount ); + fold( _input2, _Wanal, _Nw, _buffer2, _N, _inCount ); + + rdft( _N, 1, _buffer1, _bitshuffle, _trigland ); + rdft( _N, 1, _buffer2, _bitshuffle, _trigland ); + + // ---- BEGIN -------------------------------- + + F threshMult = _threshMult; + if (threshMult == 0. ) threshMult = 1; + + for ( i = 0; i <= _N2; i++ ) { + int even = i<<1,odd = even + 1; + + /* convert to polar coordinates from complex values */ + register F a,b; + + a = ( i == _N2 ? _buffer1[1] : _buffer1[even] ); + b = ( i == 0 || i == _N2 ? 0. : _buffer1[odd] ); + + _channel1[even] = hypot( a, b ); + _channel1[odd] = -atan2( b, a ); + + a = ( i == _N2 ? _buffer2[1] : _buffer2[even] ); + b = ( i == 0 || i == _N2 ? 0. : _buffer2[odd] ); + + _channel2[even] = hypot( a, b ); + _channel2[odd] = -atan2( b, a ); + + /* use simple threshold for inverse compositing */ + + if(_invert?(_channel1[even] > _channel2[even]*threshMult):(_channel1[even] < _channel2[even]*threshMult) ) + _channel1[even] = _channel2[even]; + + if (_channel1[odd] == 0. ) _channel1[odd] = _channel2[odd]; + + + /* convert back to complex form, read for the inverse fft */ + _buffer1[even] = _channel1[even] * cos( _channel1[odd] ); + + if (i != _N2 ) + _buffer1[odd] = -_channel1[even] * sin( _channel1[odd] ); + } + + // ---- END -------------------------------- + + rdft( _N, -1, _buffer1, _bitshuffle, _trigland ); + overlapadd( _buffer1, _N, _Wsyn, _output, _Nw, _inCount); + + const F mult = 1./_N; + for ( j = 0; j < _D; j++ ) + out[0][j] = _output[j] * mult; + + for ( j = 0; j < _N-_D; j++ ) + _output[j] = _output[j+_D]; + for (; j < _N; j++ ) + _output[j] = 0.; +} + diff --git a/externals/grill/fftease/src/main.cpp b/externals/grill/fftease/src/main.cpp index 1d627cf2..914d1f43 100644 --- a/externals/grill/fftease/src/main.cpp +++ b/externals/grill/fftease/src/main.cpp @@ -3,8 +3,6 @@ FFTease - A set of Live Spectral Processors Originally written by Eric Lyon and Christopher Penrose for the Max/MSP platform -This flext port is based on the jMax port of Christian Klippel - Copyright (c)Thomas Grill (xovo@gmx.net) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. @@ -23,20 +21,18 @@ V lib_setup() post("Originally written by Eric Lyon and Christopher Penrose"); post("for the MAX/MSP platform."); post(""); - post("flext port done by Thomas Grill, (C)2003"); + post("flext port provided by Thomas Grill, (C)2003"); post("-------------------------------------------------------"); post(""); // call the objects' setup routines FLEXT_DSP_SETUP(burrow); - -/* FLEXT_DSP_SETUP(cross); FLEXT_DSP_SETUP(dentist); FLEXT_DSP_SETUP(disarray); FLEXT_DSP_SETUP(drown); FLEXT_DSP_SETUP(ether); - +/* FLEXT_DSP_SETUP(morphine); FLEXT_DSP_SETUP(pvcompand); FLEXT_DSP_SETUP(pvoc); @@ -51,7 +47,12 @@ V lib_setup() */ #if FLEXT_SYS == FLEXT_SYS_MAX -// finder_addclass((C *)"FFTease",(C *)"xxxxx"); + finder_addclass((C *)"FFTease",(C *)"burrow~"); + finder_addclass((C *)"FFTease",(C *)"cross~"); + finder_addclass((C *)"FFTease",(C *)"dentist~"); + finder_addclass((C *)"FFTease",(C *)"disarray~"); + finder_addclass((C *)"FFTease",(C *)"drown~"); + finder_addclass((C *)"FFTease",(C *)"ether~"); #endif } diff --git a/externals/grill/fftease/src/main.h b/externals/grill/fftease/src/main.h index c0fb56f8..6dbddf7e 100644 --- a/externals/grill/fftease/src/main.h +++ b/externals/grill/fftease/src/main.h @@ -3,8 +3,6 @@ FFTease - A set of Live Spectral Processors Originally written by Eric Lyon and Christopher Penrose for the Max/MSP platform -This flext port is based on the jMax port of Christian Klippel - Copyright (c)Thomas Grill (xovo@gmx.net) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution. @@ -16,6 +14,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #define FFTEASE_VERSION "0.0.1" + #define FLEXT_ATTRIBUTES 1 #include <flext.h> @@ -24,6 +23,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #error You need at least flext version 0.4.1 #endif + #include "pv.h" // lazy me |