aboutsummaryrefslogtreecommitdiff
path: root/externals/grill
diff options
context:
space:
mode:
Diffstat (limited to 'externals/grill')
-rw-r--r--externals/grill/fftease/fftease.dsp12
-rw-r--r--externals/grill/fftease/make-files.txt3
-rw-r--r--externals/grill/fftease/src/burrow~.cpp20
-rw-r--r--externals/grill/fftease/src/cross~.cpp23
-rw-r--r--externals/grill/fftease/src/dentist~.cpp6
-rw-r--r--externals/grill/fftease/src/disarray~.cpp31
-rw-r--r--externals/grill/fftease/src/drown~.cpp53
-rw-r--r--externals/grill/fftease/src/ether~.cpp32
-rw-r--r--externals/grill/fftease/src/fftease.cpp42
-rw-r--r--externals/grill/fftease/src/main.cpp6
-rw-r--r--externals/grill/fftease/src/main.h13
-rw-r--r--externals/grill/fftease/src/morphine~.cpp117
-rw-r--r--externals/grill/fftease/src/scrape~.cpp158
-rw-r--r--externals/grill/fftease/src/shapee~.cpp79
14 files changed, 475 insertions, 120 deletions
diff --git a/externals/grill/fftease/fftease.dsp b/externals/grill/fftease/fftease.dsp
index f825d29b..413523ef 100644
--- a/externals/grill/fftease/fftease.dsp
+++ b/externals/grill/fftease/fftease.dsp
@@ -162,6 +162,18 @@ SOURCE=.\src\drown~.cpp
SOURCE=.\src\ether~.cpp
# End Source File
+# Begin Source File
+
+SOURCE=.\src\morphine~.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\scrape~.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\shapee~.cpp
+# End Source File
# End Group
# Begin Group "doc"
diff --git a/externals/grill/fftease/make-files.txt b/externals/grill/fftease/make-files.txt
index 1866faa6..418cd275 100644
--- a/externals/grill/fftease/make-files.txt
+++ b/externals/grill/fftease/make-files.txt
@@ -3,7 +3,8 @@ SRCS= \
convert.c convert_new.c fft4.c fft.c fold.c \
leanconvert.c leanunconvert.c makewindows.c overlapadd.c unconvert.c \
main.cpp fftease.cpp \
- burrow~.cpp cross~.cpp dentist~.cpp disarray~.cpp drown~.cpp ether~.cpp
+ burrow~.cpp cross~.cpp dentist~.cpp disarray~.cpp drown~.cpp ether~.cpp \
+ morphine~.cpp scrape~.cpp shapee~.cpp
HDRS= \
pv.h main.h
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 <stdlib.h>
+
+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 <stdlib.h>
+
+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 <stdlib.h>
+
+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];
+ }
+}