From d9c287d4336721d773c8a4c01588f0b7c8be984d Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Thu, 16 Jan 2003 04:36:48 +0000 Subject: "" svn path=/trunk/; revision=340 --- externals/grill/fftease/src/burrow~.cpp | 20 ++-- externals/grill/fftease/src/cross~.cpp | 23 +++-- externals/grill/fftease/src/dentist~.cpp | 6 +- externals/grill/fftease/src/disarray~.cpp | 31 +++--- externals/grill/fftease/src/drown~.cpp | 53 +++++----- externals/grill/fftease/src/ether~.cpp | 32 +++--- externals/grill/fftease/src/fftease.cpp | 42 ++++---- externals/grill/fftease/src/main.cpp | 6 +- externals/grill/fftease/src/main.h | 13 ++- externals/grill/fftease/src/morphine~.cpp | 117 ++++++++++++++++++++++ externals/grill/fftease/src/scrape~.cpp | 158 ++++++++++++++++++++++++++++++ externals/grill/fftease/src/shapee~.cpp | 79 +++++++++++++++ 12 files changed, 461 insertions(+), 119 deletions(-) create mode 100644 externals/grill/fftease/src/morphine~.cpp create mode 100644 externals/grill/fftease/src/scrape~.cpp create mode 100644 externals/grill/fftease/src/shapee~.cpp (limited to 'externals/grill/fftease/src') diff --git a/externals/grill/fftease/src/burrow~.cpp b/externals/grill/fftease/src/burrow~.cpp index 0bb3208f..f299ce3f 100644 --- a/externals/grill/fftease/src/burrow~.cpp +++ b/externals/grill/fftease/src/burrow~.cpp @@ -55,7 +55,7 @@ V burrow::setup(t_classid c) burrow::burrow(I argc,const t_atom *argv): - fftease(4,true,true,true), + fftease(4,F_STEREO|F_WINDOW|F_BITSHUFFLE), _thresh_dB(-30),_mult_dB(-18), _invert(false) { @@ -91,7 +91,7 @@ burrow::burrow(I argc,const t_atom *argv): V burrow::Transform(I _N2,S *const *in) { for (I i = 0; i <= _N2; i++ ) { - const I even = i<<1,odd = even+1; + const I even = i*2,odd = even+1; /* convert to polar coordinates from complex values */ register F a,b; @@ -99,23 +99,21 @@ V burrow::Transform(I _N2,S *const *in) 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 ); + F amp1 = hypot( a, b ); + F phase1 = -atan2( b, a ); a = ( i == _N2 ? _buffer2[1] : _buffer2[even] ); b = ( i == 0 || i == _N2 ? 0. : _buffer2[odd] ); - _channel2[even] = hypot( a, b ); + F amp2 = hypot( a, b ); /* use simple threshold from second signal to trigger filtering */ - if (_invert?(_channel2[even] < _threshold):(_channel2[even] > _threshold) ) - _channel1[even] *= _multiplier; + if (_invert?(amp2 < _threshold):(amp2 > _threshold) ) + amp1 *= _multiplier; /* 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] ); + _buffer1[even] = amp1 * cos(phase1); + if ( i != _N2 ) _buffer1[odd] = -amp1 * sin(phase1); } } diff --git a/externals/grill/fftease/src/cross~.cpp b/externals/grill/fftease/src/cross~.cpp index 728e868a..8fbc2c22 100644 --- a/externals/grill/fftease/src/cross~.cpp +++ b/externals/grill/fftease/src/cross~.cpp @@ -29,7 +29,7 @@ FLEXT_LIB_DSP_V("fftease, cross~",cross) cross::cross(I argc,const t_atom *argv): - fftease(2,true,true,true) + fftease(2,F_STEREO|F_WINDOW|F_BITSHUFFLE) { AddInSignal("Messages and driver signal"); AddInSignal("Filter signal"); @@ -40,28 +40,27 @@ cross::cross(I argc,const t_atom *argv): V cross::Transform(I _N2,S *const *in) { // TG: filled only once per signal vector!! - float threshie = *in[0]; + const F threshie = *in[0]; for (I i = 0; i <= _N2; i++ ) { - const I even = i<<1,odd = even+1; + const I even = i*2,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 ) ; + + F amp1 = 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); + F amp2 = hypot( a, b ); + F phase2 = -atan2( b, a ); - _channel1[odd] = -atan2( b, a ); - _buffer1[even] = _channel1[even] * cos( _channel1[odd] ); + // modulate amp2 with amp1 (if over threshold) + if( amp1 > threshie ) amp2 *= amp1; - if ( i != _N2 ) - _buffer1[odd] = -_channel1[even] * sin( _channel1[odd] ); + _buffer1[even] = amp2 * cos( phase2 ); + if ( i != _N2 ) _buffer1[odd] = -amp2 * sin( phase2 ); } } diff --git a/externals/grill/fftease/src/dentist~.cpp b/externals/grill/fftease/src/dentist~.cpp index 375006b9..7c1206ee 100644 --- a/externals/grill/fftease/src/dentist~.cpp +++ b/externals/grill/fftease/src/dentist~.cpp @@ -63,7 +63,7 @@ V dentist::setup(t_classid c) dentist::dentist(I argc,const t_atom *argv): - fftease(4,false,true,true), + fftease(4,F_WINDOW|F_BITSHUFFLE|F_CONVERT), _knee(500),_tooth_count(10) { /* parse and set object's options given */ @@ -127,13 +127,9 @@ V dentist::Set() V dentist::Transform(I _N2,S *const *in) { - leanconvert( _buffer1, _channel1, _N2 ); - for(I i = 0; i < _N2 ; i++){ if( !_bin_selection[i] ) _channel1[i*2] = 0; } - - leanunconvert( _channel1, _buffer1, _N2 ); } diff --git a/externals/grill/fftease/src/disarray~.cpp b/externals/grill/fftease/src/disarray~.cpp index 8019fcdc..c45d6583 100644 --- a/externals/grill/fftease/src/disarray~.cpp +++ b/externals/grill/fftease/src/disarray~.cpp @@ -24,9 +24,6 @@ protected: virtual V Transform(I _N2,S *const *in); - I _inCount,_nmult; - - // ----------------------------- BL _qual; I _shuffle_count,_max_bin; @@ -62,7 +59,7 @@ V disarray::setup(t_classid c) disarray::disarray(I argc,const t_atom *argv): - fftease(2,false,true,true), + fftease(2,F_BITSHUFFLE|F_CONVERT), _freq(1300),_qual(false),_shuffle_count(20) { /* parse and set object's options given */ @@ -86,7 +83,7 @@ disarray::disarray(I argc,const t_atom *argv): } _mult = _qual?4:2; - _window = _qual; + if(_qual) _flags |= F_WINDOW; AddInSignal("Messages and input signal"); AddOutSignal("Transformed signal"); @@ -125,7 +122,7 @@ V disarray::ms_freq(F f) { _freq = f; // store original - const F funda = Samplerate()/(2*_nmult*Blocksize()); + const F funda = Samplerate()/(2*Mult()*Blocksize()); // TG: This is a different, but steady correction than in original fftease if( f < funda ) f = funda; @@ -135,17 +132,13 @@ V disarray::ms_freq(F f) for(F curfreq = 0; curfreq < f; curfreq += funda) ++_max_bin; } +inline V swap(F &a,F &b) { F t = a; a = b; b = t; } +inline V swap(I &a,I &b) { I t = a; a = b; b = t; } + V disarray::Transform(I _N2,S *const *in) { - leanconvert( _buffer1, _channel1, _N2 ); - - for(I 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 ); + for(I i = 0; i < _shuffle_count ; i++) + swap(_channel1[ _shuffle_in[i] * 2 ],_channel1[ _shuffle_out[i] * 2]); } @@ -158,11 +151,9 @@ V disarray::reset_shuffle() _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; + I p1 = _shuffle_out[ rand()%_max_bin ]; + I p2 = _shuffle_out[ rand()%_max_bin ]; + swap(_shuffle_out[ p1 ],_shuffle_out[ p2 ]); } } diff --git a/externals/grill/fftease/src/drown~.cpp b/externals/grill/fftease/src/drown~.cpp index 336f9c8e..2d6b46ba 100644 --- a/externals/grill/fftease/src/drown~.cpp +++ b/externals/grill/fftease/src/drown~.cpp @@ -21,7 +21,6 @@ public: drown(I argc,const t_atom *argv); protected: - virtual V Transform(I n,S *const *in); }; @@ -29,7 +28,7 @@ FLEXT_LIB_DSP_V("fftease, drown~",drown) drown::drown(I argc,const t_atom *argv): - fftease(4,false,true,false) + fftease(4,F_WINDOW) { AddInSignal("Messages and input signal"); AddInSignal("Threshold generator signal"); @@ -38,38 +37,32 @@ drown::drown(I argc,const t_atom *argv): } -/* 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::Transform(I _N2,S *const *in) { // only first value of the signal vectors - const F thresh = in[1][0],mult = in[2][0]; + const F thresh = in[0][0],mult = in[1][0]; + + // nudist helper function is integrated + + for (I i = 0; i <= _N2; i++ ) { + const I real = i*2,imag = real+1; + F amp,phase; + + // convert to amp and phase + const F a = ( i == _N2 ? _buffer1[1] : _buffer1[real] ); + const F b = ( i == 0 || i == _N2 ? 0. : _buffer1[imag] ); + + amp = hypot( a, b ); + // make up low amplitude bins + if(amp < thresh) amp *= mult; + + phase = -atan2( b, a ); + - nudist( _buffer1, _channel1, thresh, mult, _N2 ); + // convert back to real and imag + _buffer1[real] = amp * cos( phase ); + if (i != _N2) _buffer1[imag] = -amp * sin( phase ); + } } diff --git a/externals/grill/fftease/src/ether~.cpp b/externals/grill/fftease/src/ether~.cpp index e04efaec..836349f3 100644 --- a/externals/grill/fftease/src/ether~.cpp +++ b/externals/grill/fftease/src/ether~.cpp @@ -46,7 +46,7 @@ V ether::setup(t_classid c) ether::ether(I argc,const t_atom *argv): - fftease(2,true,true,true), + fftease(2,F_STEREO|F_BITSHUFFLE), _qual(false),_threshMult(0),_invert(false) { /* parse and set object's options given */ @@ -58,7 +58,7 @@ ether::ether(I argc,const t_atom *argv): } _mult = _qual?4:2; - _window = _qual; + if(_qual) _flags |= F_WINDOW; AddInSignal("Messages and input signal"); AddInSignal("Reference signal"); @@ -72,36 +72,32 @@ V ether::Transform(I _N2,S *const *in) if (threshMult == 0. ) threshMult = 1; for (I i = 0; i <= _N2; i++ ) { - int even = i<<1,odd = even + 1; + const I even = i*2,odd = even + 1; - /* convert to polar coordinates from complex values */ + // 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 ); + F amp1 = hypot( a, b ); + F phase1 = -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 ); + F amp2 = hypot( a, b ); + F phase2 = -atan2( b, a ); - /* use simple threshold for inverse compositing */ + // use simple threshold for inverse compositing - if(_invert?(_channel1[even] > _channel2[even]*threshMult):(_channel1[even] < _channel2[even]*threshMult) ) - _channel1[even] = _channel2[even]; + if(_invert?(amp1 > amp2*threshMult):(amp1 < amp2*threshMult) ) amp1 = amp2; + if (phase1 == 0. ) phase1 = phase2; - 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] ); + // convert back to complex form, read for the inverse fft + _buffer1[even] = amp1 * cos(phase1); + if(i != _N2) _buffer1[odd] = -amp1 * sin(phase1); } } diff --git a/externals/grill/fftease/src/fftease.cpp b/externals/grill/fftease/src/fftease.cpp index 9e59faa1..d29ecf27 100644 --- a/externals/grill/fftease/src/fftease.cpp +++ b/externals/grill/fftease/src/fftease.cpp @@ -12,8 +12,8 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "main.h" -fftease::fftease(I mult,BL stereo,BL window,BL bitshuf): - _mult(mult),_stereo(stereo),_window(window),_bitshuf(bitshuf), +fftease::fftease(I mult,I flags): + _mult(mult),_flags(flags), _inCount(0), blsz(0),smprt(0) {} @@ -54,7 +54,7 @@ V fftease::m_signal(I n,S *const *in,S *const *out) /* fill our retaining buffers */ _inCount += _D; - if(_stereo) { + if(_flags&F_STEREO) { for(i = 0; i < _N-_D ; i++ ) { _input1[i] = _input1[i+_D]; _input2[i] = _input2[i+_D]; @@ -73,28 +73,37 @@ V fftease::m_signal(I n,S *const *in,S *const *out) /* apply hamming window and fold our window buffer into the fft buffer */ fold( _input1, _Wanal, _Nw, _buffer1, _N, _inCount ); - if(_stereo) fold( _input2, _Wanal, _Nw, _buffer2, _N, _inCount ); + if(_flags&F_STEREO) fold( _input2, _Wanal, _Nw, _buffer2, _N, _inCount ); /* do an fft */ - if(_bitshuf) { + if(_flags&F_BITSHUFFLE) { rdft( _N, 1, _buffer1, _bitshuffle, _trigland ); - if(_stereo) rdft( _N, 1, _buffer2, _bitshuffle, _trigland ); + if(_flags&F_STEREO) rdft( _N, 1, _buffer2, _bitshuffle, _trigland ); } else { rfft( _buffer1, _N2, 1); - if(_stereo) rfft( _buffer2, _N2,1); + if(_flags&F_STEREO) rfft( _buffer2, _N2,1); } + if(_flags&F_BITSHUFFLE) { + leanconvert( _buffer1, _channel1, _N2 ); + if(_flags&F_STEREO) leanconvert( _buffer2, _channel2, _N2 ); + } // ---- BEGIN -------------------------------- - Transform(_N2,in+(_stereo?1:2)); + Transform(_N2,in+((_flags&F_STEREO)?1:2)); // ---- END -------------------------------- + if(_flags&F_CONVERT) { + leanunconvert( _channel1, _buffer1, _N2 ); + if(_flags&F_STEREO) leanunconvert( _channel2, _buffer2, _N2 ); + } + /* do an inverse fft */ - if(_bitshuf) + if(_flags&F_BITSHUFFLE) rdft( _N, -1, _buffer1, _bitshuffle, _trigland ); else rfft( _buffer1, _N2, 0); @@ -124,15 +133,15 @@ void fftease::Set() /* assign memory to the buffers */ _input1 = new F[_Nw]; _buffer1 = new F[_N]; - _channel1 = new F[_N+2]; - if(_stereo) { + if(_flags&F_CONVERT) _channel1 = new F[_N+2]; + if(_flags&F_STEREO) { _input2 = new F[_Nw]; _buffer2 = new F[_N]; - _channel2 = new F[_N+2]; + if(_flags&F_CONVERT) _channel2 = new F[_N+2]; } _output = new F[_Nw]; - if(_bitshuf) { + if(_flags&F_BITSHUFFLE) { _bitshuffle = new I[_N*2]; _trigland = new F[_N*2]; init_rdft( _N, _bitshuffle, _trigland); @@ -141,7 +150,7 @@ void fftease::Set() _Hwin = new F[_Nw]; _Wanal = new F[_Nw]; _Wsyn = new F[_Nw]; - if(_window) + if(_flags&F_WINDOW) makewindows( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0); else makehanning( _Hwin, _Wanal, _Wsyn, _Nw, _N, _D, 0,0); @@ -164,14 +173,14 @@ void fftease::Delete() if(_input1) delete[] _input1; if(_buffer1) delete[] _buffer1; if(_channel1) delete[] _channel1; - if(_stereo) { + if(_flags&F_STEREO) { if(_input2) delete[] _input2; if(_buffer2) delete[] _buffer2; if(_channel2) delete[] _channel2; } if(_output) delete[] _output; - if(_bitshuf) { + if(_flags&F_BITSHUFFLE) { if(_bitshuffle) delete[] _bitshuffle; if(_trigland) delete[] _trigland; } @@ -182,4 +191,3 @@ void fftease::Delete() } - diff --git a/externals/grill/fftease/src/main.cpp b/externals/grill/fftease/src/main.cpp index 914d1f43..36a02533 100644 --- a/externals/grill/fftease/src/main.cpp +++ b/externals/grill/fftease/src/main.cpp @@ -32,12 +32,12 @@ V lib_setup() FLEXT_DSP_SETUP(disarray); FLEXT_DSP_SETUP(drown); FLEXT_DSP_SETUP(ether); -/* FLEXT_DSP_SETUP(morphine); - FLEXT_DSP_SETUP(pvcompand); - FLEXT_DSP_SETUP(pvoc); FLEXT_DSP_SETUP(scrape); FLEXT_DSP_SETUP(shapee); +/* + FLEXT_DSP_SETUP(pvcompand); + FLEXT_DSP_SETUP(pvoc); FLEXT_DSP_SETUP(swinger); FLEXT_DSP_SETUP(taint); diff --git a/externals/grill/fftease/src/main.h b/externals/grill/fftease/src/main.h index d9746c71..620cca5d 100644 --- a/externals/grill/fftease/src/main.h +++ b/externals/grill/fftease/src/main.h @@ -44,7 +44,7 @@ class fftease: FLEXT_HEADER_S(fftease,flext_dsp,setup) public: - fftease(I mult,BL stereo,BL window,BL bitshuf); + fftease(I mult,I flags); virtual ~fftease(); protected: @@ -60,6 +60,7 @@ protected: virtual V Delete(); virtual V Transform(I _N2,S *const *in) = 0; + I Mult() const { return _mult; } F *_input1,*_input2; @@ -72,8 +73,14 @@ protected: I _inCount; - I _mult; - BL _stereo,_window,_bitshuf; + enum { + F_STEREO = 0x01, + F_WINDOW = 0x02, + F_BITSHUFFLE = 0x04, + F_CONVERT = 0x08,F_CRES = 0x10, + }; + + I _mult,_flags; private: I blsz; diff --git a/externals/grill/fftease/src/morphine~.cpp b/externals/grill/fftease/src/morphine~.cpp new file mode 100644 index 00000000..1febe853 --- /dev/null +++ b/externals/grill/fftease/src/morphine~.cpp @@ -0,0 +1,117 @@ +/* + +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 + +class morphine: + public fftease +{ + FLEXT_HEADER_S(morphine,fftease,setup) + +public: + morphine(I argc,const t_atom *argv); + +protected: + + virtual V Transform(I n,S *const *in); + + F _index; + + struct pickme { I bin; F value; }; + static I sortpicks( const V *a, const V *b ); + + pickme *_picks; + +private: + virtual V Set(); + virtual V Clear(); + virtual V Delete(); + + static V setup(t_classid c); + + FLEXT_ATTRVAR_F(_index) +}; + +FLEXT_LIB_DSP_V("fftease, morphine~",morphine) + + +V morphine::setup(t_classid c) +{ + FLEXT_CADDATTR_VAR1(c,"index",_index); +} + + +morphine::morphine(I argc,const t_atom *argv): + fftease(4,F_STEREO|F_WINDOW|F_BITSHUFFLE|F_CONVERT), + _index(1) +{ + /* parse and set object's options given */ + if(argc >= 1) { + if(CanbeFloat(argv[0])) + _index = GetAFloat(argv[0]); + else + post("%s - Index must be a float value - set to %f",thisName(),_index); + } + + AddInSignal("Messages and input signal 1"); + AddInSignal("Input signal 2"); + AddOutSignal("Transformed signal"); +} + +V morphine::Clear() +{ + fftease::Clear(); + _picks = NULL; +} + +V morphine::Delete() +{ + fftease::Delete(); + if(_picks) delete[] _picks; +} + +V morphine::Set() +{ + fftease::Set(); + + const I _N2 = Blocksize()*Mult()/2; + _picks = new pickme[_N2+1]; +} + +I morphine::sortpicks( const void *a, const void *b ) +{ + if ( ((pickme *)a)->value > ((pickme *) b)->value ) return 1; + if ( ((pickme *) a)->value < ((pickme *) b)->value ) return -1; + return 0; +} + +V morphine::Transform(I _N2,S *const *in) +{ + I i; + for ( i = 0; i <= _N2; i++ ) { + // find amplitude differences between home and visitors + _picks[i].value = fabs( _channel1[i*2] - _channel2[i*2]); + _picks[i].bin = i; + } + + // sort our differences in ascending order + qsort( _picks, _N2+1, sizeof(pickme), sortpicks ); + + const I morphindex = _index*(_N2+1)+.5; + // choose the bins that are least different first + for ( i=0; i <= morphindex; i++ ) { + const I even = _picks[i].bin*2,odd = even + 1; + _channel1[even] = _channel2[even]; + _channel1[odd] = _channel2[odd]; + } +} + diff --git a/externals/grill/fftease/src/scrape~.cpp b/externals/grill/fftease/src/scrape~.cpp new file mode 100644 index 00000000..6d63ed6b --- /dev/null +++ b/externals/grill/fftease/src/scrape~.cpp @@ -0,0 +1,158 @@ +/* + +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 + +class scrape: + public fftease +{ + FLEXT_HEADER_S(scrape,fftease,setup) + +public: + scrape(I argc,const t_atom *argv); + +protected: + + virtual V Transform(I n,S *const *in); + + F _thresh1,_thresh2; + F _knee,_cutoff; + F *_threshfunc; + + V UpdThrFun(); + +private: + virtual V Set(); + virtual V Clear(); + virtual V Delete(); + + static V setup(t_classid c); + + V ms_knee(F knee) { _knee = knee; UpdThrFun(); } + V ms_cutoff(F cutoff) { _cutoff = cutoff; UpdThrFun(); } + + FLEXT_ATTRGET_F(_knee) + FLEXT_CALLSET_F(ms_knee) + FLEXT_ATTRGET_F(_cutoff) + FLEXT_CALLSET_F(ms_cutoff) +}; + +FLEXT_LIB_DSP_V("fftease, scrape~",scrape) + + +V scrape::setup(t_classid c) +{ + FLEXT_CADDATTR_VAR(c,"knee",_knee,ms_knee); + FLEXT_CADDATTR_VAR(c,"cutoff",_cutoff,ms_cutoff); +} + + +scrape::scrape(I argc,const t_atom *argv): + fftease(4,F_WINDOW|F_BITSHUFFLE|F_CRES), + _thresh1(.0001),_thresh2(.09), + _knee(1000),_cutoff(4000) + +{ + /* 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 %f",thisName(),_knee); + } + if(argc >= 2) { + if(CanbeFloat(argv[0])) { + F c = GetAFloat(argv[0]); + if(c > 0) _cutoff = c; + else + post("%s - Cutoff must be > 0 - set to %f",thisName(),_cutoff); + } + else + post("%s - Cutoff must be a float value - set to %f",thisName(),_cutoff); + } + + AddInSignal("Messages and input signal"); + AddInSignal("Multiplier signal"); + AddOutSignal("Transformed signal"); +} + +V scrape::Clear() +{ + fftease::Clear(); + _threshfunc = NULL; +} + +V scrape::Delete() +{ + fftease::Delete(); + if(_threshfunc) delete[] _threshfunc; +} + +V scrape::Set() +{ + fftease::Set(); + + const I _N2 = Blocksize()*Mult()/2; + _threshfunc = new F[_N2]; + UpdThrFun(); +} + +V scrape::UpdThrFun() +{ + const I _N = Blocksize()*Mult(),_N2 = _N/2; + const F funda = Samplerate()/(_N*2); + + F curfreq = funda; + for(I i = 0; i < _N2; i++ ) { + if( curfreq < _knee ) + _threshfunc[i] = 0; + else if( curfreq >= _knee && curfreq < _cutoff ) { + F m = (_knee - curfreq) / (_cutoff - _knee) ; + _threshfunc[i] = (1-m) * _thresh1 + m * _thresh2 ; + } else + _threshfunc[i] = _thresh2; + + curfreq += funda ; + } +} + + +V scrape::Transform(I _N2,S *const *in) +{ + const F fmult = *in[0]; + + I i; + F maxamp = 1.; + + for( i = 0; i <= _N2; i++ ) { + const I amp = i*2; + if( maxamp < _channel1[amp] ) maxamp = _channel1[amp]; + } + + for ( i = 0; i <= _N2; i++ ) { + const I real = i*2,imag = real+1; + + F a = ( i == _N2 ? _buffer1[1] : _buffer1[real] ); + F b = ( i == 0 || i == _N2 ? 0. : _buffer1[imag] ); + + _channel1[real] = hypot( a, b ); + if ( _channel1[real] < _threshfunc[i] * maxamp ) _channel1[real] *= fmult; + _channel1[imag] = -atan2( b, a ); + } + + for ( i = 0; i <= _N2; i++ ) { + const I real = i*2, imag = real+1; + _buffer1[real] = _channel1[real] * cos( _channel1[imag] ); + if( i != _N2 ) _buffer1[imag] = -_channel1[real] * sin( _channel1[imag] ); + } +} + diff --git a/externals/grill/fftease/src/shapee~.cpp b/externals/grill/fftease/src/shapee~.cpp new file mode 100644 index 00000000..2fa0268c --- /dev/null +++ b/externals/grill/fftease/src/shapee~.cpp @@ -0,0 +1,79 @@ +/* + +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 + +class shapee: + public fftease +{ + FLEXT_HEADER(shapee,fftease) + +public: + shapee(I argc,const t_atom *argv); + +protected: + + virtual V Transform(I n,S *const *in); + + BL _qual; +}; + +FLEXT_LIB_DSP_V("fftease, shapee~",shapee) + + +shapee::shapee(I argc,const t_atom *argv): + fftease(2,F_STEREO|F_BITSHUFFLE|F_CONVERT), + _qual(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); + } + + if(_qual) + _mult = 4,_flags |= F_WINDOW; + else + _mult = 2; + + AddInSignal("Messages and frequency reference signal"); + AddInSignal("Amplitude reference signal"); + AddOutSignal("Transformed signal"); +} + + +V shapee::Transform(I _N2,S *const *in) +{ + // lets just shape the entire signal in groups of three + + const _N = _N2*2; + I i; + for ( i=2; i < _N+2; i += 6 ) { + F lowerMult = _channel1[i-2] / _channel1[i]; + F upperMult = _channel1[i+2] / _channel1[i]; + F newCenter = ( _channel2[i-2]+_channel2[i]+_channel2[i+2] ) / (upperMult + lowerMult + 1); + + _channel2[i-2] = lowerMult * newCenter; + _channel2[i+2] = upperMult * newCenter; + _channel2[i] = newCenter; + } + + for ( i=0; i < _N; i+=2 ) { + _channel1[i] = _channel2[i]; + if ( _channel1[i] == 0. ) + _channel1[i+1] = 0.; + else if( _channel1[i+1] == 0. ) + _channel1[i+1] = _channel2[i+1]; + } +} -- cgit v1.2.1