/* 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); inline V ms_knee(F knee) { _knee = knee; UpdThrFun(); } inline V ms_cutoff(F cutoff) { _cutoff = cutoff; UpdThrFun(); } inline V ms_thresh1(F thr) { _thresh1 = thr; UpdThrFun(); } inline V ms_thresh2(F thr) { _thresh2 = thr; UpdThrFun(); } FLEXT_ATTRGET_F(_knee) FLEXT_CALLSET_F(ms_knee) FLEXT_ATTRGET_F(_cutoff) FLEXT_CALLSET_F(ms_cutoff) FLEXT_ATTRGET_F(_thresh1) FLEXT_CALLSET_F(ms_thresh1) FLEXT_ATTRGET_F(_thresh2) FLEXT_CALLSET_F(ms_thresh2) }; 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); FLEXT_CADDATTR_VAR(c,"thresh1",_thresh1,ms_thresh1); FLEXT_CADDATTR_VAR(c,"thresh2",_thresh2,ms_thresh2); } scrape::scrape(I argc,const t_atom *argv): fftease(4,F_BALANCED|F_BITSHUFFLE), _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[1])) { F c = GetAFloat(argv[1]); 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() { _threshfunc = NULL; fftease::Clear(); } V scrape::Delete() { fftease::Delete(); if(_threshfunc) delete[] _threshfunc; } V scrape::Set() { fftease::Set(); _threshfunc = new F[get_N()/2]; UpdThrFun(); } V scrape::UpdThrFun() { const I _N2 = get_N()/2; const F funda = get_Fund(); F curfreq = funda; for(I i = 0; i < _N2; i++ ) { if( curfreq < _knee ) _threshfunc[i] = 0; else if( curfreq >= _knee && curfreq < _cutoff ) { const F m = (_knee - curfreq) / (_cutoff - _knee) ; _threshfunc[i] = (1-m) * _thresh1 + m * _thresh2 ; } else _threshfunc[i] = _thresh2; curfreq += funda ; } } /*! \brief Do the spectral transformation \remark maxamp is calculated later than in the original FFTease scrape~ object */ V scrape::Transform(I _N,S *const *in) { const F fmult = *in[0]; const F *thrf = _threshfunc; I i; F maxamp = 1.; for( i = 0; i <= _N; i += 2 ) if(maxamp < _channel1[i]) maxamp = _channel1[i]; for( i = 0; i <= _N; i += 2 ) if(_channel1[i] < *(thrf++) * maxamp) _channel1[i] *= fmult; }