diff options
author | Robert Jonsson <spamatica@gmail.com> | 2011-03-07 19:01:11 +0000 |
---|---|---|
committer | Robert Jonsson <spamatica@gmail.com> | 2011-03-07 19:01:11 +0000 |
commit | e40fc849149dd97c248866a4a1d026dda5e57b62 (patch) | |
tree | b12b358f3b3a0608001d30403358f8443118ec5f /attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp | |
parent | 1bd4f2e8d9745cabb667b043171cad22c8577768 (diff) |
clean3
Diffstat (limited to 'attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp')
-rw-r--r-- | attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp b/attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp new file mode 100644 index 00000000..10f968bd --- /dev/null +++ b/attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp @@ -0,0 +1,462 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2002-2006 by Werner Schweer and others +// +// ZynAddSubFX - a software synthesizer +// Copyright (C) 2002-2005 Nasca Octavian Paul +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> + +#include "Misc/Master.h" +#include "Misc/Util.h" +#include "MasterUI.h" + +//========================================================= +// MESS interface +//========================================================= + +#include "synti/libsynti/mess.h" +int instances = -1; + +//--------------------------------------------------------- +// Zynadd +//--------------------------------------------------------- + +class Zynadd : public Mess, public Master + { + virtual void process(float** buffer, int offset, int n); + virtual bool processEvent(const MidiEvent&); + virtual void getInitData(int*, const unsigned char**); + virtual int getControllerInfo(int, const char**, int*, int*, int*); + virtual const char* getPatchName(int, int, int) const; + virtual const MidiPatch* getPatchInfo(int, const MidiPatch*) const; + virtual bool hasGui() const { return true; } + virtual bool guiVisible() const { return _guiVisible; } + virtual void showGui(bool val); + + mutable MidiPatch patch; + mutable int currentBank; + + bool _guiVisible; + bool loadBank(int); + char* messPatch[MAX_NUM_BANKS][128]; + + public: + int Pexitprogram; + MasterUI* ui; + pthread_t thr; + + Zynadd(); + ~Zynadd(); + + enum { + GUI_NO_CMD, GUI_REFRESH, GUI_HIDE, GUI_SHOW + }; + int guiCmd; + }; + +//--------------------------------------------------------- +// guiThread +//--------------------------------------------------------- + +void* guiThread(void *arg) + { + Zynadd* z = (Zynadd *) arg; + z->ui = new MasterUI(z, &z->Pexitprogram); + z->ui->showUI(); + while (z->Pexitprogram == 0) { + switch(z->guiCmd) { + case Zynadd::GUI_REFRESH: + z->ui->refresh_master_ui(); + break; + case Zynadd::GUI_HIDE: + switch (config.cfg.UserInterfaceMode) { + case 0: + z->ui->selectuiwindow->hide(); + break; + case 1: + z->ui->masterwindow->hide(); + break; + case 2: + z->ui->simplemasterwindow->hide(); + break; + } + break; + case Zynadd::GUI_SHOW: + z->ui->showUI(); + break; + } + z->guiCmd = Zynadd::GUI_NO_CMD; + Fl::wait(0.01); + } + delete(z->ui); + Fl::wait(0.01); + pthread_exit(0); + return 0; + } + +//--------------------------------------------------------- +// Zynadd +//--------------------------------------------------------- + +Zynadd::Zynadd() : Mess(2), Master() + { + instances++; + swaplr = config.cfg.SwapStereo; + Pexitprogram = 0; + currentBank = -1; + guiCmd = 0; + + swaplr = 0; //1 for left-right swapping + memset(messPatch, 0, sizeof(messPatch)); + bank.rescanforbanks(); + defaults(); + + for (int i = 1; i < MAX_NUM_BANKS; ++i) { + if (bank.banks[i].dir == 0) + break; + loadBank(i); + for (unsigned int k = 0; k < 128; ++k) { + if (!bank.emptyslot(k)) { + messPatch[i][k] = strdup(bank.getname(k)); + } + } + } + + pthread_create(&thr, NULL, guiThread, this); + _guiVisible = true; + } + +//--------------------------------------------------------- +// ~Zynadd +//--------------------------------------------------------- + +Zynadd::~Zynadd() + { + Pexitprogram = 1; + sleep(2); //wait the thread to finish + instances--; + } + +//--------------------------------------------------------- +// showGui +//--------------------------------------------------------- + +void Zynadd::showGui(bool val) + { + if (val != _guiVisible) + guiCmd = val ? GUI_SHOW : GUI_HIDE; + _guiVisible = val; + } + +//--------------------------------------------------------- +// loadBank +//--------------------------------------------------------- + +bool Zynadd::loadBank(int n) + { + if (n != currentBank) { + if (bank.banks[n].dir == 0) { + printf("Zynaddsubfx: empty bank %d\n", n); + return false; + } + bank.loadbank(bank.banks[n].dir); + currentBank = n; + } + return true; + } + +//--------------------------------------------------------- +// getControllerInfo +//--------------------------------------------------------- + +struct ZynCtrl { + const char* name; + int num; + int min; + int max; + }; + +// +// NRPN +// 0x04 0 // System Effects +// 0x04 1 +// 0x04 2 +// 0x04 3 +// +// 0x08 0 // Insertion Effects +// 0x08 1 +// 0x08 2 +// 0x08 3 +// 0x08 4 +// 0x08 5 +// 0x08 6 +// 0x08 7 +// 0x08 8 + +int Zynadd::getControllerInfo(int i, const char** name, int* num, int* min, int* max) + { + static const ZynCtrl ctrl[] = { + { "Pitch", 0x40000, -8191, 8190 }, + { "ProgramChange", 0x40001, 0, 0xffffff }, + { "Modulation", 1, 0, 127 }, + { "MainVolume", 7, 0, 127 }, + { "Pan", 10, 0, 127 }, + { "Expression", 11, 0, 127 }, + { "Sustain", 64, 0, 127 }, + { "Portamento", 65, 0, 127 }, + { "FilterQ", 71, 0, 127 }, + { "FilterCutoff", 74, 0, 127 }, + { "Bandwidth", 75, 0, 127 }, + { "ModulationAmp", 76, 0, 127 }, + { "ResonanceCenter", 77, 0, 127 }, + { "ResonanceBandwidth", 78, 0, 127 }, + { "AllSoundsOff", 120, 0, 127 }, + { "ResetAllController", 121, 0, 127 }, + { "AllNotesOff", 123, 0, 127 }, + }; + if ((unsigned)i >= sizeof(ctrl)/sizeof(*ctrl)) + return 0; + *name = ctrl[i].name; + *num = ctrl[i].num; + *min = ctrl[i].min; + *max = ctrl[i].max; + return i+1;; + } + +//--------------------------------------------------------- +// getPatchName +//--------------------------------------------------------- + +const char* Zynadd::getPatchName(int, int val, int) const + { + int bankNo = (val >> 8) + 1; + int program = val & 0x7f; + return messPatch[bankNo][program]; + } + +//--------------------------------------------------------- +// getPatchInfo +//--------------------------------------------------------- + +const MidiPatch* Zynadd::getPatchInfo(int, const MidiPatch* p) const { + if(p) { + patch.hbank = p->hbank; + patch.lbank = p->lbank; + patch.prog = p->prog; + int bn = ((patch.hbank << 7) + patch.lbank); //7 because lbank is signed + switch(p->typ) { + case MP_TYPE_LBANK : + patch.typ = 0; + patch.name = messPatch[bn + 1][patch.prog]; + if(patch.name) return &patch; + else return getPatchInfo(0, &patch); + break; + default : + if(patch.prog + 1 < 128) { + patch.prog++; + patch.name = messPatch[bn + 1][patch.prog]; + if(patch.name) return &patch; + else return getPatchInfo(0, &patch); + } + else { + patch.prog = 0; + if(bn + 1 < MAX_NUM_BANKS - 1) { + bn++; + patch.name = bank.banks[bn + 1].name; + patch.hbank = bn / 128; + patch.lbank = bn % 128; + patch.typ = MP_TYPE_LBANK; + if(patch.name) return &patch; + else return getPatchInfo(0, &patch); + } + else return NULL; + } + break; + } + } + else { + patch.typ = MP_TYPE_LBANK; + patch.hbank = 0; + patch.lbank = 0; + patch.prog = 0; + patch.name = bank.banks[(patch.hbank << 7) + patch.lbank + 1].name; + if(patch.name) return &patch; + else { + patch.typ = 0; + patch.prog = 127; //hack to go faster + return getPatchInfo(0, &patch); + } + } +} + +//--------------------------------------------------------- +// getInitData +//--------------------------------------------------------- + +void Zynadd::getInitData(int* n, const unsigned char** data) + { + *n = getalldata((char **)data); + } + +//--------------------------------------------------------- +// process +// synthesize n samples into buffer+offset +//--------------------------------------------------------- + +void Zynadd::process(float** outputs, int offset, int n) + { + float* outl = outputs[0] + offset; + float* outr = outputs[1] + offset; + if (busy) { + memset(outl, 0, sizeof(float) * n); + memset(outr, 0, sizeof(float) * n); + return; + } + GetAudioOutSamples(n, outl, outr); + } + +//--------------------------------------------------------- +// processEvent +//--------------------------------------------------------- + +bool Zynadd::processEvent(const MidiEvent& e) + { + if (busy) + return true; + int ch = e.channel(); + switch(e.type()) { + case 0x80: // note off + NoteOff(ch, e.dataA()); + break; + case 0x90: // note on + NoteOn(ch, e.dataA(), e.dataB()); + break; + case 0xb0: // controller + switch(e.dataA()) { + case 0x40000: // pitch + SetController(ch, C_pitchwheel, e.dataB()); + break; + case 0x40001: // program change + { + int bankNo = (e.dataB() >> 8) + 1; + if (!loadBank(bankNo)) + return false; + int program = e.dataB() & 0x7f; + if (bank.emptyslot(program)) { + printf("Zynaddsubfx: programslot %d is empty!\n", program); + break; + } + for (int npart = 0; npart < NUM_MIDI_PARTS; npart++) { + Part* p = part[npart]; + if ((ch == p->Prcvchn) && (p->Penabled != 0)) + bank.loadfromslot(program, p); + } + guiCmd = GUI_REFRESH; + } + break; + default: + { + int ctl; + switch (e.dataA()) { + case 1: ctl = C_modwheel; break; + case 7: ctl = C_volume; break; + case 10: ctl = C_panning; break; + case 11: ctl = C_expression; break; + case 64: ctl = C_sustain; break; + case 65: ctl = C_portamento; break; + case 71: ctl = C_filterq; break; + case 74: ctl = C_filtercutoff; break; + case 75: ctl = C_bandwidth; break; + case 76: ctl = C_fmamp; break; + case 77: ctl = C_resonance_center; break; + case 78: ctl = C_resonance_bandwidth; break; + case 120: ctl = C_allsoundsoff; break; + case 121: ctl = C_resetallcontrollers; break; + case 123: ctl = C_allnotesoff; break; + case 0x06: ctl = C_dataentryhi; break; + case 0x26: ctl = C_dataentrylo; break; + case 99: ctl = C_nrpnhi; break; + case 98: ctl = C_nrpnlo; break; + default: ctl = C_NULL; break; + } + SetController(ch, ctl, e.dataB()); + guiCmd = GUI_REFRESH; // does not work + } + break; + } + break; + + case 0xf0: + putalldata((char*)e.data(), e.len()); + break; + } + return false; + } + +//--------------------------------------------------------- +// instantiate +//--------------------------------------------------------- + +static Mess* instantiate(int sr, const char*) + { + if (instances == -1) { + config.init(); + instances = 0; + srand(time(0)); + // SOUND_BUFFER_SIZE restricts midi resolution + SOUND_BUFFER_SIZE = 64; + OSCIL_SIZE = 256; // config.cfg.OscilSize; + SAMPLE_RATE = sr; + denormalkillbuf = new REALTYPE [SOUND_BUFFER_SIZE]; + for (int i = 0; i < SOUND_BUFFER_SIZE; i++) + denormalkillbuf[i] = (RND - 0.5) * 1e-16; + + OscilGen::tmpsmps = new REALTYPE[OSCIL_SIZE]; + newFFTFREQS(&OscilGen::outoscilFFTfreqs,OSCIL_SIZE/2); + } + if (instances != 0) + return 0; //don't allow multiple instances + + Zynadd* sintetizator = new Zynadd(); + sintetizator->setSampleRate(sr); + return sintetizator; + } + +extern "C" { + static MESS descriptor = { + "Zynaddsubfx", + "Zynaddsubfx Software Synthesizer", + "0.1", // version string + MESS_MAJOR_VERSION, MESS_MINOR_VERSION, + instantiate + }; + + // We must compile with -fvisibility=hidden to avoid namespace + // conflicts with global variables. + // Only visible symbol is "mess_descriptor". + // (TODO: all plugins should be compiled this way) + + __attribute__ ((visibility("default"))) + const MESS* mess_descriptor() { return &descriptor; } + } + |