#include #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 401) #error You need at least flext version 0.4.1 #endif // A flext dsp external ("tilde object") inherits from the class flext_dsp class yin: public flext_dsp { // Each external that is written in C++ needs to use #defines // from flbase.h // // The define // // FLEXT_HEADER(NEW_CLASS, PARENT_CLASS) // // should be somewhere in your dsp file. // A good place is here: FLEXT_HEADER(yin, flext_dsp) public: yin() { // The constructor of your class is responsible for // setting up inlets and outlets and for registering // inlet-methods: // The descriptions of the inlets and outlets are output // via the Max/MSP assist method (when mousing over them in edit mode). // PD will hopefully provide such a feature as well soon AddInSignal("audio in"); // audio in AddOutSignal("fundamental freq out"); // fundamental freq out // We're done constructing: post("yin~ fundamental frequency estimator"); } // end of constructor protected: // here we declare the virtual DSP function virtual void m_signal(int n, float *const *in, float *const *out); private: void ACF(const float* ins, int n, float* r); void diff(const float* ins, float* r, int n, float* difference); void cumnorm(float* difference, int n, float* d_primes); float get_max_period(float* d_primes, int n); }; // end of class declaration for yin #include "yin_helpers.cpp" // Before we can run our yin-class in PD, the object has to be registered as a // PD object. Otherwise it would be a simple C++-class, and what good would // that be for? Registering is made easy with the FLEXT_NEW_* macros defined // in flext.h. For tilde objects without arguments call: FLEXT_NEW_DSP("yin~", yin) // Now we define our DSP function. It gets this arguments: // // int n: length of signal vector. Loop over this for your signal processing. // float *const *in, float *const *out: // These are arrays of the signals in the objects signal inlets rsp. // oulets. We come to that later inside the function. void yin::m_signal(int n, float *const *in, float *const *out) { //declare local variables const float *ins = in[0]; float *outs = out[0]; float f_zero; float r[n]; float difference[n]; float d_primes[n]; float max_period; //calculate autocorrelation ACF(ins, n/2, r); //calculate difference from autocorrelation diff(ins, r, n/2, difference); //calculate cumulative norm cumnorm(difference, n/2, d_primes); //convert max period to frequency max_period = get_max_period(d_primes, n/2); if (max_period == 0) f_zero = 0; else f_zero = Samplerate()/max_period; for (int i=0; i