/*----------------------------------------------------------------------------- Entaro! ChucK WinFuncEnv extends Envelope. An AR Envelope that allows for envelopes in the shape of various window functions. http://en.wikipedia.org/wiki/Window_function Copyright (c) 2015 Eric Heep. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- #include "chuck_dl.h"#include "chuck_def.h" #include <stdio.h>#include <limits.h>#ifdef WIN32#define _USE_MATH_DEFINES#endif#include <math.h> CK_DLL_CTOR(winfuncenv_ctor);CK_DLL_DTOR(winfuncenv_dtor); // ~ envelope functionsCK_DLL_MFUN(winfuncenv_setKeyOn);CK_DLL_MFUN(winfuncenv_setKeyOff);CK_DLL_MFUN(winfuncenv_setAttack);CK_DLL_MFUN(winfuncenv_setRelease);CK_DLL_MFUN(winfuncenv_getWindowValue); // ~ window functionsCK_DLL_MFUN(winfuncenv_setBlackman);CK_DLL_MFUN(winfuncenv_setBlackmanArg);CK_DLL_MFUN(winfuncenv_setBlackmanDerivative);CK_DLL_MFUN(winfuncenv_setBlackmanHarris);CK_DLL_MFUN(winfuncenv_setBlackmanNutall);CK_DLL_MFUN(winfuncenv_setExponential);CK_DLL_MFUN(winfuncenv_setExponentialArg);CK_DLL_MFUN(winfuncenv_setHann);CK_DLL_MFUN(winfuncenv_setHannPoisson);CK_DLL_MFUN(winfuncenv_setHannPoissonArg);// TODO CK_DLL_MFUN(winfuncenv_setKaiser);CK_DLL_MFUN(winfuncenv_setNutall);CK_DLL_MFUN(winfuncenv_setParzen);CK_DLL_MFUN(winfuncenv_setPoisson);CK_DLL_MFUN(winfuncenv_setPoissonArg);CK_DLL_MFUN(winfuncenv_setTukey);CK_DLL_MFUN(winfuncenv_setTukeyArg);CK_DLL_MFUN(winfuncenv_setWelch); CK_DLL_TICK(winfuncenv_tick);t_CKINT winfuncenv_data_offset = 0; class WindowFunc{public: virtual float attackWindow (int n, int attack) = 0; virtual float releaseWindow (int n, int release) = 0;}; class BlackmanFunc : public WindowFunc{public: BlackmanFunc(float a) { // blackman coefficients a0 = (1.0 - a)/2.0; a1 = 1.0/2.0; a2 = a/2.0; // delicious pies two_pi = 2.0 * M_PI; four_pi = 4.0 * M_PI; // optimization variables N_inv = 0.0; twoPiVal = 0.0; fourPiVal = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/(attack * 2); twoPiVal = two_pi * N_inv; fourPiVal = four_pi * N_inv; return a0 - a1 + a2; } return a0 - a1 * cos(twoPiVal * n) + a2 * cos(fourPiVal * n); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/(release * 2); twoPiVal = two_pi * N_inv; fourPiVal = four_pi * N_inv; } n = n + release; return a0 - a1 * cos(twoPiVal * n) + a2 * cos(fourPiVal * n); }private: // blackman coefficients float a0, a1, a2; // delicious pies float two_pi, four_pi; float twoPiVal, fourPiVal; // optimization variables float N_inv;}; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~class BlackmanDerivativeFunc : public WindowFunc{public: BlackmanDerivativeFunc(float _a0, float _a1, float _a2, float _a3) { // blackman-derivative coefficients a0 = _a0; a1 = _a1; a2 = _a2; a3 = _a3; two_pi = 2.0 * M_PI; four_pi = 4.0 * M_PI; six_pi = 6.0 * M_PI; N_inv = 0.0; twoPiVal = 0.0; fourPiVal = 0.0; sixPiVal = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/(attack * 2); twoPiVal = two_pi * N_inv; fourPiVal = four_pi * N_inv; sixPiVal = six_pi * N_inv; return a0 - a1 + a2 - a3; } return a0 - a1 * cos(twoPiVal * n) + a2 * cos(fourPiVal * n) - a3 * cos(sixPiVal * n); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/(release * 2); twoPiVal = two_pi * N_inv; fourPiVal = four_pi * N_inv; sixPiVal = six_pi * N_inv; } n = n + release; return a0 - a1 * cos(twoPiVal * n) + a2 * cos(fourPiVal * n) - a3 * cos(sixPiVal * n); } private: // blackman-derivative coefficients float a0, a1, a2, a3; float two_pi, four_pi, six_pi; float twoPiVal, fourPiVal, sixPiVal; float N_inv; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~class ExponentialFunc: public WindowFunc{public: ExponentialFunc( float _t ) { t_inv = 0.0; t = _t; } float attackWindow (int n, int attack) { if( n == 0 ) { t_inv = 1.0/(attack * t); } return exp(-abs(n - attack) * t_inv); } float releaseWindow (int n, int release) { if( n == 0 ) { t_inv = 1.0/(release * t); return 1.0; } return exp(-abs(n) * t_inv); }private: float t_inv, t;}; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~class HannFunc : public WindowFunc{public: HannFunc() { two_pi = 2.0 * M_PI; twoPiVal = 0; } float attackWindow (int n, int attack) { if( n == 0 ) { twoPiVal = two_pi * 1.0/(attack * 2); return 0.0; } return 0.5 * (1.0 - cos(twoPiVal * n)); } float releaseWindow (int n, int release) { if( n == 0 ) { twoPiVal = two_pi * 1.0/(release * 2); } n = n + release; return 0.5 * (1.0 - cos(twoPiVal * n)); }private: float two_pi; float twoPiVal;}; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~class HannPoissonFunc : public WindowFunc{public: HannPoissonFunc( float _a ) { a = _a; pi = M_PI; N_inv = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/attack; } n = attack - n; return 0.5 * (1.0 + cos(pi * n * N_inv)) * exp(-a * n * N_inv); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/release; } return 0.5 * (1.0 + cos(pi * n * N_inv)) * exp(-a * n * N_inv); }private: float a; float pi; float N_inv;}; /* TODOclass KaiserFunc : public WindowFunc{public: KaiserFunc( float a ) { } float attackWindow (int n, int attack) { if( n == 0 ) { } return 0; } float releaseWindow (int n, int release) { if( n == 0 ) { } return 0; }private: float a; float pi;};*/ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~class ParzenFunc : public WindowFunc{public: ParzenFunc() { N_inv = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/attack; } n = attack - n - 1; if( n < attack * 0.5 ) { return 1.0 - 6.0 * pow(n * N_inv, 2) * (1.0 - (n * N_inv)); } else { return 2.0 * pow( 1.0 - n * N_inv, 3); } } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/release; } if( n < release * 0.5 ) { return 1.0 - 6.0 * pow(n * N_inv, 2) * (1.0 - (n * N_inv)); } else { return 2.0 * pow( 1.0 - n * N_inv, 3); } }private: float N_inv;}; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~class PoissonFunc : public WindowFunc{public: PoissonFunc( float _a ) { a = _a; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/attack; } n = attack - n; return exp(-a * n * N_inv); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/release; } return exp(-a * n * N_inv); }private: float a; float N_inv;}; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~class TukeyFunc : public WindowFunc{public: TukeyFunc( float _a ) { a = _a; pi = M_PI; } float attackWindow (int n, int attack) { if( n == 0 ) { } if ( n < a * attack ) { return 0.5 * (1.0 + cos(pi * ((2 * n)/(a * attack * 2.0) - 1.0))); } else { return 1.0; } } float releaseWindow (int n, int release) { if( n == 0 ) { } if ( n < a * release ) { return 1.0; } else { return 0.5 * (1.0 + cos(pi * ((2 * n)/(a * release * 2.0) - 2.0/a + 1.0))); } }private: float a; float pi;}; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~class WelchFunc : public WindowFunc{public: WelchFunc() { N_inv = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/attack; } return 1.0 - pow((n - attack) * N_inv, 2); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/release; } n = n + release; return 1.0 - pow((n - release) * N_inv, 2); }private: float N_inv;}; // ~~~~~~~~~~~~~class WinFuncEnv{public: // constructor WinFuncEnv( t_CKFLOAT fs) { m_n = 0; m_keyOn = 0; m_keyOff = 0; m_attack = 0; m_release = 0; m_currentLevel = 0; m_keyOnLevel = 0; m_keyOffLevel = 0; m_windowValue = 0; // default window m_func = new HannFunc(); } WindowFunc* m_func; // keyOn int setKeyOn() { m_keyOnLevel = m_currentLevel; m_n = 0; m_keyOn = 1; m_keyOff = 0; return m_keyOn; } int setKeyOn( t_CKINT ) { m_keyOnLevel = m_currentLevel; m_n = 0; m_keyOn = 1; m_keyOff = 0; return m_keyOn; } // keyOff int setKeyOff() { m_keyOffLevel = m_currentLevel; m_n = 0;Lines 1–500 of 987. Load more
/*----------------------------------------------------------------------------- Entaro! ChucK WinFuncEnv extends Envelope. An AR Envelope that allows for envelopes in the shape of various window functions. http://en.wikipedia.org/wiki/Window_function Copyright (c) 2015 Eric Heep. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- #include "chuck_dl.h" #include "chuck_def.h" #include <stdio.h> #include <limits.h> #ifdef WIN32 #define _USE_MATH_DEFINES #endif #include <math.h> CK_DLL_CTOR(winfuncenv_ctor); CK_DLL_DTOR(winfuncenv_dtor); // ~ envelope functions CK_DLL_MFUN(winfuncenv_setKeyOn); CK_DLL_MFUN(winfuncenv_setKeyOff); CK_DLL_MFUN(winfuncenv_setAttack); CK_DLL_MFUN(winfuncenv_setRelease); CK_DLL_MFUN(winfuncenv_getWindowValue); // ~ window functions CK_DLL_MFUN(winfuncenv_setBlackman); CK_DLL_MFUN(winfuncenv_setBlackmanArg); CK_DLL_MFUN(winfuncenv_setBlackmanDerivative); CK_DLL_MFUN(winfuncenv_setBlackmanHarris); CK_DLL_MFUN(winfuncenv_setBlackmanNutall); CK_DLL_MFUN(winfuncenv_setExponential); CK_DLL_MFUN(winfuncenv_setExponentialArg); CK_DLL_MFUN(winfuncenv_setHann); CK_DLL_MFUN(winfuncenv_setHannPoisson); CK_DLL_MFUN(winfuncenv_setHannPoissonArg); // TODO CK_DLL_MFUN(winfuncenv_setKaiser); CK_DLL_MFUN(winfuncenv_setNutall); CK_DLL_MFUN(winfuncenv_setParzen); CK_DLL_MFUN(winfuncenv_setPoisson); CK_DLL_MFUN(winfuncenv_setPoissonArg); CK_DLL_MFUN(winfuncenv_setTukey); CK_DLL_MFUN(winfuncenv_setTukeyArg); CK_DLL_MFUN(winfuncenv_setWelch); CK_DLL_TICK(winfuncenv_tick); t_CKINT winfuncenv_data_offset = 0; class WindowFunc { public: virtual float attackWindow (int n, int attack) = 0; virtual float releaseWindow (int n, int release) = 0; }; class BlackmanFunc : public WindowFunc { public: BlackmanFunc(float a) { // blackman coefficients a0 = (1.0 - a)/2.0; a1 = 1.0/2.0; a2 = a/2.0; // delicious pies two_pi = 2.0 * M_PI; four_pi = 4.0 * M_PI; // optimization variables N_inv = 0.0; twoPiVal = 0.0; fourPiVal = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/(attack * 2); twoPiVal = two_pi * N_inv; fourPiVal = four_pi * N_inv; return a0 - a1 + a2; } return a0 - a1 * cos(twoPiVal * n) + a2 * cos(fourPiVal * n); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/(release * 2); twoPiVal = two_pi * N_inv; fourPiVal = four_pi * N_inv; } n = n + release; return a0 - a1 * cos(twoPiVal * n) + a2 * cos(fourPiVal * n); } private: // blackman coefficients float a0, a1, a2; // delicious pies float two_pi, four_pi; float twoPiVal, fourPiVal; // optimization variables float N_inv; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class BlackmanDerivativeFunc : public WindowFunc { public: BlackmanDerivativeFunc(float _a0, float _a1, float _a2, float _a3) { // blackman-derivative coefficients a0 = _a0; a1 = _a1; a2 = _a2; a3 = _a3; two_pi = 2.0 * M_PI; four_pi = 4.0 * M_PI; six_pi = 6.0 * M_PI; N_inv = 0.0; twoPiVal = 0.0; fourPiVal = 0.0; sixPiVal = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/(attack * 2); twoPiVal = two_pi * N_inv; fourPiVal = four_pi * N_inv; sixPiVal = six_pi * N_inv; return a0 - a1 + a2 - a3; } return a0 - a1 * cos(twoPiVal * n) + a2 * cos(fourPiVal * n) - a3 * cos(sixPiVal * n); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/(release * 2); twoPiVal = two_pi * N_inv; fourPiVal = four_pi * N_inv; sixPiVal = six_pi * N_inv; } n = n + release; return a0 - a1 * cos(twoPiVal * n) + a2 * cos(fourPiVal * n) - a3 * cos(sixPiVal * n); } private: // blackman-derivative coefficients float a0, a1, a2, a3; float two_pi, four_pi, six_pi; float twoPiVal, fourPiVal, sixPiVal; float N_inv; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class ExponentialFunc: public WindowFunc { public: ExponentialFunc( float _t ) { t_inv = 0.0; t = _t; } float attackWindow (int n, int attack) { if( n == 0 ) { t_inv = 1.0/(attack * t); } return exp(-abs(n - attack) * t_inv); } float releaseWindow (int n, int release) { if( n == 0 ) { t_inv = 1.0/(release * t); return 1.0; } return exp(-abs(n) * t_inv); } private: float t_inv, t; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class HannFunc : public WindowFunc { public: HannFunc() { two_pi = 2.0 * M_PI; twoPiVal = 0; } float attackWindow (int n, int attack) { if( n == 0 ) { twoPiVal = two_pi * 1.0/(attack * 2); return 0.0; } return 0.5 * (1.0 - cos(twoPiVal * n)); } float releaseWindow (int n, int release) { if( n == 0 ) { twoPiVal = two_pi * 1.0/(release * 2); } n = n + release; return 0.5 * (1.0 - cos(twoPiVal * n)); } private: float two_pi; float twoPiVal; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class HannPoissonFunc : public WindowFunc { public: HannPoissonFunc( float _a ) { a = _a; pi = M_PI; N_inv = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/attack; } n = attack - n; return 0.5 * (1.0 + cos(pi * n * N_inv)) * exp(-a * n * N_inv); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/release; } return 0.5 * (1.0 + cos(pi * n * N_inv)) * exp(-a * n * N_inv); } private: float a; float pi; float N_inv; }; /* TODO class KaiserFunc : public WindowFunc { public: KaiserFunc( float a ) { } float attackWindow (int n, int attack) { if( n == 0 ) { } return 0; } float releaseWindow (int n, int release) { if( n == 0 ) { } return 0; } private: float a; float pi; }; */ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class ParzenFunc : public WindowFunc { public: ParzenFunc() { N_inv = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/attack; } n = attack - n - 1; if( n < attack * 0.5 ) { return 1.0 - 6.0 * pow(n * N_inv, 2) * (1.0 - (n * N_inv)); } else { return 2.0 * pow( 1.0 - n * N_inv, 3); } } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/release; } if( n < release * 0.5 ) { return 1.0 - 6.0 * pow(n * N_inv, 2) * (1.0 - (n * N_inv)); } else { return 2.0 * pow( 1.0 - n * N_inv, 3); } } private: float N_inv; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class PoissonFunc : public WindowFunc { public: PoissonFunc( float _a ) { a = _a; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/attack; } n = attack - n; return exp(-a * n * N_inv); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/release; } return exp(-a * n * N_inv); } private: float a; float N_inv; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class TukeyFunc : public WindowFunc { public: TukeyFunc( float _a ) { a = _a; pi = M_PI; } float attackWindow (int n, int attack) { if( n == 0 ) { } if ( n < a * attack ) { return 0.5 * (1.0 + cos(pi * ((2 * n)/(a * attack * 2.0) - 1.0))); } else { return 1.0; } } float releaseWindow (int n, int release) { if( n == 0 ) { } if ( n < a * release ) { return 1.0; } else { return 0.5 * (1.0 + cos(pi * ((2 * n)/(a * release * 2.0) - 2.0/a + 1.0))); } } private: float a; float pi; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class WelchFunc : public WindowFunc { public: WelchFunc() { N_inv = 0.0; } float attackWindow (int n, int attack) { if( n == 0 ) { N_inv = 1.0/attack; } return 1.0 - pow((n - attack) * N_inv, 2); } float releaseWindow (int n, int release) { if( n == 0 ) { N_inv = 1.0/release; } n = n + release; return 1.0 - pow((n - release) * N_inv, 2); } private: float N_inv; }; // ~~~~~~~~~~~~~ class WinFuncEnv { public: // constructor WinFuncEnv( t_CKFLOAT fs) { m_n = 0; m_keyOn = 0; m_keyOff = 0; m_attack = 0; m_release = 0; m_currentLevel = 0; m_keyOnLevel = 0; m_keyOffLevel = 0; m_windowValue = 0; // default window m_func = new HannFunc(); } WindowFunc* m_func; // keyOn int setKeyOn() { m_keyOnLevel = m_currentLevel; m_n = 0; m_keyOn = 1; m_keyOff = 0; return m_keyOn; } int setKeyOn( t_CKINT ) { m_keyOnLevel = m_currentLevel; m_n = 0; m_keyOn = 1; m_keyOff = 0; return m_keyOn; } // keyOff int setKeyOff() { m_keyOffLevel = m_currentLevel; m_n = 0;