summaryrefslogtreecommitdiff
path: root/attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp
diff options
context:
space:
mode:
authorRobert Jonsson <spamatica@gmail.com>2011-03-07 19:01:11 +0000
committerRobert Jonsson <spamatica@gmail.com>2011-03-07 19:01:11 +0000
commite40fc849149dd97c248866a4a1d026dda5e57b62 (patch)
treeb12b358f3b3a0608001d30403358f8443118ec5f /attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp
parent1bd4f2e8d9745cabb667b043171cad22c8577768 (diff)
clean3
Diffstat (limited to 'attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp')
-rw-r--r--attic/muse_qt4_evolution/synti/zynaddsubfx/main.cpp462
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; }
+ }
+