summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse/synti/organ/organ.cpp139
-rw-r--r--muse/synti/organ/organ.h23
-rw-r--r--muse/synti/organ/organgui.ui203
-rw-r--r--muse/synti/organ/reverb.cpp4
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;
}
}