aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/fftease/src
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2003-01-17 04:37:14 +0000
committerThomas Grill <xovo@users.sourceforge.net>2003-01-17 04:37:14 +0000
commit478eeca99ee6f5bad3063700fbcc9d8913c770ae (patch)
treebe9b6dff36c03985fe7ee6a9ba15be4427b3d035 /externals/grill/fftease/src
parent0623a36babf06fe897bbb59244c7d4f010d46b9c (diff)
""
svn path=/trunk/; revision=342
Diffstat (limited to 'externals/grill/fftease/src')
-rw-r--r--externals/grill/fftease/src/fftease.cpp14
-rw-r--r--externals/grill/fftease/src/main.cpp25
-rw-r--r--externals/grill/fftease/src/main.h2
-rw-r--r--externals/grill/fftease/src/scrape~.cpp38
-rw-r--r--externals/grill/fftease/src/shapee~.cpp2
-rw-r--r--externals/grill/fftease/src/swinger~.cpp62
-rw-r--r--externals/grill/fftease/src/taint~.cpp97
-rw-r--r--externals/grill/fftease/src/thresher~.cpp125
-rw-r--r--externals/grill/fftease/src/vacancy~.cpp125
-rw-r--r--externals/grill/fftease/src/xsyn~.cpp52
10 files changed, 503 insertions, 39 deletions
diff --git a/externals/grill/fftease/src/fftease.cpp b/externals/grill/fftease/src/fftease.cpp
index d29ecf27..4944e839 100644
--- a/externals/grill/fftease/src/fftease.cpp
+++ b/externals/grill/fftease/src/fftease.cpp
@@ -22,9 +22,8 @@ fftease::~fftease() {}
BL fftease::Init()
{
- BL ret = flext_dsp::Init();
Clear();
- return ret;
+ return flext_dsp::Init();
}
V fftease::Exit()
@@ -71,6 +70,13 @@ V fftease::m_signal(I n,S *const *in,S *const *out)
_input1[i] = in[0][j];
}
+ _rms = 0.;
+ if(_flags&F_RMS) {
+ for ( i=0; i < _Nw; i++ )
+ _rms += _input1[i] * _input1[i];
+ _rms = sqrt(_rms / _Nw);
+ }
+
/* apply hamming window and fold our window buffer into the fft buffer */
fold( _input1, _Wanal, _Nw, _buffer1, _N, _inCount );
if(_flags&F_STEREO) fold( _input2, _Wanal, _Nw, _buffer2, _N, _inCount );
@@ -133,11 +139,11 @@ void fftease::Set()
/* assign memory to the buffers */
_input1 = new F[_Nw];
_buffer1 = new F[_N];
- if(_flags&F_CONVERT) _channel1 = new F[_N+2];
+ if(_flags&(F_CONVERT|F_CRES)) _channel1 = new F[_N+2];
if(_flags&F_STEREO) {
_input2 = new F[_Nw];
_buffer2 = new F[_N];
- if(_flags&F_CONVERT) _channel2 = new F[_N+2];
+ if(_flags&(F_CONVERT|F_CRES)) _channel2 = new F[_N+2];
}
_output = new F[_Nw];
diff --git a/externals/grill/fftease/src/main.cpp b/externals/grill/fftease/src/main.cpp
index 36a02533..5dfdbee2 100644
--- a/externals/grill/fftease/src/main.cpp
+++ b/externals/grill/fftease/src/main.cpp
@@ -16,13 +16,12 @@ WARRANTIES, see the file, "license.txt," in this distribution.
V lib_setup()
{
post("");
- post("-------------------------------------------------------");
+ post("-------------------------------------------------------------------");
post("FFTease - A set of Live Spectral Processors");
- post("Originally written by Eric Lyon and Christopher Penrose");
- post("for the MAX/MSP platform.");
+ post("Originally written by Eric Lyon and Christopher Penrose for MAX/MSP");
post("");
- post("flext port provided by Thomas Grill, (C)2003");
- post("-------------------------------------------------------");
+ post("flext port (version " FFTEASE_VERSION ") provided by Thomas Grill, (C)2003");
+ post("-------------------------------------------------------------------");
post("");
// call the objects' setup routines
@@ -35,15 +34,15 @@ V lib_setup()
FLEXT_DSP_SETUP(morphine);
FLEXT_DSP_SETUP(scrape);
FLEXT_DSP_SETUP(shapee);
-/*
- FLEXT_DSP_SETUP(pvcompand);
- FLEXT_DSP_SETUP(pvoc);
-
FLEXT_DSP_SETUP(swinger);
FLEXT_DSP_SETUP(taint);
FLEXT_DSP_SETUP(thresher);
FLEXT_DSP_SETUP(vacancy);
FLEXT_DSP_SETUP(xsyn);
+/*
+ FLEXT_DSP_SETUP(pvcompand);
+ FLEXT_DSP_SETUP(pvoc);
+
*/
#if FLEXT_SYS == FLEXT_SYS_MAX
@@ -53,6 +52,14 @@ V lib_setup()
finder_addclass((C *)"FFTease",(C *)"disarray~");
finder_addclass((C *)"FFTease",(C *)"drown~");
finder_addclass((C *)"FFTease",(C *)"ether~");
+ finder_addclass((C *)"FFTease",(C *)"morphine~");
+ finder_addclass((C *)"FFTease",(C *)"scrape~");
+ finder_addclass((C *)"FFTease",(C *)"shapee~");
+ finder_addclass((C *)"FFTease",(C *)"swinger~");
+ finder_addclass((C *)"FFTease",(C *)"taint~");
+ finder_addclass((C *)"FFTease",(C *)"thresher~");
+ finder_addclass((C *)"FFTease",(C *)"vacancy~");
+ finder_addclass((C *)"FFTease",(C *)"xsyn~");
#endif
}
diff --git a/externals/grill/fftease/src/main.h b/externals/grill/fftease/src/main.h
index 620cca5d..aeaea3e4 100644
--- a/externals/grill/fftease/src/main.h
+++ b/externals/grill/fftease/src/main.h
@@ -78,9 +78,11 @@ protected:
F_WINDOW = 0x02,
F_BITSHUFFLE = 0x04,
F_CONVERT = 0x08,F_CRES = 0x10,
+ F_RMS = 0x20
};
I _mult,_flags;
+ F _rms;
private:
I blsz;
diff --git a/externals/grill/fftease/src/scrape~.cpp b/externals/grill/fftease/src/scrape~.cpp
index 6d63ed6b..9aa0245f 100644
--- a/externals/grill/fftease/src/scrape~.cpp
+++ b/externals/grill/fftease/src/scrape~.cpp
@@ -37,8 +37,8 @@ private:
static V setup(t_classid c);
- V ms_knee(F knee) { _knee = knee; UpdThrFun(); }
- V ms_cutoff(F cutoff) { _cutoff = cutoff; UpdThrFun(); }
+ inline V ms_knee(F knee) { _knee = knee; UpdThrFun(); }
+ inline V ms_cutoff(F cutoff) { _cutoff = cutoff; UpdThrFun(); }
FLEXT_ATTRGET_F(_knee)
FLEXT_CALLSET_F(ms_knee)
@@ -57,7 +57,7 @@ V scrape::setup(t_classid c)
scrape::scrape(I argc,const t_atom *argv):
- fftease(4,F_WINDOW|F_BITSHUFFLE|F_CRES),
+ fftease(4,F_WINDOW|F_BITSHUFFLE|F_CONVERT),
_thresh1(.0001),_thresh2(.09),
_knee(1000),_cutoff(4000)
@@ -116,7 +116,7 @@ V scrape::UpdThrFun()
if( curfreq < _knee )
_threshfunc[i] = 0;
else if( curfreq >= _knee && curfreq < _cutoff ) {
- F m = (_knee - curfreq) / (_cutoff - _knee) ;
+ const F m = (_knee - curfreq) / (_cutoff - _knee) ;
_threshfunc[i] = (1-m) * _thresh1 + m * _thresh2 ;
} else
_threshfunc[i] = _thresh2;
@@ -125,34 +125,22 @@ V scrape::UpdThrFun()
}
}
+/*! \brief Do the spectral transformation
+ \remark maxamp is calculated later than in the original FFTease scrape~ object
+*/
V scrape::Transform(I _N2,S *const *in)
{
const F fmult = *in[0];
I i;
F maxamp = 1.;
+ for( i = 0; i <= _N2; i++ )
+ if(maxamp < _channel1[i*2])
+ maxamp = _channel1[i*2];
- 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] );
- }
+ for( i = 0; i <= _N2; i++ )
+ if(_channel1[i*2] < _threshfunc[i] * maxamp)
+ _channel1[i*2] *= fmult;
}
diff --git a/externals/grill/fftease/src/shapee~.cpp b/externals/grill/fftease/src/shapee~.cpp
index 2fa0268c..e6c0f3f7 100644
--- a/externals/grill/fftease/src/shapee~.cpp
+++ b/externals/grill/fftease/src/shapee~.cpp
@@ -57,7 +57,7 @@ V shapee::Transform(I _N2,S *const *in)
{
// lets just shape the entire signal in groups of three
- const _N = _N2*2;
+ const I _N = _N2*2;
I i;
for ( i=2; i < _N+2; i += 6 ) {
F lowerMult = _channel1[i-2] / _channel1[i];
diff --git a/externals/grill/fftease/src/swinger~.cpp b/externals/grill/fftease/src/swinger~.cpp
new file mode 100644
index 00000000..39fbd9a1
--- /dev/null
+++ b/externals/grill/fftease/src/swinger~.cpp
@@ -0,0 +1,62 @@
+/*
+
+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>
+
+
+// add quality switch
+
+class swinger:
+ public fftease
+{
+ FLEXT_HEADER(swinger,fftease)
+
+public:
+ swinger();
+
+protected:
+
+ virtual V Transform(I n,S *const *in);
+};
+
+FLEXT_LIB_DSP("fftease, swinger~",swinger)
+
+
+swinger::swinger():
+ fftease(2,F_STEREO|F_BITSHUFFLE)
+{
+ AddInSignal("Messages and input signal");
+ AddInSignal("Signal to supply phase information");
+ AddOutSignal("Transformed signal");
+}
+
+
+V swinger::Transform(I _N2,S *const *in)
+{
+ for (I i = 0; i <= _N2; i++ ) {
+ const I even = i*2,odd = even+1;
+
+ // convert to polar coordinates from complex values
+ // replace signal one's phases with those of signal two
+ const F a1 = ( i == _N2 ? _buffer1[1] : _buffer1[even] );
+ const F b1 = ( i == 0 || i == _N2 ? 0. : _buffer1[odd] );
+ const F amp = hypot( a1, b1 );
+
+ const F a2 = ( i == _N2 ? _buffer2[1] : _buffer2[even] );
+ const F b2 = ( i == 0 || i == _N2 ? 0. : _buffer2[odd] );
+ const F ph = -atan2( b2, a2 );
+
+ _buffer1[even] = amp * cos( ph );
+ if ( i != _N2 )
+ _buffer1[odd] = -amp * sin( ph );
+ }
+}
diff --git a/externals/grill/fftease/src/taint~.cpp b/externals/grill/fftease/src/taint~.cpp
new file mode 100644
index 00000000..675ced1a
--- /dev/null
+++ b/externals/grill/fftease/src/taint~.cpp
@@ -0,0 +1,97 @@
+/*
+
+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 taint:
+ public fftease
+{
+ FLEXT_HEADER_S(taint,fftease,setup)
+
+public:
+ taint(I argc,const t_atom *argv);
+
+protected:
+
+ virtual V Transform(I n,S *const *in);
+
+ V ms_thresh(F thr) { _threshold = (F)pow(10.,(_threshdB = thr)*.05); }
+
+ F _threshold,_threshdB;
+ BL _invert;
+
+private:
+ static V setup(t_classid c);
+
+ FLEXT_ATTRGET_F(_threshdB)
+ FLEXT_CALLSET_F(ms_thresh)
+ FLEXT_ATTRVAR_B(_invert)
+};
+
+FLEXT_LIB_DSP_V("fftease, taint~",taint)
+
+
+V taint::setup(t_classid c)
+{
+ FLEXT_CADDATTR_VAR(c,"threshold",_threshdB,ms_thresh);
+ FLEXT_CADDATTR_VAR1(c,"invert",_invert);
+}
+
+
+taint::taint(I argc,const t_atom *argv):
+ fftease(4,F_STEREO|F_WINDOW|F_BITSHUFFLE|F_CONVERT),
+ _threshdB(-10),_invert(false)
+{
+ /* parse and set object's options given */
+ if(argc >= 1) {
+ if(CanbeFloat(argv[0]))
+ _threshdB = GetAFloat(argv[0]);
+ else
+ post("%s - Threshold must be a float value - set to %f",thisName(),_threshdB);
+ }
+
+ if(argc >= 2) {
+ if(CanbeBool(argv[1]))
+ _invert = GetABool(argv[1]);
+ else
+ post("%s - Invert must be a boolean value - set to %0i",thisName(),_invert?1:0);
+ }
+
+ ms_thresh(_threshdB);
+
+ AddInSignal("Messages and frequency reference signal");
+ AddInSignal("Amplitude reference signal");
+ AddOutSignal("Transformed signal");
+}
+
+
+V taint::Transform(I _N2,S *const *in)
+{
+ for (I i = 0; i <= _N2; i++ ) {
+ const I even = i*2, odd = even + 1;
+
+ const F magnitude = _channel2[even];
+
+ if(_invert) {
+ // use threshold for inverse filtering to avoid division by zero
+ if ( magnitude < _threshold )
+ _channel1[even] = 0;
+ else
+ _channel1[even] /= magnitude;
+ }
+ else {
+ // simple multiplication of magnitudes
+ if (magnitude > _threshold)
+ _channel1[even] *= magnitude;
+ }
+ }
+}
diff --git a/externals/grill/fftease/src/thresher~.cpp b/externals/grill/fftease/src/thresher~.cpp
new file mode 100644
index 00000000..6be2389b
--- /dev/null
+++ b/externals/grill/fftease/src/thresher~.cpp
@@ -0,0 +1,125 @@
+/*
+
+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 thresher:
+ public fftease
+{
+ FLEXT_HEADER_S(thresher,fftease,setup)
+
+public:
+ thresher();
+
+protected:
+ virtual V Set();
+ virtual V Clear();
+ virtual V Delete();
+
+ virtual V Transform(I n,S *const *in);
+
+ F *_compositeFrame;
+ I *_framesLeft;
+ F *_c_lastphase_in,*_c_lastphase_out;
+ F _c_fundamental,_c_factor_in,_c_factor_out;
+ BL _firstFrame;
+
+ F _moveThreshold;
+ I _maxHoldFrames;
+
+private:
+ static V setup(t_classid c);
+};
+
+FLEXT_LIB_DSP("fftease, thresher~",thresher)
+
+
+V thresher::setup(t_classid c)
+{
+}
+
+void thresher::Set()
+{
+ fftease::Set();
+
+ const F _R = Samplerate();
+ const I _D = Blocksize(),_N = _D*Mult(),_Nw = _N,_N2 = _N/2,_Nw2 = _Nw/2;
+
+ _compositeFrame = new F[_N+2];
+ _framesLeft = new I[_N+2];
+ _c_lastphase_in = new F[_N2+1];
+ _c_lastphase_out = new F[_N2+1];
+
+ _c_fundamental = _R/_N;
+ _c_factor_in = _R/(_D * 3.14159265358979*2);
+ _c_factor_out = 1./_c_factor_in;
+
+ _firstFrame = true;
+ _moveThreshold = .00001 ;
+ F _maxHoldTime = 5.0 ;
+ _maxHoldFrames = (I)(_maxHoldTime *_R/_D);
+}
+
+void thresher::Clear()
+{
+ fftease::Clear();
+ _compositeFrame = NULL;
+ _framesLeft = NULL;
+ _c_lastphase_in = _c_lastphase_out = NULL;
+}
+
+void thresher::Delete()
+{
+ fftease::Delete();
+ if(_compositeFrame) delete[] _compositeFrame;
+ if(_framesLeft) delete[] _framesLeft;
+ if(_c_lastphase_in) delete[] _c_lastphase_in;
+ if(_c_lastphase_out) delete[] _c_lastphase_out;
+}
+
+
+thresher::thresher():
+ fftease(4,F_WINDOW|F_BITSHUFFLE|F_CRES)
+{
+ AddInSignal("Messages and input signal");
+ AddOutSignal("Transformed signal");
+}
+
+
+V thresher::Transform(I _N2,S *const *in)
+{
+ const I _N = _N2*2;
+
+ convert( _buffer1, _channel1, _N2, _c_lastphase_in, _c_fundamental, _c_factor_in );
+
+ if( _firstFrame ) {
+ for (I i = 0; i < _N+2; i++ ){
+ _compositeFrame[i] = _channel1[i];
+ _framesLeft[i] = _maxHoldFrames;
+ }
+ _firstFrame = false;
+ }
+ else {
+ for(I i = 0; i < _N+2; i += 2 ){
+ if( (fabs( _compositeFrame[i] - _channel1[i] ) > _moveThreshold) || (_framesLeft[i] <= 0) ) {
+ _compositeFrame[i] = _channel1[i];
+ _compositeFrame[i+1] = _channel1[i+1];
+ _framesLeft[i] = _maxHoldFrames;
+ }
+ else {
+ _framesLeft[i]--;
+ }
+ }
+ }
+
+ unconvert( _compositeFrame, _buffer1, _N2, _c_lastphase_out, _c_fundamental, _c_factor_out );
+}
diff --git a/externals/grill/fftease/src/vacancy~.cpp b/externals/grill/fftease/src/vacancy~.cpp
new file mode 100644
index 00000000..a6d0a852
--- /dev/null
+++ b/externals/grill/fftease/src/vacancy~.cpp
@@ -0,0 +1,125 @@
+/*
+
+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 vacancy:
+ public fftease
+{
+ FLEXT_HEADER_S(vacancy,fftease,setup)
+
+public:
+ vacancy(I argc,const t_atom *argv);
+
+protected:
+ virtual V Transform(I n,S *const *in);
+
+ V ms_thresh(F thr) { _threshold = (F)pow(10.,(_threshdB = thr)*.05); }
+
+ F _threshold,_threshdB;
+ BL _invert,_useRms,_swapPhase;
+
+private:
+ static V setup(t_classid c);
+
+ FLEXT_ATTRGET_F(_threshdB)
+ FLEXT_CALLSET_F(ms_thresh)
+ FLEXT_ATTRVAR_B(_invert)
+ FLEXT_ATTRVAR_B(_useRms)
+ FLEXT_ATTRVAR_B(_swapPhase)
+};
+
+FLEXT_LIB_DSP_V("fftease, vacancy~",vacancy)
+
+
+V vacancy::setup(t_classid c)
+{
+ FLEXT_CADDATTR_VAR(c,"threshold",_threshdB,ms_thresh);
+ FLEXT_CADDATTR_VAR1(c,"invert",_invert);
+ FLEXT_CADDATTR_VAR1(c,"rms",_useRms);
+ FLEXT_CADDATTR_VAR1(c,"swapphase",_swapPhase);
+}
+
+
+vacancy::vacancy(I argc,const t_atom *argv):
+ fftease(2,F_BITSHUFFLE|F_CONVERT),
+ _threshdB(-30),_invert(false),_useRms(true),_swapPhase(false)
+{
+ /* parse and set object's options given */
+ if(argc >= 1) {
+ if(CanbeFloat(argv[0]))
+ _threshdB = GetAFloat(argv[0]);
+ else
+ post("%s - Threshold must be a float value - set to %f",thisName(),_threshdB);
+ }
+
+ if(argc >= 2) {
+ if(CanbeBool(argv[1]))
+ _invert = GetABool(argv[1]);
+ else
+ post("%s - Invert must be a boolean value - set to %0i",thisName(),_invert?1:0);
+ }
+
+ if(argc >= 3) {
+ if(CanbeBool(argv[2]))
+ _useRms = GetABool(argv[2]);
+ else
+ post("%s - Rms flag must be a boolean value - set to %0i",thisName(),_useRms?1:0);
+ }
+
+ if(argc >= 4) {
+ if(CanbeBool(argv[3]))
+ _swapPhase = GetABool(argv[3]);
+ else
+ post("%s - Swapphase flag must be a boolean value - set to %0i",thisName(),_swapPhase?1:0);
+ }
+
+ ms_thresh(_threshdB);
+
+ AddInSignal("Messages and input signal");
+ AddInSignal("Reference signal");
+ AddOutSignal("Transformed signal");
+}
+
+
+V vacancy::Transform(I _N2,S *const *in)
+{
+ const F useme = _useRms?_rms * _threshold:_threshold;
+
+ // composite here please
+ if (_invert)
+ if (_swapPhase)
+ for (I i=0; i < _N2; i+=2 )
+ if ( _channel1[i] > useme && _channel2[i] < _channel1[i] ) {
+ _channel1[i] = _channel2[i];
+ _channel1[i+1] = _channel2[i+1];
+ }
+ else
+ for (I i=0; i < _N2; i+=2 )
+ if ( _channel1[i] > useme && _channel2[i] < _channel1[i] ) {
+ _channel1[i] = _channel2[i];
+ if ( _channel1[i+1] == 0. ) _channel1[i+1] = _channel2[i+1];
+ }
+ else
+ if (_swapPhase)
+ for (I i=0; i < _N2; i+=2 )
+ if ( _channel1[i] < useme && _channel2[i] > _channel1[i] ) {
+ _channel1[i] = _channel2[i];
+ _channel1[i+1] = _channel2[i+1];
+ }
+ else
+ for (I i=0; i < _N2; i+=2 )
+ if ( _channel1[i] < useme && _channel2[i] > _channel1[i] ) {
+ _channel1[i] = _channel2[i];
+ if ( _channel1[i+1] == 0. ) _channel1[i+1] = _channel2[i+1];
+ }
+}
diff --git a/externals/grill/fftease/src/xsyn~.cpp b/externals/grill/fftease/src/xsyn~.cpp
new file mode 100644
index 00000000..fdb1e736
--- /dev/null
+++ b/externals/grill/fftease/src/xsyn~.cpp
@@ -0,0 +1,52 @@
+/*
+
+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 xsyn:
+ public fftease
+{
+ FLEXT_HEADER(xsyn,fftease)
+
+public:
+ xsyn();
+
+protected:
+ virtual V Transform(I n,S *const *in);
+};
+
+FLEXT_LIB_DSP("fftease, xsyn~",xsyn)
+
+
+xsyn::xsyn():
+ fftease(2,F_STEREO|F_BITSHUFFLE|F_CONVERT)
+{
+ AddInSignal("Messages and Source signal 1");
+ AddInSignal("Source signal 2");
+ AddOutSignal("Transformed signal");
+}
+
+
+V xsyn::Transform(I _N2,S *const *in)
+{
+ const I _N = _N2*2;
+
+ F maxamp = 0;
+ I i;
+ for( i = 0; i < _N; i+= 2 )
+ if(_channel2[i] > maxamp ) maxamp = _channel2[i];
+
+ const F f = maxamp?1./maxamp:1.;
+
+ for( i = 0; i < _N; i+= 2 )
+ _channel1[i] *= (_channel2[i] * f);
+}