From e40fc849149dd97c248866a4a1d026dda5e57b62 Mon Sep 17 00:00:00 2001 From: Robert Jonsson Date: Mon, 7 Mar 2011 19:01:11 +0000 Subject: clean3 --- attic/muse_qt4_evolution/synti/organ/organ.cpp | 621 +++++++++++++++++++++++++ 1 file changed, 621 insertions(+) create mode 100644 attic/muse_qt4_evolution/synti/organ/organ.cpp (limited to 'attic/muse_qt4_evolution/synti/organ/organ.cpp') diff --git a/attic/muse_qt4_evolution/synti/organ/organ.cpp b/attic/muse_qt4_evolution/synti/organ/organ.cpp new file mode 100644 index 00000000..7c83a463 --- /dev/null +++ b/attic/muse_qt4_evolution/synti/organ/organ.cpp @@ -0,0 +1,621 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: organ.cpp,v 1.23 2005/12/16 15:36:51 wschweer Exp $ +// +// Parts of this file taken from: +// Organ - Additive Organ Synthesizer Voice +// Copyright (C) 1999, 2000 David A. Bartold +// Some information was gathered form the "beatrix" organ +// from Fredrik Kilander +// +// (C) Copyright 2001-2007 Werner Schweer (ws@seh.de) +//========================================================= + +#include "muse/midi.h" +#include "libsynti/midievent.h" + +#include "organ.h" +#include "organgui.h" +#include "reverb.h" + +float* Organ::attackEnv; +float* Organ::releaseEnv; +int Organ::envSize; +float* Organ::waveTable; +int Organ::useCount; +double Organ::cb2amp_tab[MAX_ATTENUATION]; +float Organ::keyCompression[NO_VOICES]; + +//--------------------------------------------------------- +// dBToGain +//--------------------------------------------------------- + +static double dBToGain(double dB) + { + return pow(10.0, (dB / 20.0)); + } + +//--------------------------------------------------------- +// cb2amp +// convert centibel to amplification (0 - 96dB) +//--------------------------------------------------------- + +double Organ::cb2amp(int cb) + { + if (cb < 0) + return 1.0; + if (cb >= MAX_ATTENUATION) + return 0.0; + return cb2amp_tab[cb]; + } + +static const unsigned SHIFT = 16; +static const double RESO = 256.0 * 256.0 * 256.0 * 256.0; +static const unsigned resolution = 256 * 256; // 16 Bit + +//--------------------------------------------------------- +// Organ +//--------------------------------------------------------- + +Organ::Organ(int sr) + : Mess2(2) + { + setSampleRate(sr); + gui = 0; + reverb = new Reverb(); + + ++useCount; + if (useCount > 1) + return; + + // centibels to amplitude conversion + for (int i = 0; i < MAX_ATTENUATION; i++) + cb2amp_tab[i] = pow(10.0, double(i) / -200.0); + + // Initialize sine table. + waveTable = new float[resolution]; + for (unsigned i = 0; i < resolution; i++) + waveTable[i] = sin (double(i) * 2.0 * M_PI / double(resolution)); + + // Initialize envelope tables + + envSize = sr * 4 / 1000; // 4 msec + attackEnv = new float[envSize]; + releaseEnv = new float[envSize]; + + for (int i = 0; i < envSize; ++i) { + attackEnv[i] = float(i) / float(envSize); + releaseEnv[i] = float(i) / float(envSize); + } + + // Initialize key compression table + + keyCompression[ 0] = 1.0; + keyCompression[ 1] = 1.0; + keyCompression[ 2] = dBToGain(-1.1598); + keyCompression[ 3] = dBToGain(-2.0291); + keyCompression[ 4] = dBToGain(-2.4987); + keyCompression[ 5] = dBToGain(-2.9952); + keyCompression[ 6] = dBToGain(-3.5218); + keyCompression[ 7] = dBToGain(-4.0823); + keyCompression[ 8] = dBToGain(-4.6815); + keyCompression[ 9] = dBToGain(-4.9975); + keyCompression[10] = dBToGain(-4.9998); + + /* Linear interpolation from u to v. */ + + static const float u = -5.0; + static const float v = -9.0; + static const float m = 1.0 / (NO_VOICES - 12); + for (int i = 11; i < NO_VOICES; i++) { + keyCompression[i] = dBToGain(u + ((v - u) * float(i - 11) * m)); + } + + // Initialize controller table + + addController("drawbar16", DRAWBAR0, 0, 8, 8); + addController("drawbar513", DRAWBAR1, 0, 8, 8); + addController("drawbar8", DRAWBAR2, 0, 8, 8); + addController("drawbar4", DRAWBAR3, 0, 8, 0); + addController("drawbar223", DRAWBAR4, 0, 8, 0); + addController("drawbar2", DRAWBAR5, 0, 8, 0); + addController("drawbar135", DRAWBAR6, 0, 8, 0); + addController("drawbar113", DRAWBAR7, 0, 8, 0); + addController("drawbar1", DRAWBAR8, 0, 8, 0); + addController("reverbOn", REVERB_ON, 0, 1, 0); + addController("reverbRoomSize", REVERB_ROOM_SIZE, 0, 127, 60); + addController("reverbMix", REVERB_MIX, 0, 127, 100); + addController("vibratoOn", VIBRATO_ON, 0, 1, 1); + addController("vibratoFreq", VIBRATO_FREQ, 0, 127, 100); + addController("vibratoDepth", VIBRATO_DEPTH, 0, 127, 50); + addController("volume", CTRL_VOLUME, 0, 127, 100); + addController("percOn", PERC_ON, 0, 1, 1); + addController("percGain", PERC_GAIN, 0, 127, 60); + addController("percDecay", PERC_DECAY, 0, 127, 60); + addController("percHarmony", PERC_HARMONY, 0, 8, 3); + addController("rotaryOn", ROTARY_ON, 0, 1, 0); + addController("rot1Freq", ROT1_FREQ, 0, 127, 100); + addController("rot1Depth", ROT1_DEPTH, 0, 127, 50); + addController("rot2Freq", ROT2_FREQ, 0, 127, 100); + addController("rot2Depth", ROT2_DEPTH, 0, 127, 50); + } + +//--------------------------------------------------------- +// ~Organ +//--------------------------------------------------------- + +Organ::~Organ() + { + if (gui) + delete gui; + delete reverb; + + --useCount; + if (useCount == 0) { + delete[] waveTable; + delete[] attackEnv; + delete[] releaseEnv; + } + } + +//--------------------------------------------------------- +// init +//--------------------------------------------------------- + +bool Organ::init(const char* name) + { + gui = new OrganGui; + gui->hide(); + gui->setWindowTitle(QString(name)); + + // + // Initialize controller + // + int idx = 0; + foreach(SynthCtrl* c, ctrl) { + setController(c->ctrl, c->init); // init synti + gui->setParamIdx(idx, c->init); // init gui + ++idx; + } + + // see: http://www.dairiki.org/HammondWiki/GearRatio + static const int gearA[12] = { 85, 71,67,35,69,12,37,49,48,11,67,54 }; + static const int gearB[12] = { 104,82,73,36,67,11,32,40,37, 8,46,35 }; + static const int teeth[] = { 2, 4, 8, 16, 32, 64, 128, 192 }; + + vibratoAccu = 0; + rot1AccuL = 0; + rot1AccuR = 0x80000000; + rot2AccuL = 0; + rot2AccuR = 0x80000000; + + for (int i = 0; i < NO_WHEELS; ++i) { + int note = i % 12; + int octave = i / 12; + if (octave == 7) + note += 5; + // in 60Hz organs, the motor turns at 1200 RPM (20 revolutions /sec) + double freq = 20.0 * teeth[octave] * gearA[note] / gearB[note]; + wheels[i].frameStep = lrint(freq * RESO / double(sampleRate())); + wheels[i].accu = 0; + wheels[i].refCount = 0; + wheels[i].active = false; + for (int k = 0; k < NO_BUSES; ++k) + wheels[i].envCount[k] = 0; + } + keyCompressionValue = 1.0; + keyCompressionCount = 0; + percGain = 0.0; + return false; + } + +//--------------------------------------------------------- +// process +//--------------------------------------------------------- + +void Organ::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) { + setController(ev.dataA(), ev.dataB()); + sendEvent(ev); + } + else + printf("Organ::process(): unknown event\n"); + } + + float* buffer1 = ports[0] + offset; + float* buffer2 = ports[1] + offset; + memset(buffer1, 0, sizeof(float) * sampleCount); + memset(buffer2, 0, sizeof(float) * sampleCount); + + float vibrato[sampleCount]; + + if (vibratoOn) { + // + // compute partial vibrato sinus + // + for (int i = 0; i < sampleCount; ++i) { + vibratoAccu += vibratoStep; + vibrato[i] = waveTable[vibratoAccu >> SHIFT] * vibratoDepth; + } + } + + foreach (Wheel* w, activeWheels) { + for (int i = 0; i < sampleCount; ++i) { + + unsigned step = w->frameStep; + if (vibratoOn) + step += unsigned(step * vibrato[i]); + + w->accu += step; + + int idx = w->accu >> SHIFT; + float val1 = waveTable[idx]; + idx = (idx + 1) & 0xffff; + float val2 = waveTable[idx]; + float val = val1 + (val2 - val1) * double(w->accu & 0xffff)/double(0x10000); + + for (int k = 0; k < NO_BUSES; ++k) { + int* envCnt = &(w->envCount[k]); + float v; + if (*envCnt > 0) { + (*envCnt)--; + float gain = w->gain[k] - w->deltaGain[k] * w->env[k][*envCnt]; + v = val * gain; + if ((*envCnt == 0) && (w->refCount == 0)) { + int idx = activeWheels.indexOf(w); + if (idx != -1) { + activeWheels.removeAt(idx); + w->active = false; + } + } + } + else { + v = val * w->gain[k]; + } + buffer1[i] += v * drawBarGain[k]; + if (k == percussionBus) + buffer2[i] += v; + } + } + } + if (percussionOn) { + for (int i = 0; i < sampleCount; ++i) { + buffer1[i] = buffer1[i] * volume * keyCompressionValue + + buffer2[i] * percGain; + percGain *= percussionEnvDecay; + if (keyCompressionCount) { + keyCompressionValue += keyCompressionDelta; + --keyCompressionCount; + } + } + } + else { + for (int i = 0; i < sampleCount; ++i) { + buffer1[i] *= volume * keyCompressionValue; + if (keyCompressionCount) { + keyCompressionValue += keyCompressionDelta; + --keyCompressionCount; + } + } + } + memcpy(buffer2, buffer1, sizeof(float) * sampleCount); + if (reverbOn) + reverb->process(buffer1, buffer2, sampleCount); + } + +//--------------------------------------------------------- +// changeKeyCompression +//--------------------------------------------------------- + +void Organ::changeKeyCompression() + { + float kc = keyCompression[pressedKeys.size()]; + keyCompressionCount = int(sampleRate() * .005); // 5 msec envelope + if (keyCompressionCount < 2) + keyCompressionCount = 2; + keyCompressionDelta = (kc - keyCompressionValue) / keyCompressionCount; + } + +//--------------------------------------------------------- +// playNote +//--------------------------------------------------------- + +bool Organ::playNote(int /*channel*/, int pitch, int velo) + { + if (pitch < 36 || pitch > 97) + return false; + if (velo == 0) { + int idx = pressedKeys.indexOf(pitch); + if (idx == -1) { + printf("Organ: noteoff %d not found\n", pitch); + return false; + } + pressedKeys.removeAt(idx); + } + else { + if (pressedKeys.isEmpty()) + percGain = percGainInit; + pressedKeys.append(pitch); + } + changeKeyCompression(); + + for (int k = 0; k < NO_ELEMENTS; ++k) { + const Elem* e = &routing[pitch - 36][k]; + if (e->bus == -1) + break; + Wheel* w = &wheels[int(e->wheel)]; + int bus = e->bus; + float level = e->level; + + if (velo) { + if (!w->active) { + // activate wheel + for (int k = 0; k < NO_BUSES; ++k) { + w->gain[k] = 0.0; + w->envCount[k] = 0; + } + activeWheels.append(w); + w->active = true; + } + float deltaGain = level; + + if (w->envCount[bus]) { + deltaGain += w->deltaGain[bus] * w->env[bus][w->envCount[bus]]; + } + w->env[bus] = attackEnv; + w->deltaGain[bus] = deltaGain; + w->gain[bus] += level; + w->refCount++; + } + else { + float deltaGain = -level; + + if (w->envCount[bus]) { + deltaGain += w->deltaGain[bus] * w->env[bus][w->envCount[bus]]; + } + w->env[bus] = releaseEnv; + w->deltaGain[bus] = deltaGain; + w->gain[bus] -= level; + if (w->refCount) + w->refCount--; + } + w->envCount[bus] = envSize; + } + return false; + } + +//--------------------------------------------------------- +// percussionChanged +//--------------------------------------------------------- + +void Organ::percussionChanged() + { + percussionEnvDecay = exp(log(0.001/percGainInit) / (percDecay * double(sampleRate()))); + } + +//--------------------------------------------------------- +// setController +//--------------------------------------------------------- + +void Organ::setController(int ctrlId, int data) + { + int ctrlIdx = controllerIdx(ctrlId); + if (ctrlIdx != -1) + ctrl[ctrlIdx]->val = data; + switch (ctrlId) { + case DRAWBAR0 ... DRAWBAR8: + { + int db = ctrlId - DRAWBAR0; + drawBarGain[db] = float(data) / 8.0; + } + break; + case REVERB_ROOM_SIZE: + reverb->setRoomSize(float(data) / 127.0); + break; + + case REVERB_MIX: + reverb->setMix(float(data) / 127.0); + break; + + case REVERB_ON: + reverbOn = data != 0; + break; + + case VIBRATO_ON: + vibratoOn = data != 0; + break; + + case VIBRATO_FREQ: + vibratoFreq = float(data) * 6.0 / 127.0 + 4; + vibratoStep = lrint(vibratoFreq * RESO / double(sampleRate())); + break; + + case VIBRATO_DEPTH: + vibratoDepth = float(data) / 127.0 * .01; + break; + + case PERC_ON: + percussionOn = data != 0; + break; + + case PERC_GAIN: // 0.01 - 0.4 + percGainInit = float(data) * .39 / 127.0 + 0.01; + percussionChanged(); + break; + + case PERC_DECAY: // 0.5 - 4.5 sec + percDecay = float(data) * 4.0 / 127.0 + 0.5; + percussionChanged(); + break; + + case PERC_HARMONY: + percussionBus = data; + break; + + case ROTARY_ON: + rotaryOn = data != 0; + break; + + case ROT1_FREQ: + rot1Freq = float(data) * 6.0 / 127.0 + 0.67; + rot1Step = lrint(rot1Freq * RESO / double(sampleRate())); + break; + + case ROT1_DEPTH: + rot1Depth = float(data) / 127.0 * 1.0; + break; + + case ROT2_FREQ: + rot1Freq = float(data) * 5.0 / 127.0 + 0.5; + rot1Step = lrint(rot1Freq * RESO / double(sampleRate())); + break; + + case ROT2_DEPTH: + rot2Depth = float(data) / 127.0 * 1.0; + break; + + case CTRL_VOLUME: + data &= 0x7f; + volume = data == 0 ? 0.0 : cb2amp(int(200 * log10((127.0 * 127)/(data*data)))); + volume *= .04; + break; + + case CTRL_ALL_SOUNDS_OFF: + foreach(Wheel* w, activeWheels) { + for (int k = 0; k < NO_ELEMENTS; ++k) { + w->gain[k] = 0.0; + w->envCount[k] = 0; + } + w->refCount = 0; + } + pressedKeys.clear(); + break; + + case CTRL_RESET_ALL_CTRL: +// for (int i = 0; i < NUM_CONTROLLER; ++i) +// setController(0, synthCtrl[i].num, synthCtrl[i].val); + break; + default: + fprintf(stderr, "Organ:set unknown Ctrl 0x%x to 0x%x\n", ctrlId, data); + return; + } + } + +//--------------------------------------------------------- +// setController +//--------------------------------------------------------- + +bool Organ::setController(int channel, int ctrlId, int data) + { + MidiEvent ev(0, channel, ME_CONTROLLER, ctrlId, data); + gui->writeEvent(ev); + setController(ctrlId, data); + return false; + } + +//--------------------------------------------------------- +// sysex +//--------------------------------------------------------- + +bool Organ::sysex(int n, const unsigned char* data) + { + int nn = ctrl.size() * sizeof(int); + if (nn != n) { + printf("unknown sysex %d %02x %02x\n", n, data[0], data[1]); + return false; + } + const int* s = (const int*) data; + for (int i = 0; i < ctrl.size(); ++i) { + setController(0, ctrl[i]->ctrl, *s); + setController(ctrl[i]->ctrl, *s); + s++; + } + return false; + } + +//--------------------------------------------------------- +// MESS +//--------------------------------------------------------- + +//--------------------------------------------------------- +// guiVisible +//--------------------------------------------------------- + +bool Organ::guiVisible() const + { + return gui->isVisible(); + } + +//--------------------------------------------------------- +// showGui +//--------------------------------------------------------- + +void Organ::showGui(bool val) + { + gui->setShown(val); + } + +//--------------------------------------------------------- +// getGeometry +//--------------------------------------------------------- + +void Organ::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 Organ::setGeometry(int x, int y, int w, int h) + { + gui->resize(QSize(w, h)); + gui->move(QPoint(x, y)); + } + +//--------------------------------------------------------- +// instantiate +// construct a new synthesizer instance +//--------------------------------------------------------- + +static Mess* instantiate(int sr, const char* name) + { + Organ* synth = new Organ(sr); + if (synth->init(name)) { + delete synth; + synth = 0; + } + return synth; + } + +//--------------------------------------------------------- +// msynth_descriptor +// Return a descriptor of the requested plugin type. +//--------------------------------------------------------- + +extern "C" { + static MESS descriptor = { + "Organ", + "Organ; based on David A. Bartold's LADSPA plugin", + "0.1", // version string + MESS_MAJOR_VERSION, MESS_MINOR_VERSION, + instantiate, + }; + + const MESS* mess_descriptor() { return &descriptor; } + } + -- cgit v1.2.3