diff options
-rw-r--r-- | muse/synti/organ/organ.cpp | 139 | ||||
-rw-r--r-- | muse/synti/organ/organ.h | 23 | ||||
-rw-r--r-- | muse/synti/organ/organgui.ui | 203 | ||||
-rw-r--r-- | muse/synti/organ/reverb.cpp | 4 |
4 files changed, 340 insertions, 29 deletions
diff --git a/muse/synti/organ/organ.cpp b/muse/synti/organ/organ.cpp index 50477cc7..3bb5f4cf 100644 --- a/muse/synti/organ/organ.cpp +++ b/muse/synti/organ/organ.cpp @@ -133,6 +133,12 @@ Organ::Organ(int sr) addController("percOn", PERC_ON, 0, 1, 1); addController("percSoft", PERC_SOFT, 0, 1, 0); addController("percSlow", PERC_SLOW, 0, 1, 1); + addController("percFirst", PERC_FIRST, 0, 1, 1); + 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); } //--------------------------------------------------------- @@ -178,10 +184,11 @@ bool Organ::init(const char* name) 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 }; - vibratoFreq = 7.25; - vibratoDepth = 0.005; - vibratoStep = lrint(vibratoFreq * RESO / double(sampleRate())); - vibratoAccu = 0; + vibratoAccu = 0; + rot1AccuL = 0; + rot1AccuR = 0x80000000; + rot2AccuL = 0; + rot2AccuR = 0x80000000; for (int i = 0; i < NO_WHEELS; ++i) { int note = i % 12; @@ -199,14 +206,12 @@ bool Organ::init(const char* name) } keyCompressionValue = 1.0; keyCompressionCount = 0; - percussionBus = 5; // 5 or 7 - percussionOn = true; - percussionEnvelopeCount = 0; + percGain = 0.0; return false; } //--------------------------------------------------------- -// write +// process //--------------------------------------------------------- void Organ::process(float** ports, int offset, int sampleCount) @@ -229,8 +234,17 @@ void Organ::process(float** ports, int offset, int sampleCount) float* buffer2 = ports[1] + offset; memset(buffer1, 0, sizeof(float) * sampleCount); memset(buffer2, 0, sizeof(float) * sampleCount); + float buffer3[sampleCount]; + float buffer4[sampleCount]; + memset(buffer3, 0, sizeof(float) * sampleCount); + memset(buffer4, 0, sizeof(float) * sampleCount); float vibrato[sampleCount]; + float rot1L[sampleCount]; + float rot1R[sampleCount]; + float rot2L[sampleCount]; + float rot2R[sampleCount]; + if (vibratoOn) { // // compute partial vibrato sinus @@ -240,22 +254,40 @@ void Organ::process(float** ports, int offset, int sampleCount) vibrato[i] = waveTable[vibratoAccu >> SHIFT] * vibratoDepth; } } + if (rotaryOn) { + for (int i = 0; i < sampleCount; ++i) { + rot1AccuL += rot1Step; + rot1L[i] = waveTable[rot1AccuL >> SHIFT] * rot1Depth; + rot1AccuR += rot1Step; + rot1R[i] = waveTable[rot1AccuR >> SHIFT] * rot1Depth; + rot2AccuL += rot2Step; + rot2L[i] = waveTable[rot2AccuL >> SHIFT] * rot2Depth; + rot2AccuR += rot2Step; + rot2R[i] = waveTable[rot2AccuR >> SHIFT] * rot2Depth; + } + } - foreach(Wheel* w, activeWheels) { + foreach (Wheel* w, activeWheels) { for (int i = 0; i < sampleCount; ++i) { unsigned step = w->frameStep; if (vibratoOn) - step += lrint(step * vibrato[i]); + step += unsigned(step * vibrato[i]); + w->accu += step; - float val = waveTable[w->accu >> SHIFT]; + unsigned off1 = unsigned(w->accu + (step * rot1L[i])); + unsigned off2 = unsigned(w->accu + (step * rot1R[i])); + float val1 = waveTable[off1 >> SHIFT]; + float val2 = waveTable[off2 >> SHIFT]; for (int k = 0; k < NO_BUSES; ++k) { int* envCnt = &(w->envCount[k]); + float v1, v2; if (*envCnt > 0) { (*envCnt)--; float gain = w->gain[k] - w->deltaGain[k] * w->env[k][*envCnt]; - buffer1[i] += val * gain * drawBarGain[k]; + v1 = val1 * gain; + v2 = val2 * gain; if ((*envCnt == 0) && (w->refCount == 0)) { int idx = activeWheels.indexOf(w); if (idx != -1) { @@ -265,26 +297,43 @@ void Organ::process(float** ports, int offset, int sampleCount) } } else { - buffer1[i] += val * w->gain[k] * drawBarGain[k]; + v1 = val1 * w->gain[k]; + v2 = val2 * w->gain[k]; } - if (percussionOn && k == percussionBus && percussionEnvelopeCount) { - // TODO + buffer1[i] += v1 * drawBarGain[k]; + buffer2[i] += v2 * drawBarGain[k]; + if (k == percussionBus) { + buffer3[i] += v1; + buffer4[i] += v2; } } } } - for (int i = 0; i < sampleCount; ++i) { - buffer1[i] *= volume * keyCompressionValue; - - if (keyCompressionCount) { - keyCompressionValue += keyCompressionDelta; - --keyCompressionCount; + if (percussionOn) { + for (int i = 0; i < sampleCount; ++i) { + buffer1[i] = buffer1[i] * volume * keyCompressionValue + + buffer3[i] * percGain; + buffer2[i] = buffer2[i] * volume * keyCompressionValue + + buffer4[i] * percGain; + percGain *= percussionEnvDecay; + if (keyCompressionCount) { + keyCompressionValue += keyCompressionDelta; + --keyCompressionCount; + } + } + } + else { + for (int i = 0; i < sampleCount; ++i) { + buffer1[i] *= volume * keyCompressionValue; + buffer2[i] *= volume * keyCompressionValue; + if (keyCompressionCount) { + keyCompressionValue += keyCompressionDelta; + --keyCompressionCount; + } } } if (reverbOn) reverb->process(buffer1, buffer2, sampleCount); - else - memcpy(buffer2, buffer1, sizeof(float) * sampleCount); } //--------------------------------------------------------- @@ -362,10 +411,23 @@ bool Organ::playNote(int /*channel*/, int pitch, int velo) } w->envCount[bus] = envSize; } + if (pressedKeys.isEmpty()) + percGain = percGainInit; return false; } //--------------------------------------------------------- +// percussionChanged +//--------------------------------------------------------- + +void Organ::percussionChanged() + { + double decay = percussionSlow ? 4.0 : 1.0; + percGainInit = percussionSoft ? 0.5012 : 1.0; + percussionEnvDecay = exp(log(0.001/percGainInit) / (decay * double(sampleRate()))); + } + +//--------------------------------------------------------- // setController //--------------------------------------------------------- @@ -407,12 +469,43 @@ void Organ::setController(int ctrlId, int data) break; case PERC_ON: + percussionOn = data != 0; break; case PERC_SOFT: + percussionSoft = data != 0; + percussionChanged(); break; case PERC_SLOW: + percussionSlow = data != 0; + percussionChanged(); + break; + + case PERC_FIRST: + percussionBus = data ? 3 : 4; + 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 * .01; + 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 * .01; break; case CTRL_VOLUME: diff --git a/muse/synti/organ/organ.h b/muse/synti/organ/organ.h index 6a90d67a..ac6ef156 100644 --- a/muse/synti/organ/organ.h +++ b/muse/synti/organ/organ.h @@ -31,7 +31,8 @@ enum { DRAWBAR3, DRAWBAR4, DRAWBAR5, DRAWBAR6, DRAWBAR7, DRAWBAR8, REVERB_ON, REVERB_ROOM_SIZE, REVERB_MIX, VIBRATO_ON, VIBRATO_FREQ, VIBRATO_DEPTH, - PERC_ON, PERC_SOFT, PERC_SLOW, + PERC_ON, PERC_SOFT, PERC_SLOW, PERC_FIRST, + ROTARY_ON, ROT1_FREQ, ROT1_DEPTH, ROT2_FREQ, ROT2_DEPTH }; //--------------------------------------------------------- @@ -101,8 +102,25 @@ class Organ : public Mess2 { // percussion int percussionBus; // usually drawbar 3 or drawbar 4 bool percussionOn; + bool percussionSlow; + bool percussionSoft; int percussionEnvelopeCount; - + double percussionEnvDecay; + double percGain; + double percGainInit; + + // rotary speaker emulation + bool rotaryOn; + double rot1Freq; // horn: 0,67 - 6,7 + double rot1Depth; + double rot2Freq; // drum: 0,5 - 5,5 + double rot2Depth; + unsigned rot1Step; + unsigned rot1AccuL; + unsigned rot1AccuR; + unsigned rot2Step; + unsigned rot2AccuL; + unsigned rot2AccuR; float drawBarGain[NO_BUSES]; Wheel wheels[NO_WHEELS]; @@ -111,6 +129,7 @@ class Organ : public Mess2 { void setController(int ctrl, int val); void changeKeyCompression(); + void percussionChanged(); virtual void process(float**, int, int); virtual bool playNote(int channel, int pitch, int velo); diff --git a/muse/synti/organ/organgui.ui b/muse/synti/organ/organgui.ui index c0643106..60eddb1b 100644 --- a/muse/synti/organ/organgui.ui +++ b/muse/synti/organ/organgui.ui @@ -6,7 +6,7 @@ <x>0</x> <y>0</y> <width>555</width> - <height>334</height> + <height>341</height> </rect> </property> <property name="sizePolicy" > @@ -323,7 +323,7 @@ background-color: gray; </sizepolicy> </property> <property name="title" > - <string>Drawbars</string> + <string>UPPER MANUAL</string> </property> <layout class="QHBoxLayout" > <item> @@ -393,6 +393,13 @@ background-color: gray; <property name="value" > <double>8.000000000000000</double> </property> + <property name="sliderColor" > + <color> + <red>128</red> + <green>102</green> + <blue>86</blue> + </color> + </property> </widget> </item> <item> @@ -455,6 +462,198 @@ background-color: gray; </widget> </item> <item> + <widget class="QGroupBox" name="rotaryOn" > + <property name="title" > + <string>RotarySpeaker (test)</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <layout class="QGridLayout" > + <item row="0" column="0" > + <widget class="Awl::Knob" name="rot1Freq" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="scaleWidth" > + <number>5</number> + </property> + <property name="scaleValueColor" > + <color> + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </property> + <property name="maxValue" > + <double>127.000000000000000</double> + </property> + <property name="lineStep" > + <double>8.000000000000000</double> + </property> + <property name="pageStep" > + <double>20.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="Awl::Knob" name="rot1Depth" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="scaleWidth" > + <number>5</number> + </property> + <property name="scaleValueColor" > + <color> + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </property> + <property name="maxValue" > + <double>127.000000000000000</double> + </property> + <property name="lineStep" > + <double>8.000000000000000</double> + </property> + <property name="pageStep" > + <double>20.000000000000000</double> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_5" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>f1</string> + </property> + <property name="alignment" > + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QLabel" name="label_6" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>depth1</string> + </property> + <property name="alignment" > + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="Awl::Knob" name="rot2Freq" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="scaleWidth" > + <number>5</number> + </property> + <property name="scaleValueColor" > + <color> + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </property> + <property name="maxValue" > + <double>127.000000000000000</double> + </property> + <property name="lineStep" > + <double>8.000000000000000</double> + </property> + <property name="pageStep" > + <double>20.000000000000000</double> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="Awl::Knob" name="rot2Depth" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="scaleWidth" > + <number>5</number> + </property> + <property name="scaleValueColor" > + <color> + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </property> + <property name="maxValue" > + <double>127.000000000000000</double> + </property> + <property name="lineStep" > + <double>8.000000000000000</double> + </property> + <property name="pageStep" > + <double>20.000000000000000</double> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="label_7" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>f2</string> + </property> + <property name="alignment" > + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="3" column="1" > + <widget class="QLabel" name="label_8" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>depth2</string> + </property> + <property name="alignment" > + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> <spacer> <property name="orientation" > <enum>Qt::Horizontal</enum> diff --git a/muse/synti/organ/reverb.cpp b/muse/synti/organ/reverb.cpp index 18376a8f..72775bc5 100644 --- a/muse/synti/organ/reverb.cpp +++ b/muse/synti/organ/reverb.cpp @@ -143,7 +143,7 @@ void Reverb::process(float* l, float* r, int n) for (int i = 0; i < n; ++i) { float outL = 0.0; float outR = 0.0; - float input = l[i] * gain; + float input = (l[i] + r[i]) * gain; // Accumulate comb filters in parallel for (int k = 0; k < numcombs; k++) { @@ -157,7 +157,7 @@ void Reverb::process(float* l, float* r, int n) outR = allpassR[k].process(outR); } l[i] = outL * wet + l[i] * dry; - r[i] = outR * wet + l[i] * dry; + r[i] = outR * wet + r[i] * dry; } } |