//========================================================= // MusE // Linux Music Editor // $Id: s1.cpp,v 1.10 2005/01/13 21:16:27 wschweer Exp $ // // S1 - simple mono demo synthesizer // - plays only one note at a time // - has no gui nor any controller // // Version 0.2: stop note on wave zero crossing to avoid // clicks // // (C) Copyright 2001-2004 Werner Schweer (ws@seh.de) //========================================================= #include #include #include "synti/libsynti/mono.h" #define RESOLUTION 16384 //--------------------------------------------------------- // S1 - simple mono demo synthesizer //--------------------------------------------------------- class S1 : public MessMono { static int useCount; static float *wave_table; int gate; float freq; unsigned accu; float sample; virtual void note(int channel, int pitch, int velo); virtual void process(float** buffer, int offset, int n); public: S1(); ~S1(); }; float* S1::wave_table; int S1::useCount = 0; //--------------------------------------------------------- // S1 //--------------------------------------------------------- S1::S1() : MessMono() { if (useCount++ == 0) { // // create sinus wave table // wave_table = new float[RESOLUTION]; for (int i = 0; i < RESOLUTION; i++) wave_table[i] = sin ((i * 2.0 * M_PI) / RESOLUTION) / 6.0; } gate = 0; } //--------------------------------------------------------- // ~S1 //--------------------------------------------------------- S1::~S1() { if (--useCount == 0) delete[] wave_table; } //--------------------------------------------------------- // noteon // process note on //--------------------------------------------------------- void S1::note(int /*channel*/, int pitch, int velo) { if (velo == 0) { // // note off // if (sample == 0.0) gate = 0; else if (sample > 0.0) gate = 2; else if (sample < 0.0) gate = 3; } else { // // note on // accu = 0; gate = 1; freq = 8.176 * exp(float(pitch)*log(2.0)/12.0); } } //--------------------------------------------------------- // write // synthesize n samples into buffer+offset //--------------------------------------------------------- void S1::process(float** buffer, int offset, int n) { if (gate == 0) return; float* p = buffer[0] + offset; unsigned freq_256 = (int) (freq * ((double) RESOLUTION) / sampleRate() * 256.0); for (int i = 0; i < n; i++) { accu += freq_256; while (accu >= RESOLUTION * 256) accu -= RESOLUTION * 256; sample = wave_table[accu >> 8]; // // stop on zero crossing // if in decay state // if (gate == 2 && sample <= 0.0) { gate = 0; break; } else if (gate == 3 && sample >= 0.0) { gate = 0; break; } p[i] += sample; } } //--------------------------------------------------------- // inst //--------------------------------------------------------- static Mess* instantiate(int sr, const char*) { S1* s1 = new S1(); s1->setSampleRate(sr); return s1; } extern "C" { static MESS descriptor = { "S1", "S1 MusE Demo Software Synthesizer", "0.2", // version string MESS_MAJOR_VERSION, MESS_MINOR_VERSION, instantiate }; const MESS* mess_descriptor() { return &descriptor; } }