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/vam/vam.cpp | |
parent | 1bd4f2e8d9745cabb667b043171cad22c8577768 (diff) |
clean3
Diffstat (limited to 'attic/muse_qt4_evolution/synti/vam/vam.cpp')
-rw-r--r-- | attic/muse_qt4_evolution/synti/vam/vam.cpp | 801 |
1 files changed, 801 insertions, 0 deletions
diff --git a/attic/muse_qt4_evolution/synti/vam/vam.cpp b/attic/muse_qt4_evolution/synti/vam/vam.cpp new file mode 100644 index 00000000..bc5c035a --- /dev/null +++ b/attic/muse_qt4_evolution/synti/vam/vam.cpp @@ -0,0 +1,801 @@ +//========================================================= +// MusE +// Linux Music Editor +// +// Parts of this file taken from: +// The analogue oscillator from Steve Harris plugin collection. +// Werner Schweer's organ softsynth for MusE. +// The music-dsp source archive. +// +// (C) Copyright 2002 Jotsif Lindman Hölund (jotsif@linux.nu) +// +// 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, USA or point your web browser to http://www.gnu.org. +//========================================================= + +#include "libsynti/mess.h" +#include "muse/midi.h" +#include "muse/midictrl.h" + +#include "vam.h" +#include "vamgui.h" +#include "libsynti/mono.h" + +// Denormalise floats, only actually needed for PIII and very recent PowerPC +#define DENORMALISE(fv) (((*(unsigned int*)&(fv))&0x7f800000)==0)?0.0f:(fv) + +// A fast, truncating towards 0 modulo function. ANSI C doesn't define +// which % will do, most truncate towards -inf +#define MOD(v,m) (v<0?v+m:(v>m?v-m:v)) + +// Limit values +#define LIMIT(v,l,u) (v<l?l:(v>u?u:v)) + +#define PI M_PI + +//--------------------------------------------------------- +// Oscillator +//--------------------------------------------------------- + +struct Oscillator { + float phase; + float pitchmod; + float detune; + float freq; + float pwm; + float pw; + float fm; + int waveform; + bool on; +}; + +struct LPFilter { + float out[4]; + float in[4]; +}; + +//--------------------------------------------------------- +// Envelope +//--------------------------------------------------------- + +struct EnvelopeGenerator { + static const int onStates = 2; + static const int offStates = 1; + + struct Segment { + int ticks; + double incr; + }; + Segment segment[onStates + offStates]; + + int state; + double env; + int tick; + + int attack; + int decay; + float sustain; + int release; + + EnvelopeGenerator() { + segment[0].ticks = 441; + segment[0].incr = 1.0/441.0; + segment[1].ticks = 0; + segment[1].incr = 0.0; + segment[2].ticks = 441; + segment[2].incr = -(1.0/441.0); + } + + void setSegment(int seg, int ticks, double incr) { + segment[seg].ticks = ticks; + segment[seg].incr = incr; + } + + void keyOn() { +// env = 0.0; + state = 0; + if(env) segment[state].incr = (1.0 - env) / segment[state].ticks; + else env = 0.0; + tick = segment[state].ticks; + } + void keyOff() { + state = onStates; + tick = segment[state].ticks; + } + bool isOff() { + return state == (onStates+offStates); + } + bool step() { + if(state >= onStates+offStates) + return false; + if (tick == 0) + return true; + env +=segment[state].incr; + if(env < 0.0) + env = 0.0; + --tick; + while(tick == 0) { + ++state; + if(state >= onStates+offStates) + return false; + if(state == onStates) + return true; + tick = segment[state].ticks; + } + return true; + } +}; + +//--------------------------------------------------------- +// VAM +//--------------------------------------------------------- + +class VAM : public MessMono { + static int useCount; + static const int CB_AMP_SIZE = 961; + static const int LIN2EXP_SIZE = 256; + + static double cb2amp_tab[CB_AMP_SIZE]; + static double cb2amp(double cb); + + static float lin2exp[LIN2EXP_SIZE]; + +/* Synthvariables */ + static float *sin_tbl, *tri_tbl, *saw_tbl, *squ_tbl; + bool isOn; + int pitch, channel; + float velocity; + + int idata[NUM_CONTROLLER]; // buffer for init data + + EnvelopeGenerator dco1_env; + EnvelopeGenerator dco2_env; + EnvelopeGenerator filt_env; + + LPFilter dco1_filter; + LPFilter dco2_filter; + + Oscillator dco1; + Oscillator dco2; + Oscillator lfo; + + bool filt_invert, filt_keytrack; + + double filt_env_mod, filt_res, filt_cutoff, keytrack_cutoff; + + int controller[NUM_CONTROLLER]; + + void noteoff(int channel, int pitch); + + virtual void process(float**, int, int); + virtual void note(int channel, int pitch, int velo); + virtual bool setController(int channel, int ctrl, int val); + virtual bool sysex(int, const unsigned char*); + void getInitData(int* n, const unsigned char**p); + + void setController(int ctrl, int data); + + float *wave_tbl(int wave); + double lowpass_filter(double cutoff, double resonance, double input, LPFilter *f); + + virtual bool guiVisible() const; + virtual void showGui(bool); + virtual bool hasGui() const { return true; } + virtual void getGeometry(int* x, int* y, int* w, int* h) const; + virtual void setGeometry(int x, int y, int w, int h); + + VAMGui* gui; + + public: + VAM(int sr); + ~VAM(); + bool init(const char* name); + }; + +float* VAM::sin_tbl; +float* VAM::tri_tbl; +float* VAM::saw_tbl; +float* VAM::squ_tbl; +int VAM::useCount = 0; +double VAM::cb2amp_tab[VAM::CB_AMP_SIZE]; +float VAM::lin2exp[VAM::LIN2EXP_SIZE]; + + +//--------------------------------------------------------- +// VAM +//--------------------------------------------------------- + +VAM::VAM(int sr) + : MessMono() + { + setSampleRate(sr); + gui = 0; + } + +//--------------------------------------------------------- +// ~VAM +//--------------------------------------------------------- + +VAM::~VAM() + { + --useCount; + if (useCount == 0) { + delete[] sin_tbl; + delete[] tri_tbl; + delete[] saw_tbl; + delete[] squ_tbl; + } + } + +//--------------------------------------------------------- +// curTime +//--------------------------------------------------------- + +double VAM::cb2amp(double cb) +{ + if(cb < 0.0) + return 1.0; + if(cb > 960.0) + return 0.0; + return cb2amp_tab[int(cb)]; +} + +double VAM::lowpass_filter(double cutoff, double resonance, double input, LPFilter *f) +{ + double output; + cutoff *= 1.16; + + input -= f->out[3] * (resonance * 4.0) * (1.0 - 0.15 * cutoff * cutoff); + input *= 0.35013 * cutoff * cutoff * cutoff * cutoff; + + f->out[0] = input + 0.3 * f->in[0] + (1.0 - cutoff) * f->out[0]; // Pole 1 + f->in[0] = input; + f->out[1] = f->out[0] + 0.3 * f->in[1] + (1.0 - cutoff) * f->out[1]; // Pole 2 + f->in[1] = f->out[0]; + f->out[2] = f->out[1] + 0.3 * f->in[2] + (1.0 - cutoff) * f->out[2]; // Pole 3 + f->in[2] = f->out[1]; + f->out[3] = f->out[2] + 0.3 * f->in[3] + (1.0 - cutoff) * f->out[3]; // Pole 4 + f->in[3] = f->out[2]; + +// if(f.out[3] > 1.0) f.out[3] = 1.0; + + output = f->out[3]; + + + return output; +} + +float *VAM::wave_tbl(int wave) +{ + if (wave == 0) { + return sin_tbl; + } + else if (wave == 1) { + return squ_tbl; + } + else if (wave == 2) { + return saw_tbl; + } + else if (wave == 3) { + return tri_tbl; + } + return sin_tbl; +} + +//--------------------------------------------------------- +// init +//--------------------------------------------------------- + +bool VAM::init(const char* name) + { + gui = new VAMGui; + gui->hide(); // to avoid flicker during MusE startup + gui->setWindowTitle(QString(name)); + + if (useCount == 0) { + int i; + float tmp; + for(i = 0; i < CB_AMP_SIZE; i++) { + cb2amp_tab[i] = pow(10.0, double(i) / -300.0); +// cb2amp_tab[i] = 1.0 - i/(float)CB_AMP_SIZE; + } + for(i = 0; i < LIN2EXP_SIZE; i++) { + tmp = i/255.0; + lin2exp[i] = 1.5 * tmp * tmp * tmp - 0.69 * tmp * tmp + 0.16 * tmp; + } + int sr = sampleRate(); + /* Build up denormalised oscilator wavetables, these are sample_rate + long, costs more RAM to create them but makes freqency calcs much + cheaper, and means that interpolation isn't that neccesary, esp if + you use integer frequncies */ + + float *tmp_tbl = new float[sr]; + const int lag = sr/50; + sin_tbl = new float[sr]; + for (i = 0; i < sr; i++) { + tmp = sin(i * 2.0 * PI / sr); + sin_tbl[i] = DENORMALISE(tmp); + } + tri_tbl = new float[sr]; + for (i = 0; i < sr; i++) { + tmp = acos(cos(i * 2.0 * PI / sr)) / PI * 2.0 - 1.0; + tri_tbl[i] = DENORMALISE(tmp); + } + squ_tbl = new float[sr]; + for (i = 0; i < sr/2; i++) { + tmp_tbl[i] = -1.0f; + } + for (i = sr/2; i < sr; i++) { + tmp_tbl[i] = +1.0f; + } + tmp = -1.0f; + for (i = (sr/2)-lag; i < (sr/2)+lag; i++) { + tmp_tbl[i] = tmp; + tmp += 1.0/(lag * 2.0); + } + for (i = 0; i < sr; i++) { + squ_tbl[i] = (tmp_tbl[MOD(i-lag, sr)] + + tmp_tbl[MOD(i+lag, sr)]) * 0.5; + } + saw_tbl = new float[sr]; + for (i = 0; i < sr; i++) { + tmp = ((2.0 * i) - (float)sr) / (float)sr; + tmp_tbl[i] = DENORMALISE(tmp); + } + for (i = 0; i < sr; i++) { + saw_tbl[i] = (tmp_tbl[MOD(i-lag, sr)] + + tmp_tbl[MOD(i+lag, sr)]) * 0.5; + } + delete[] tmp_tbl; + } + + dco1_filter.out[0] = dco1_filter.out[1] = dco1_filter.out[2] = dco1_filter.out[3] = 0.0; + dco1_filter.in[0] = dco1_filter.in[1] = dco1_filter.in[2] = dco1_filter.in[3] = 0.0; + dco2_filter.out[0] = dco2_filter.out[1] = dco2_filter.out[2] = dco2_filter.out[3] = 0.0; + dco2_filter.in[0] = dco2_filter.in[1] = dco2_filter.in[2] = dco2_filter.in[3] = 0.0; + + ++useCount; + dco1.phase = 0.0; + dco2.phase = 0.0; + lfo.phase = 0.0; + + memset(controller, 0, sizeof(controller)); + + int maxval = 128*128-1; + + setController(0, DCO1_PITCHMOD, 8191); + setController(0, DCO2_PITCHMOD, 8191); + setController(0, DCO1_WAVEFORM, 1); + setController(0, DCO2_WAVEFORM, 1); + setController(0, DCO1_FM, 0); + setController(0, DCO2_FM, 0); + setController(0, DCO1_PWM, 0); + setController(0, DCO2_PWM, 0); + setController(0, DCO1_ATTACK, 0); + setController(0, DCO2_ATTACK, 0); + setController(0, DCO1_DECAY, 0); + setController(0, DCO2_DECAY, 0); + setController(0, DCO1_SUSTAIN, maxval - 255); + setController(0, DCO2_SUSTAIN, maxval - 255); + setController(0, DCO1_RELEASE, 0); + setController(0, DCO2_RELEASE, 0); + setController(0, LFO_FREQ, 0); + setController(0, LFO_WAVEFORM, 0); + setController(0, FILT_ENV_MOD, 0); + setController(0, FILT_KEYTRACK, 0); + setController(0, FILT_RES, 0); + setController(0, FILT_ATTACK, 0); + setController(0, FILT_DECAY, 0); + setController(0, FILT_SUSTAIN, maxval); + setController(0, FILT_RELEASE, 3); + setController(0, DCO2ON, 0); + setController(0, FILT_INVERT, 0); + setController(0, FILT_CUTOFF, 15000); + setController(0, DCO1_DETUNE, 8191); + setController(0, DCO2_DETUNE, 8191); + setController(0, DCO1_PW, 0); + setController(0, DCO2_PW, 0); + + isOn = false; + return false; + } + +//--------------------------------------------------------- +// write +//--------------------------------------------------------- + +void VAM::process(float** ports, int offset, int sampleCount) +{ + // + // get and process all pending events from the + // synthesizer GUI + // + while (gui->fifoSize()) { + MidiEvent ev = gui->readEvent(); + if (ev.type() == ME_CONTROLLER) { + // process local? + setController(ev.dataA() & 0xfff, ev.dataB()); + sendEvent(ev); + } + else + printf("Organ::process(): unknown event\n"); + } + float* buffer = *ports + offset; + if (!isOn) + return; + + float sample, osc, lfol, *dco1_tbl, *dco2_tbl, *lfo_tbl, pw; + float cutoff; + int sr = sampleRate(); + + dco1_tbl = wave_tbl(dco1.waveform); + dco2_tbl = wave_tbl(dco2.waveform); + lfo_tbl = wave_tbl(lfo.waveform); + + cutoff = filt_keytrack ? (dco1.freq /500.0 + filt_cutoff)/2 : filt_cutoff; + cutoff = LIMIT(cutoff, 0.0, 1.0); + + for (int i = 0; i < sampleCount; i++) { + if(!(dco1_env.step() + dco2_env.step())) { + isOn = false; + break; + } + filt_env.step(); + + /* DCO 1 */ + lfol = lfo_tbl[(int)lfo.phase]; + pw = dco1.pw + dco1.pwm * lfol * 0.5; + pw = LIMIT(pw, 0.0, 1.0); + if(dco1.phase < sr/2 * ( 1.0 - pw)) + osc = dco1_tbl[int(dco1.phase / (1.0 - pw))]; + else + osc = dco1_tbl[int(dco1.phase / (1.0 + pw))]; + lfol = lfo_tbl[(int)lfo.phase]; + dco1.phase += dco1.freq + dco1.fm * lfol * 1500.0; + lfo.phase += lfo.freq * 50.0; + if(!filt_invert) + sample = lowpass_filter((cb2amp(960.0 * (1.0 - filt_env_mod * filt_env.env)) + + 1.0 - filt_env_mod) * cutoff, + filt_res, osc, &dco1_filter) * cb2amp(960.0 * (1.0 - dco1_env.env)); + else sample = lowpass_filter((cb2amp(960.0 * (1.0 - filt_env_mod * (1.0 - filt_env.env))) + + 1.0 - filt_env_mod) * cutoff, + filt_res, osc, &dco1_filter) * cb2amp(960.0 * (1.0 - dco1_env.env)); + while(dco1.phase > sr) dco1.phase -= sr; + while(dco1.phase < 0.0) dco1.phase += sr; + + /* DCO 2 */ + if(dco2.on) { + pw = dco2.pw + dco2.pwm * lfol * 0.5; + pw = LIMIT(pw, 0.0, 1.0); + if(dco2.phase < sr/2 * (1 - pw)) + osc = dco2_tbl[int(dco2.phase / (1.0 - pw))]; + else + osc = dco2_tbl[int(dco2.phase / (1.0 + pw))]; + dco2.phase += dco2.freq + dco2.fm * lfol * 1500.0; + if(!filt_invert) + sample += lowpass_filter((cb2amp(960.0 * (1.0 - filt_env_mod * filt_env.env)) + 1.0 - filt_env_mod) * cutoff, + filt_res, osc, &dco2_filter) * cb2amp(960.0 * (1.0 - dco2_env.env)); + else sample += lowpass_filter((cb2amp(960.0 * (1.0 - filt_env_mod * (1.0 - filt_env.env))) + 1.0 - filt_env_mod) * cutoff, + filt_res, osc, &dco2_filter) * cb2amp(960.0 * (1.0 - dco2_env.env)); + + while (dco2.phase > sr) dco2.phase -= sr; + while (dco2.phase < 0.0) dco2.phase += sr; + } + while(lfo.phase > sr) lfo.phase -= sr; + while(lfo.phase < 0.0) lfo.phase += sr; + sample *= velocity * 0.5; + sample = LIMIT(sample, -1.0, 1.0); + +// if(sample > 1.0) fprintf(stderr, "oooops %f\n", sample); + buffer[i] = sample; + } +} + +//--------------------------------------------------------- +// note +//--------------------------------------------------------- + +void VAM::note(int chan, int newpitch, int velo) +{ + if (velo == 0) { + noteoff(chan, newpitch); + return; + } + isOn = true; + channel = chan; + pitch = newpitch; + velocity = velo / 127.0; + dco1.freq = 8.176 * exp(float(pitch + dco1.pitchmod + dco1.detune)*log(2.0)/12.0); + dco2.freq = 8.176 * exp(float(pitch + dco2.pitchmod + dco2.detune)*log(2.0)/12.0); + keytrack_cutoff = 16.0 * dco1.freq / sampleRate(); + if(keytrack_cutoff > 1.0) keytrack_cutoff = 1.0; + dco1_env.setSegment(0, dco1_env.attack, 1.0/dco1_env.attack); + dco1_env.setSegment(1, dco1_env.decay, -((1.0-dco1_env.sustain)/dco1_env.decay)); + dco2_env.setSegment(0, dco2_env.attack, 1.0/dco2_env.attack); + dco2_env.setSegment(1, dco2_env.decay, -((1.0-dco2_env.sustain)/dco2_env.decay)); + filt_env.setSegment(0, filt_env.attack, 1.0/filt_env.attack); + filt_env.setSegment(1, filt_env.decay, -((1.0-filt_env.sustain)/filt_env.decay)); + dco1_env.keyOn(); + dco2_env.keyOn(); + filt_env.env = 0.0; + filt_env.keyOn(); +// dco1.phase = 0.0; +// dco2.phase = 0.0; +// lfo.phase = 0.0; +} + +//--------------------------------------------------------- +// noteoff +//--------------------------------------------------------- + +void VAM::noteoff(int chan, int offpitch) +{ + if(isOn && (pitch == offpitch) && (channel == chan)) { + dco1_env.keyOff(); + dco2_env.keyOff(); + filt_env.keyOff(); + } +} + +//--------------------------------------------------------- +// setController +//--------------------------------------------------------- + +bool VAM::setController(int /*channel*/, int ctrl, int data) +{ + setController(ctrl & 0xfff, data); + MidiEvent ev(0, channel, ME_CONTROLLER, ctrl, data); + gui->writeEvent(ev); + return false; + } + +void VAM::setController(int ctrl, int data) + { +// fprintf(stderr, "ctrl: %d data: %d\n", ctrl, data); + int maxval = 128*128-1; + double normval = double(data) / double(maxval); + switch (ctrl) { + case DCO1_PITCHMOD: + dco1.pitchmod = (data - 8191) / 341.333; + break; + case DCO1_WAVEFORM: + dco1.waveform = data; + break; + case DCO1_FM: + dco1.fm = lin2exp[int(normval * 255.0)]; + break; + case DCO1_PWM: + dco1.pwm = normval; + break; + case DCO1_ATTACK: + dco1_env.attack = int(lin2exp[int(normval * 255.0)] * 5.0 * sampleRate()) + 1; + break; + case DCO1_DECAY: + dco1_env.decay = (data * sampleRate() * 5) / maxval + 1; + break; + case DCO1_SUSTAIN: + dco1_env.sustain = normval; + break; + case DCO1_RELEASE: + dco1_env.release = int(lin2exp[int(normval * 255.0)] * 10.0 * sampleRate()) + 1; + dco1_env.setSegment(2, dco1_env.release, -(1.0/dco1_env.release)); + break; + + case DCO2_PITCHMOD: + dco2.pitchmod = (data - 8191) / 341.333; + break; + case DCO2_WAVEFORM: + dco2.waveform = data; + break; + case DCO2_FM: + dco2.fm = normval; + break; + case DCO2_PWM: + dco2.pwm = normval; + break; + case DCO2_ATTACK: + dco2_env.attack = int(lin2exp[int(normval * 255.0)] * 5.0 * sampleRate()) + 1; + break; + case DCO2_DECAY: + dco2_env.decay = (data * sampleRate() * 5) / maxval + 1; + break; + case DCO2_SUSTAIN: + dco2_env.sustain = normval; + break; + case DCO2_RELEASE: + dco2_env.release = int(lin2exp[int(normval * 255.0)] * 10.0 * sampleRate()) + 1; + dco2_env.setSegment(2, dco2_env.release, -(1.0/dco2_env.release)); + break; + case LFO_FREQ: + lfo.freq = lin2exp[int(normval * 255.0)]; +// fprintf(stderr, "%f\n", lfo.freq); + break; + case LFO_WAVEFORM: + lfo.waveform = data; + break; + case FILT_ENV_MOD: + filt_env_mod = 1.0 - lin2exp[int(255.0 - normval * 255.0)]; + break; + case FILT_KEYTRACK: + filt_keytrack = data; + break; + case FILT_RES: + filt_res = normval; + break; + case FILT_ATTACK: + filt_env.attack = int(lin2exp[int(normval * 255.0)] * 5.0 * sampleRate()); + break; + case FILT_DECAY: + filt_env.decay = (data * sampleRate() * 5) / maxval + 1; + break; + case FILT_SUSTAIN: + filt_env.sustain = normval; + break; + case FILT_RELEASE: + filt_env.release = int(lin2exp[int(normval * 255.0)] * 10.0 * sampleRate()) + 1; + filt_env.setSegment(2, filt_env.release, -(1.0/filt_env.release)); + break; + case DCO2ON: + dco2.on = data; + break; + case FILT_INVERT: + filt_invert = data; + break; + case FILT_CUTOFF: + filt_cutoff = normval; +// fprintf(stderr, "%f\n", filt_cutoff); + break; + case DCO1_DETUNE: + dco1.detune = (data - 8191) / 16384.0; + break; + case DCO2_DETUNE: + dco2.detune = (data - 8191) / 16384.0; + break; + case DCO1_PW: + dco1.pw = normval; + if(dco1.pw == 1.0) dco1.pw = 0.99; + + break; + case DCO2_PW: + dco2.pw = normval; + if(dco2.pw == 1.0) dco2.pw = 0.99; + break; + default: + printf("VAM: set unknown Ctrl 0x%x to 0x%x\n", ctrl, data); + break; + } + controller[ctrl] = data; +} + +//--------------------------------------------------------- +// parameterRequest +//--------------------------------------------------------- + +#if 0 +void VAM::parameterRequest(int ctrl) +{ + if(ctrl >= NUM_CONTROLLER) { + fprintf(stderr, "VAM: illegal controller %d request\n", ctrl); + return; + } + unsigned char data[] = { 0x7c, 0x2, 0x2, 0x0, 0x0, 0x0 }; + data[3] = ctrl; + data[4] = controller[ctrl] & 0x7f; + data[5] = (controller[ctrl] >> 7) & 0x7f; + sendSysex(data, sizeof(data)); +} +#endif + +//--------------------------------------------------------- +// getInitData +//--------------------------------------------------------- + +void VAM::getInitData(int* n, const unsigned char**p) + { + int* d = idata; + for (int i = 0; i < NUM_CONTROLLER; ++i) { + int val = controller[i]; + *d++ = val; + } + *n = NUM_CONTROLLER * sizeof(int); // sizeof(idata); + *p = (unsigned char*)idata; + } + +//--------------------------------------------------------- +// sysex +//--------------------------------------------------------- + +bool VAM::sysex(int n, const unsigned char* data) + { + if (n != (NUM_CONTROLLER * sizeof(int))) { + printf("Organ: unknown sysex\n"); + return false; + } + int* s = (int*) data; + for (int i = 0; i < NUM_CONTROLLER; ++i) { + int val = *s++; + setController(0, i, val); + } + return false; + } + +//--------------------------------------------------------- +// guiVisible +//--------------------------------------------------------- + +bool VAM::guiVisible() const + { + return gui->isVisible(); + } + +//--------------------------------------------------------- +// showGui +//--------------------------------------------------------- + +void VAM::showGui(bool val) + { + gui->setShown(val); + } + +//--------------------------------------------------------- +// getGeometry +//--------------------------------------------------------- + +void VAM::getGeometry(int* x, int* y, int* w, int* h) const + { + QPoint pos(gui->pos()); + QSize size(gui->size()); + *x = pos.x(); + *y = pos.y(); + *w = size.width(); + *h = size.height(); + } + +//--------------------------------------------------------- +// setGeometry +//--------------------------------------------------------- + +void VAM::setGeometry(int x, int y, int w, int h) + { + gui->resize(QSize(w, h)); + gui->move(QPoint(x, y)); + } + +//--------------------------------------------------------- +// inst +//--------------------------------------------------------- + +static Mess* instantiate(int sr, const char* name) + { + VAM* vam = new VAM(sr); + if (vam->init(name)) { + delete vam; + return 0; + } + return vam; + } + +extern "C" { + static MESS descriptor = { + "vam", + "vam soft synth", + "0.1", // version string + MESS_MAJOR_VERSION, MESS_MINOR_VERSION, + instantiate, + }; + + const MESS* mess_descriptor() { return &descriptor; } + } + |