diff --git a/README.md b/README.md
index eb8d4d4..6d54c22 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,11 @@
ChangeLog
````
+== 2024-12-07
+ * Bugfix:
+ * EnvFollower - IO-page AUX input
+ * Enhancements:
+ * EnvFollower - mode Follower, Vactrol (based on MU Streams)
== 2024-11-30
* Bugfix:
* Crash on patch saving/restoring (#97)
diff --git a/app/CV/EnvFollower.bin b/app/CV/EnvFollower.bin
new file mode 100644
index 0000000..433a494
Binary files /dev/null and b/app/CV/EnvFollower.bin differ
diff --git a/app/CV/EnvFollower.cpp b/app/CV/EnvFollower.cpp
new file mode 100644
index 0000000..bd2081e
--- /dev/null
+++ b/app/CV/EnvFollower.cpp
@@ -0,0 +1,134 @@
+// Copyright (C)2021 - E.Heidt
+//
+// Author: E.Heidt (eh2k@gmx.de)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+
+#include "../squares-and-circles-api.h"
+#include
+#include "../../lib/streams/follower.h"
+#include "../../lib/streams/vactrol.h"
+#include "../../lib/streams/audio_cv_meter.h"
+
+streams::Follower _follower;
+streams::Vactrol _vactrol;
+streams::AudioCvMeter _meter;
+
+int32_t attack_ = 0;
+int32_t decay_ = 0;
+int32_t mode_ = 0;
+
+namespace gfx
+{
+ uint8_t i = 0;
+ int8_t scope[128] = {};
+ void drawScope(int x0, int y)
+ {
+ for (int x = x0; x < 127; x++)
+ {
+ if (x % 3 == 0)
+ gfx::setPixel(x, y);
+ gfx::drawLine(x, y - scope[(i + x) % 128], x + 1, y - scope[(1 + i + x) % 128]);
+ }
+ }
+
+ void push_scope(int8_t y)
+ {
+ scope[i++ % 128] = y;
+ if (i > 128)
+ i = 0;
+ }
+}
+
+const char *mode_names[] = {
+ "Follower",
+ "Vactrol",
+ ""};
+
+void engine::setup()
+{
+ engine::addParam("Attack", &attack_, 0, UINT16_MAX);
+ engine::addParam("MODE", &mode_, 0, 1, mode_names);
+ engine::addParam("Decay", &decay_, 0, INT16_MAX);
+ decay_ = INT16_MAX / 2;
+ engine::setMode(ENGINE_MODE_COMPACT | ENGINE_MODE_CV_OUT);
+
+ _meter.Init();
+ _follower.Init();
+ _vactrol.Init();
+}
+
+void engine::process()
+{
+ auto inputL = engine::inputBuffer<0>();
+ auto outputL = engine::outputBuffer_i16<0>();
+
+ uint16_t gain;
+ uint16_t freq;
+
+ int32_t paramters[3] = {};
+ int32_t globals[3] = {};
+ globals[0] = attack_;
+ globals[2] = decay_;
+ paramters[1] = 0;
+
+ if (mode_ == 0)
+ {
+ _follower.Configure(false, paramters, globals);
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
+ {
+ _follower.Process(0, inputL[i] * INT16_MAX, &gain, &freq);
+ outputL[i] = gain >> 2; //_follower.process(inputL[i]) * 10.f;
+ }
+ }
+ else
+ {
+ _vactrol.Configure(false, paramters, globals);
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
+ {
+ _vactrol.Process(0, inputL[i] * INT16_MAX, &gain, &freq);
+ outputL[i] = gain >> 2; //_follower.process(inputL[i]) * 10.f;
+ }
+ }
+
+ _meter.Process(inputL[0] * INT16_MAX);
+
+ if ((engine::t() % 50) == 0)
+ {
+ int8_t v = outputL[0] >> 9;
+ CONSTRAIN(v, 0, 14);
+ gfx::push_scope(v);
+ }
+}
+
+void engine::draw()
+{
+ gfx::drawScope(64, 58);
+ gfx::drawRect(64, 44, 64, 15);
+ gfx::drawRect(0, 44, 63, 15);
+ gfx::fillRect(2, 46, (_meter.peak() >> 8), 11);
+}
+
+#include "../../lib/streams/svf.cc"
+#include "../../lib/streams/follower.cc"
+#include "../../lib/streams/vactrol.cc"
+#include "../../lib/streams/resources.cc"
\ No newline at end of file
diff --git a/app/CV/EnvGen.bin b/app/CV/EnvGen.bin
new file mode 100644
index 0000000..a240f7d
Binary files /dev/null and b/app/CV/EnvGen.bin differ
diff --git a/app/CV/EnvGen.cpp b/app/CV/EnvGen.cpp
new file mode 100644
index 0000000..eeb08ff
--- /dev/null
+++ b/app/CV/EnvGen.cpp
@@ -0,0 +1,139 @@
+// Copyright (C)2021 - E.Heidt
+//
+// Author: E.Heidt (eh2k@gmx.de)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+
+// ENGINE_NAME:CV/EnvGen_AD;CV/EnvGen_ADSR
+// build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16
+
+#include "../squares-and-circles-api.h"
+#include "lib/peaks/modulations/multistage_envelope.h"
+
+#include "lib/peaks/modulations/multistage_envelope.cc"
+#include "lib/peaks/resources.cc"
+
+peaks::MultistageEnvelope _processor;
+
+int32_t _attack = 0;
+int32_t _decay = UINT16_MAX / 2;
+int32_t _sustain = UINT16_MAX / 2;
+int32_t _release = UINT16_MAX / 2;
+
+struct
+{
+ int8_t scope[128] = {};
+ int i = 0;
+
+ void draw(int y)
+ {
+ for (int x = 0; x < 127; x++)
+ {
+ if (x % 3 == 0)
+ gfx::setPixel(x, y);
+ gfx::drawLine(x, y - scope[(i + x) % 128], x + 1, y - scope[(1 + i + x) % 128]);
+ }
+ }
+
+ void push(int y)
+ {
+ scope[i++ % 128] = y;
+ if (i > 127)
+ i = 0;
+ }
+} _scope;
+
+void engine::setup()
+{
+ _processor.Init();
+
+ engine::addParam("Attack", &_attack, 0, UINT16_MAX);
+ engine::addParam("Decay", &_decay, 0, UINT16_MAX);
+
+ if (!strcmp(engine::name(), "CV/EnvGen_ADSR"))
+ {
+ engine::addParam("Sustain", &_sustain, 0, UINT16_MAX);
+ engine::addParam("Release", &_release, 0, UINT16_MAX);
+ }
+ else
+ {
+ // AD - Mode
+ _sustain = -1;
+ _release = -1;
+ }
+ engine::setMode(ENGINE_MODE_COMPACT | ENGINE_MODE_CV_OUT);
+}
+
+void engine::process()
+{
+ peaks::GateFlags flags[FRAME_BUFFER_SIZE];
+
+ uint16_t params[4];
+ params[0] = _attack;
+ params[1] = _decay;
+ if (_sustain >= 0)
+ {
+ params[2] = _sustain;
+ params[3] = _release;
+ _processor.Configure(params, peaks::CONTROL_MODE_FULL);
+ }
+ else
+ {
+ // AD - Mode
+ _processor.Configure(params, peaks::CONTROL_MODE_HALF);
+ }
+
+ if (engine::trig())
+ {
+ flags[0] = peaks::GATE_FLAG_RISING;
+ std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH);
+ }
+ else if (engine::gate())
+ {
+ std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH);
+ }
+ else
+ {
+ flags[0] = flags[0] == peaks::GATE_FLAG_HIGH ? peaks::GATE_FLAG_FALLING : peaks::GATE_FLAG_LOW;
+ std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW);
+ }
+
+ int16_t *buffer = engine::outputBuffer_i16<0>();
+ _processor.Process(flags, buffer, FRAME_BUFFER_SIZE);
+
+ static int y = 0;
+ if ((engine::t() % 50) == 0)
+ {
+ _scope.push(y);
+ y = 0;
+ }
+ else
+ y = std::max(y, buffer[0] / (INT16_MAX / 16));
+
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
+ buffer[i] /= 2;
+}
+
+void engine::draw()
+{
+ _scope.draw(56);
+}
\ No newline at end of file
diff --git a/app/CV/EnvGen_ADSR.bin b/app/CV/EnvGen_ADSR.bin
index c818c19..abea342 100644
Binary files a/app/CV/EnvGen_ADSR.bin and b/app/CV/EnvGen_ADSR.bin differ
diff --git a/app/CV/LFO.bin b/app/CV/LFO.bin
new file mode 100644
index 0000000..1e79817
Binary files /dev/null and b/app/CV/LFO.bin differ
diff --git a/app/CV/LFO.cpp b/app/CV/LFO.cpp
new file mode 100644
index 0000000..705898f
--- /dev/null
+++ b/app/CV/LFO.cpp
@@ -0,0 +1,125 @@
+// Copyright (C)2021 - E.Heidt
+//
+// Author: E.Heidt (eh2k@gmx.de)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+
+// build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16
+
+#include "../squares-and-circles-api.h"
+#include "lib/peaks/modulations/lfo.h"
+
+#include "lib/peaks/modulations/lfo.cc"
+#include "lib/peaks/resources.cc"
+#include "lib/stmlib/utils/random.cc"
+
+peaks::Lfo _processor;
+
+int32_t shape = peaks::LFO_SHAPE_SINE;
+int32_t rate = -INT16_MIN;
+int32_t waveform = -INT16_MIN;
+float scale = 0.5f;
+float offset = 0;
+
+const char *shape_names[] = {"SIN", "TRI", "SQR", "STEPS", "NOISE"};
+
+struct
+{
+ int8_t scope[128] = {};
+ int i = 0;
+
+ void draw(int x0, int y)
+ {
+ for (int x = x0; x < 127; x++)
+ {
+ if (x % 3 == 0)
+ gfx::setPixel(x, y);
+ gfx::drawLine(x, y - scope[(i + x) % 128], x + 1, y - scope[(1 + i + x) % 128]);
+ }
+ }
+
+ void push(int y)
+ {
+ scope[i++ % 128] = y;
+ if (i > 127)
+ i = 0;
+ }
+} _scope;
+
+void engine::setup()
+{
+ _processor.Init();
+ _processor.set_level(UINT16_MAX);
+ _processor.set_rate(rate);
+ _processor.set_parameter((waveform - 32768));
+ _processor.set_reset_phase(-INT16_MIN - 32768);
+
+ engine::addParam("Freq.", &rate, 0, UINT16_MAX);
+ engine::addParam("Shape", &shape, 0, peaks::LFO_SHAPE_LAST - 1, shape_names);
+ engine::addParam("Scale", &scale, -0.5f, 0.5f);
+ engine::addParam("Wavefrm", &waveform, 0, UINT16_MAX);
+ engine::addParam("Offset", &offset, -1, 1);
+
+ engine::setMode(ENGINE_MODE_COMPACT | ENGINE_MODE_CV_OUT);
+}
+
+void engine::process()
+{
+ peaks::GateFlags flags[FRAME_BUFFER_SIZE];
+
+ _processor.set_shape((peaks::LfoShape)shape);
+ _processor.set_rate(rate);
+ _processor.set_parameter((waveform - 32768));
+
+ if (engine::trig())
+ {
+ flags[0] = peaks::GATE_FLAG_RISING;
+ std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH);
+ }
+ else if (engine::gate())
+ {
+ std::fill(&flags[0], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_HIGH);
+ }
+ else
+ {
+ flags[0] = flags[0] == peaks::GATE_FLAG_HIGH ? peaks::GATE_FLAG_FALLING : peaks::GATE_FLAG_LOW;
+ std::fill(&flags[1], &flags[FRAME_BUFFER_SIZE], peaks::GATE_FLAG_LOW);
+ }
+
+ int16_t *buffer = engine::outputBuffer_i16<0>();
+ _processor.Process(flags, buffer, FRAME_BUFFER_SIZE);
+
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
+ {
+ buffer[i] >>= 1;
+ buffer[i] *= scale;
+ buffer[i] += (offset * PITCH_PER_OCTAVE * 5);
+ }
+
+ if ((engine::t() % 50) == 0)
+ _scope.push(buffer[0] >> 10);
+}
+
+void engine::draw()
+{
+ _scope.draw(64, 51);
+}
\ No newline at end of file
diff --git a/app/CV/V_OCT.bin b/app/CV/V_OCT.bin
new file mode 100644
index 0000000..0246cf1
Binary files /dev/null and b/app/CV/V_OCT.bin differ
diff --git a/app/CV/V_OCT.cpp b/app/CV/V_OCT.cpp
new file mode 100644
index 0000000..e8fffa6
--- /dev/null
+++ b/app/CV/V_OCT.cpp
@@ -0,0 +1,88 @@
+// Copyright (C)2021 - E.Heidt
+//
+// Author: E.Heidt (eh2k@gmx.de)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+
+// ENGINE_NAME: CV/V/OCT
+
+#include "../squares-and-circles-api.h"
+#include
+
+#define ONE_POLE(out, in, coefficient) out += (coefficient) * ((in) - out);
+
+float note = 0;
+int32_t tune = 128;
+int32_t cv0 = 0;
+int16_t cv_ = 0;
+float glide = 0;
+
+namespace gfx
+{
+ uint8_t i = 0;
+ int8_t scope[128] = {};
+ void drawScope(int x0, int y)
+ {
+ for (int x = x0; x < 127; x++)
+ {
+ if (x % 3 == 0)
+ gfx::setPixel(x, y);
+ gfx::drawLine(x, y - scope[(i + x) % 128], x + 1, y - scope[(1 + i + x) % 128]);
+ }
+ }
+
+ void push_scope(int8_t y)
+ {
+ scope[i++ % 128] = y;
+ if (i > 128)
+ i = 0;
+ }
+}
+
+void engine::setup()
+{
+ engine::addParam(V_OCT, ¬e);
+ engine::addParam("Fine", &tune, 0, 254);
+ engine::addParam("Slew", &glide, 0, 0.5f);
+ engine::setMode(ENGINE_MODE_COMPACT | ENGINE_MODE_CV_OUT);
+}
+
+void engine::process()
+{
+ cv0 = engine::qz_process(PITCH_PER_OCTAVE * 2 + engine::cv_i32(), 0, nullptr) // note is added internal
+ + (((int)tune - 128) << 2);
+
+ ONE_POLE(cv_, cv0, powf(1 - glide, 10));
+
+ std::fill_n(engine::outputBuffer_i16<0>(), FRAME_BUFFER_SIZE, cv_);
+
+ if ((engine::t() % 50) == 0)
+ gfx::push_scope((float)cv_ / PITCH_PER_OCTAVE * 4);
+}
+
+void engine::draw()
+{
+ char tmp[64];
+ sprintf(tmp, "OUT:%.2fV", ((float)cv_ / PITCH_PER_OCTAVE));
+ gfx::drawString(4 + 64, 32, tmp, 0);
+ gfx::drawScope(0, 50);
+}
diff --git a/app/DRUMS/808ish-BD.bin b/app/DRUMS/808ish-BD.bin
index ea5b9d5..9423a4e 100644
Binary files a/app/DRUMS/808ish-BD.bin and b/app/DRUMS/808ish-BD.bin differ
diff --git a/app/DRUMS/808ish-BD.cpp b/app/DRUMS/808ish-BD.cpp
index 65ef64d..00f8ff6 100644
--- a/app/DRUMS/808ish-BD.cpp
+++ b/app/DRUMS/808ish-BD.cpp
@@ -26,9 +26,7 @@
// build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16
#include "../squares-and-circles-api.h"
-#include "peaks/drums/bass_drum.h"
-#include "peaks/drums/bass_drum.cc"
-#include "resources/peaks_lut_svf.hpp"
+#include "lib/peaks/drums/bass_drum.h"
peaks::BassDrum _processor;
@@ -72,4 +70,7 @@ void engine::process()
}
_processor.Process(flags, engine::outputBuffer_i16<0>(), FRAME_BUFFER_SIZE);
-}
\ No newline at end of file
+}
+
+#include "lib/peaks/drums/bass_drum.cc"
+#include "lib/peaks/resources.cc"
diff --git a/app/DRUMS/808ish-HiHat.bin b/app/DRUMS/808ish-HiHat.bin
index 7f0039f..cbfcc01 100644
Binary files a/app/DRUMS/808ish-HiHat.bin and b/app/DRUMS/808ish-HiHat.bin differ
diff --git a/app/DRUMS/808ish-HiHat.cpp b/app/DRUMS/808ish-HiHat.cpp
index 5875b1a..fbcd0bb 100644
--- a/app/DRUMS/808ish-HiHat.cpp
+++ b/app/DRUMS/808ish-HiHat.cpp
@@ -23,13 +23,12 @@
// See http://creativecommons.org/licenses/MIT/ for more information.
//
+// build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 -ffast-math
+
#include "../squares-and-circles-api.h"
#define private public
-#include "peaks/drums/high_hat.h"
-#include "peaks/drums/high_hat.cc"
-#include "resources/peaks_lut_svf.hpp"
-#include "braids/envelope.h"
-#include "resources/braids_lut_env.hpp"
+#include "lib/peaks/drums/high_hat.h"
+#include "lib/braids/envelope.h"
peaks::HighHat _oh;
peaks::HighHat _ch;
@@ -96,4 +95,8 @@ void engine::process()
for (size_t i = 0; i < FRAME_BUFFER_SIZE; i++)
engine::outputBuffer<0>()[i] += (float)buffer[i] / INT16_MAX * oh_ad;
-}
\ No newline at end of file
+}
+
+#include "lib/peaks/drums/high_hat.cc"
+#include "lib/peaks/resources.cc"
+#include "lib/braids/resources.cc"
\ No newline at end of file
diff --git a/app/DRUMS/808ish-SD.bin b/app/DRUMS/808ish-SD.bin
index 383bf61..d8fd96a 100644
Binary files a/app/DRUMS/808ish-SD.bin and b/app/DRUMS/808ish-SD.bin differ
diff --git a/app/DRUMS/808ish-SD.cpp b/app/DRUMS/808ish-SD.cpp
index 902b345..fe5c9c2 100644
--- a/app/DRUMS/808ish-SD.cpp
+++ b/app/DRUMS/808ish-SD.cpp
@@ -23,11 +23,10 @@
// See http://creativecommons.org/licenses/MIT/ for more information.
//
+// build_flags: -fno-inline -mfloat-abi=hard -mfpu=fpv5-d16 -ffast-math
+
#include "../squares-and-circles-api.h"
-#include "peaks/drums/snare_drum.h"
-#include "peaks/drums/snare_drum.cc"
-#include "stmlib/utils/random.cc"
-#include "resources/peaks_lut_svf.hpp"
+#include "lib/peaks/drums/snare_drum.h"
peaks::SnareDrum _processor;
@@ -72,4 +71,8 @@ void engine::process()
}
_processor.Process(flags, engine::outputBuffer_i16<0>(), FRAME_BUFFER_SIZE);
-}
\ No newline at end of file
+}
+
+#include "lib/peaks/drums/snare_drum.cc"
+#include "lib/stmlib/utils/random.cc"
+#include "lib/peaks/resources.cc"
diff --git a/app/DRUMS/Djembe.bin b/app/DRUMS/Djembe.bin
index df3e3c5..fce4de5 100644
Binary files a/app/DRUMS/Djembe.bin and b/app/DRUMS/Djembe.bin differ
diff --git a/app/DRUMS/FM-Drum.bin b/app/DRUMS/FM-Drum.bin
index c747b5d..8b1b78c 100644
Binary files a/app/DRUMS/FM-Drum.bin and b/app/DRUMS/FM-Drum.bin differ
diff --git a/app/DRUMS/FM-Drum.cpp b/app/DRUMS/FM-Drum.cpp
index b1a2288..93a640c 100644
--- a/app/DRUMS/FM-Drum.cpp
+++ b/app/DRUMS/FM-Drum.cpp
@@ -24,11 +24,10 @@
//
#include "../squares-and-circles-api.h"
-#include "peaks/drums/fm_drum.h"
-#include "peaks/drums/fm_drum.cc"
-#include "resources/peaks_lut_osc.hpp"
-#include "resources/peaks_lut_env.hpp"
-#include "stmlib/utils/random.cc"
+#include "lib/peaks/drums/fm_drum.h"
+#include "lib/peaks/drums/fm_drum.cc"
+#include "lib/peaks/resources.cc"
+#include "lib/stmlib/utils/random.cc"
static peaks::FmDrum _processor;
diff --git a/app/DRUMS/TR707.bin b/app/DRUMS/TR707.bin
index e493825..e3878fd 100644
Binary files a/app/DRUMS/TR707.bin and b/app/DRUMS/TR707.bin differ
diff --git a/app/DRUMS/TR909-HiHat.bin b/app/DRUMS/TR909-HiHat.bin
index 9810530..5b1df88 100644
Binary files a/app/DRUMS/TR909-HiHat.bin and b/app/DRUMS/TR909-HiHat.bin differ
diff --git a/app/DRUMS/TR909-Ride.bin b/app/DRUMS/TR909-Ride.bin
index 2f6c03f..4074f2b 100644
Binary files a/app/DRUMS/TR909-Ride.bin and b/app/DRUMS/TR909-Ride.bin differ
diff --git a/app/FX/Delay.bin b/app/FX/Delay.bin
index e75b100..8f87b36 100644
Binary files a/app/FX/Delay.bin and b/app/FX/Delay.bin differ
diff --git a/app/FX/Gated-Reverb.bin b/app/FX/Gated-Reverb.bin
index b1acd91..8953a68 100644
Binary files a/app/FX/Gated-Reverb.bin and b/app/FX/Gated-Reverb.bin differ
diff --git a/app/FX/JU60_chorus.bin b/app/FX/JU60_chorus.bin
index 8871caa..c08ce8c 100644
Binary files a/app/FX/JU60_chorus.bin and b/app/FX/JU60_chorus.bin differ
diff --git a/app/FX/Rev-Dattorro.bin b/app/FX/Rev-Dattorro.bin
index d88ba96..65ceb21 100644
Binary files a/app/FX/Rev-Dattorro.bin and b/app/FX/Rev-Dattorro.bin differ
diff --git a/app/FX/Reverb-HP-LP.bin b/app/FX/Reverb-HP-LP.bin
index d25e2c1..618243c 100644
Binary files a/app/FX/Reverb-HP-LP.bin and b/app/FX/Reverb-HP-LP.bin differ
diff --git a/app/FX/Reverb.bin b/app/FX/Reverb.bin
index 597bbb5..1615135 100644
Binary files a/app/FX/Reverb.bin and b/app/FX/Reverb.bin differ
diff --git a/app/FX/ReverbSC.bin b/app/FX/ReverbSC.bin
index ab477dc..e451b25 100644
Binary files a/app/FX/ReverbSC.bin and b/app/FX/ReverbSC.bin differ
diff --git a/app/GND/FFT.bin b/app/GND/FFT.bin
index 753c111..611ed7b 100644
Binary files a/app/GND/FFT.bin and b/app/GND/FFT.bin differ
diff --git a/app/GND/Scope.bin b/app/GND/Scope.bin
index e93f583..76e1ba3 100644
Binary files a/app/GND/Scope.bin and b/app/GND/Scope.bin differ
diff --git a/app/M-OSC/Waveforms.bin b/app/M-OSC/Waveforms.bin
index f4d5fc4..e520ae2 100644
Binary files a/app/M-OSC/Waveforms.bin and b/app/M-OSC/Waveforms.bin differ
diff --git a/app/MIDI/Clock.bin b/app/MIDI/Clock.bin
index 6029d3f..6aa3b62 100644
Binary files a/app/MIDI/Clock.bin and b/app/MIDI/Clock.bin differ
diff --git a/app/MIDI/Monitor.bin b/app/MIDI/Monitor.bin
index 058073b..1191b7e 100644
Binary files a/app/MIDI/Monitor.bin and b/app/MIDI/Monitor.bin differ
diff --git a/app/MIDI/VAx6.bin b/app/MIDI/VAx6.bin
index 32ab387..361ca02 100644
Binary files a/app/MIDI/VAx6.bin and b/app/MIDI/VAx6.bin differ
diff --git a/app/NOISE/808_squares.bin b/app/NOISE/808_squares.bin
index f644671..c332bf4 100644
Binary files a/app/NOISE/808_squares.bin and b/app/NOISE/808_squares.bin differ
diff --git a/app/NOISE/NES.bin b/app/NOISE/NES.bin
index bfd9961..571ae36 100644
Binary files a/app/NOISE/NES.bin and b/app/NOISE/NES.bin differ
diff --git a/app/NOISE/WhitePink.bin b/app/NOISE/WhitePink.bin
index 32bad21..ba8ecf2 100644
Binary files a/app/NOISE/WhitePink.bin and b/app/NOISE/WhitePink.bin differ
diff --git a/app/SEQ/EuclidArp.bin b/app/SEQ/EuclidArp.bin
index 05f1b2a..b53bdee 100644
Binary files a/app/SEQ/EuclidArp.bin and b/app/SEQ/EuclidArp.bin differ
diff --git a/app/SEQ/EuclidArp.cpp b/app/SEQ/EuclidArp.cpp
index 77ffba2..53a8776 100644
--- a/app/SEQ/EuclidArp.cpp
+++ b/app/SEQ/EuclidArp.cpp
@@ -25,20 +25,20 @@
//
#include "../squares-and-circles-api.h"
-#include "../lib/misc/euclidean.h"
+#include "lib/misc/euclidean.h"
#include "patterns_303.h"
#include
#include
-#include "../lib/plaits/dsp/engine2/arpeggiator.h"
+#include "lib/plaits/dsp/engine2/arpeggiator.h"
#define private public
#define SemitonesToRatioFast
-#include "../lib/plaits/dsp/chords/chord_bank.cc"
-#include "stmlib/utils/random.cc"
+#include "lib/plaits/dsp/chords/chord_bank.cc"
+#include "lib/stmlib/utils/random.cc"
-#include "../lib/stmlib/utils/dsp.h"
-#include "../DRUMS/resources/peaks_lut_env.hpp"
+#include "lib/stmlib/utils/dsp.h"
+#include "lib/peaks/resources.cc"
// This app is copiled with soft-fpu - for running on teensy3.2 & teensy 4.x
diff --git a/app/SEQ/EuclidRythm.bin b/app/SEQ/EuclidRythm.bin
index a7e418d..f81438b 100644
Binary files a/app/SEQ/EuclidRythm.bin and b/app/SEQ/EuclidRythm.bin differ
diff --git a/app/SEQ/TuringMachine.bin b/app/SEQ/TuringMachine.bin
index b47aec7..864cf92 100644
Binary files a/app/SEQ/TuringMachine.bin and b/app/SEQ/TuringMachine.bin differ
diff --git a/app/SPEECH/LPC.bin b/app/SPEECH/LPC.bin
index 47420e6..c3f8ba5 100644
Binary files a/app/SPEECH/LPC.bin and b/app/SPEECH/LPC.bin differ
diff --git a/app/SPEECH/SAM.bin b/app/SPEECH/SAM.bin
index c70e833..b9835fb 100644
Binary files a/app/SPEECH/SAM.bin and b/app/SPEECH/SAM.bin differ
diff --git a/app/SYNTH/DxFM.bin b/app/SYNTH/DxFM.bin
index 084fd15..86da76f 100644
Binary files a/app/SYNTH/DxFM.bin and b/app/SYNTH/DxFM.bin differ
diff --git a/app/SYNTH/DxFM.cpp b/app/SYNTH/DxFM.cpp
index 7241b41..66b8a4e 100644
--- a/app/SYNTH/DxFM.cpp
+++ b/app/SYNTH/DxFM.cpp
@@ -17,9 +17,6 @@
// ENGINE_NAME:SYNTH/DxFM;SYNTH/DxFM_BNK1-3
-#undef FLASHMEM
-#define FLASHMEM
-
#include "../squares-and-circles-api.h"
#include "stmlib/utils/ring_buffer.h"
#include "misc/dspinst.h"
@@ -39,6 +36,7 @@
#include
#include
+#include "plaits/resources.h"
struct dxfm
{
@@ -195,11 +193,11 @@ void engine::setup()
if (!strcmp(engine::name(), "SYNTH/DxFM_BNK1-3"))
{
- if (fm_patches_table[nprogs / 32] = machine::fs_read("DXFMSYXA"))
+ if (fm_patches_table[nprogs / 32] = plaits::fm_patches_table[0])
nprogs += 32;
- if (fm_patches_table[nprogs / 32] = machine::fs_read("DXFMSYXB"))
+ if (fm_patches_table[nprogs / 32] = plaits::fm_patches_table[1])
nprogs += 32;
- if (fm_patches_table[nprogs / 32] = machine::fs_read("DXFMSYXC"))
+ if (fm_patches_table[nprogs / 32] = plaits::fm_patches_table[2])
nprogs += 32;
}
else
@@ -396,4 +394,5 @@ void engine::draw()
#include "msfa/patch.cc"
#include "msfa/porta.cc"
#include "msfa/env.cc"
-#include "msfa/exp2.cc"
\ No newline at end of file
+#include "msfa/exp2.cc"
+#include "plaits/resources.cc"
\ No newline at end of file
diff --git a/app/SYNTH/Open303.bin b/app/SYNTH/Open303.bin
index 715d383..177437f 100644
Binary files a/app/SYNTH/Open303.bin and b/app/SYNTH/Open303.bin differ
diff --git a/app/SYNTH/Resonator.bin b/app/SYNTH/Resonator.bin
index 79f83dc..6ba59a9 100644
Binary files a/app/SYNTH/Resonator.bin and b/app/SYNTH/Resonator.bin differ
diff --git a/app/SYNTH/plaits.bin b/app/SYNTH/plaits.bin
new file mode 100644
index 0000000..f89fd3f
Binary files /dev/null and b/app/SYNTH/plaits.bin differ
diff --git a/app/SYNTH/plaits.cpp b/app/SYNTH/plaits.cpp
new file mode 100644
index 0000000..c7c72a1
--- /dev/null
+++ b/app/SYNTH/plaits.cpp
@@ -0,0 +1,488 @@
+// Copyright (C)2022 - E.Heidt
+//
+// Author: Eduard Heidt (eh2k@gmx.de)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+
+// ENGINE_NAME: M-OSC/Virt.Analog
+// ENGINE_NAME: M-OSC/Waveshaping
+// ENGINE_NAME: M-OSC/2-OP-FM
+// ENGINE_NAME: M-OSC/Formant/PD
+// ENGINE_NAME: M-OSC/Harmonic
+// ENGINE_NAME: M-OSC/Wavetable
+// ENGINE_NAME: M-OSC/Chord
+// ENGINE_NAME: DRUMS/Analog BD
+// ENGINE_NAME: DRUMS/Analog SD
+// ENGINE_NAME: DRUMS/Analog HH2
+// ENGINE_NAME: DRUMS/Analog HH
+// ENGINE_NAME: DRUMS/909ish-BD
+// ENGINE_NAME: DRUMS/909ish-SD
+// ENGINE_NAME: SYNTH/ClassicVAVCF
+
+#include "../squares-and-circles-api.h"
+
+#include "stmlib/stmlib.h"
+#define private public // ;-)
+#include "plaits/dsp/voice.h"
+#include "stmlib/dsp/dsp.h"
+
+using namespace machine;
+
+plaits::Modulations modulations;
+plaits::Voice voice;
+plaits::Patch patch;
+
+float bufferOut[FRAME_BUFFER_SIZE];
+float bufferAux[FRAME_BUFFER_SIZE];
+float out_aux_mix = 0.5f;
+float _pitch = 0;
+float _base_pitch = DEFAULT_NOTE;
+
+struct
+{
+ int engine;
+ int output; // output=0 -> out, output=1 -> aux, output=3 -> stereo
+} _mode = {};
+
+uint8_t *_buffer = nullptr;
+plaits::Engine *_plaitsEngine = nullptr;
+
+constexpr int WAVETABLE_ENGINE = 5;
+constexpr int CHORD_ENGINE = 6;
+constexpr int CLASSIC_VAVCF_ENGINE = 16;
+
+void engine_free()
+{
+ free(_plaitsEngine);
+ free(_buffer);
+}
+
+template
+void alloc_engine(size_t mem = 48)
+{
+ _plaitsEngine = new (malloc(sizeof(T))) T();
+ _buffer = (uint8_t *)malloc(mem * sizeof(float));
+
+ stmlib::BufferAllocator allocator;
+ allocator.Init(_buffer, mem * sizeof(float));
+ _plaitsEngine->Init(&allocator);
+}
+
+float harmonics, timbre, morph;
+
+bool is_drum()
+{
+ return _mode.engine == 13 || _mode.engine == 14 || _mode.engine == 15;
+}
+
+void init_params(float hh, float tt, float mm, const plaits::PostProcessingSettings &settings)
+{
+ patch.harmonics = harmonics = hh;
+ patch.timbre = timbre = tt;
+ patch.morph = morph = mm;
+ if (_plaitsEngine)
+ _plaitsEngine->post_processing_settings = settings;
+}
+
+void engine::setup()
+{
+ const char *name = engine::name();
+
+ while (*name++ != '/')
+ ;
+
+ if (!strcmp(name, "Virt.Analog"))
+ _mode = {0, 0};
+ else if (!strcmp(name, "Waveshaping"))
+ _mode = {1, 0};
+ else if (!strcmp(name, "2-OP-FM"))
+ _mode = {2, 0};
+ else if (!strcmp(name, "Formant/PD"))
+ _mode = {3, 2};
+ else if (!strcmp(name, "Harmonic"))
+ _mode = {4, 2};
+ else if (!strcmp(name, "Wavetable"))
+ _mode = {5, 2};
+ else if (!strcmp(name, "Chord"))
+ _mode = {6, 0};
+ else if (!strcmp(name, "Analog BD"))
+ _mode = {13, 0};
+ else if (!strcmp(name, "Analog SD"))
+ _mode = {14, 0};
+ else if (!strcmp(name, "Analog HH2"))
+ _mode = {15, 1};
+ else if (!strcmp(name, "Analog HH"))
+ _mode = {15, 0};
+ else if (!strcmp(name, "909ish-BD"))
+ _mode = {13, 1};
+ else if (!strcmp(name, "909ish-SD"))
+ _mode = {14, 1};
+ else if (!strcmp(name, "ClassicVAVCF"))
+ _mode = {16, 2};
+ else
+ _mode = {0, 0};
+
+ voice.Init();
+ patch.engine = 0;
+ memset(&patch, 0, sizeof(patch));
+ patch.note = DEFAULT_NOTE + _pitch * 12.f;
+
+ modulations.timbre_patched = true;
+ patch.timbre_modulation_amount = 0;
+
+ modulations.frequency_patched = true;
+ patch.frequency_modulation_amount = 0;
+
+ modulations.morph_patched = true;
+ patch.morph_modulation_amount = 0;
+
+ memset(&modulations, 0, sizeof(modulations));
+
+ patch.lpg_colour = 0.5;
+ patch.decay = 0.5;
+ modulations.trigger_patched = true; // trigger;
+ // modulations.level_patched = true;
+ // modulations.level = 1;
+
+ switch (_mode.engine)
+ {
+ case 0:
+ alloc_engine();
+ init_params(0.5f, 0.5f, 0.5f, {0.8f, 0.8f, false});
+ engine::addParam(V_OCT, &_pitch);
+ engine::addParam("Detune", &harmonics);
+ engine::addParam("Square", &timbre);
+ engine::addParam("CSAW", &morph);
+ engine::addParam("Decay", &patch.decay);
+ if (_mode.output == 2)
+ engine::addParam("AuxMix", &out_aux_mix, out_aux_mix);
+ else
+ engine::addParam("Color", &patch.lpg_colour);
+ break;
+ case 1:
+ alloc_engine();
+ init_params(0.8f, 0.8f, 0.75f, {0.7f, 0.6f, false});
+ engine::addParam(V_OCT, &_pitch);
+ engine::addParam("Waveform", &harmonics);
+ engine::addParam("Fold", &timbre);
+ engine::addParam("Asym", &morph);
+ engine::addParam("Decay", &patch.decay);
+ if (_mode.output == 2)
+ engine::addParam("AuxMix", &out_aux_mix, out_aux_mix);
+ else
+ engine::addParam("Color", &patch.lpg_colour);
+ break;
+ case 2:
+ alloc_engine();
+ init_params(0.8f, 0.8f, 0.75f, {0.6f, 0.6f, false});
+ engine::addParam(V_OCT, &_pitch);
+ engine::addParam("Ratio", &harmonics);
+ engine::addParam("Mod", &timbre);
+ engine::addParam("Feedb.", &morph);
+ engine::addParam("Decay", &patch.decay);
+ if (_mode.output == 2)
+ engine::addParam("AuxMix", &out_aux_mix, out_aux_mix);
+ else
+ engine::addParam("Color", &patch.lpg_colour);
+ break;
+ case 3:
+ alloc_engine();
+ init_params(0.8f, 0.8f, 0.75f, {0.7f, 0.6f, false});
+ engine::addParam(V_OCT, &_pitch);
+ engine::addParam("Ratio", &harmonics);
+ engine::addParam("Frm/Fq.", &timbre);
+ engine::addParam("Width", &morph);
+ engine::addParam("Decay", &patch.decay);
+ engine::addParam("PD-Mix", &out_aux_mix, out_aux_mix);
+ break;
+ case 4:
+ alloc_engine();
+ init_params(0.8f, 0.8f, 0.75f, {0.8f, 0.8f, false});
+ engine::addParam(V_OCT, &_pitch);
+ engine::addParam("Bump", &harmonics);
+ engine::addParam("Peak", &timbre);
+ engine::addParam("Shape", &morph);
+ engine::addParam("Decay", &patch.decay);
+ if (_mode.output == 2)
+ engine::addParam("AuxMix", &out_aux_mix, out_aux_mix);
+ else
+ engine::addParam("Color", &patch.lpg_colour);
+ break;
+ case WAVETABLE_ENGINE:
+ alloc_engine(64 * sizeof(const int16_t *));
+ init_params(0.f, 0.8f, 0.75f, {0.6f, 0.6f, false});
+ engine::addParam(V_OCT, &_pitch);
+ engine::addParam("Bank", &harmonics, 0.f, 0.5f);
+ engine::addParam("Row", &timbre);
+ engine::addParam("Column", &morph);
+ engine::addParam("Decay", &patch.decay);
+ if (_mode.output == 2)
+ engine::addParam("AuxMix", &out_aux_mix, out_aux_mix);
+ else
+ engine::addParam("Color", &patch.lpg_colour);
+ _plaitsEngine->LoadUserData(nullptr);
+ break;
+ case CHORD_ENGINE:
+ {
+ alloc_engine(plaits::kChordNumChords * plaits::kChordNumNotes + plaits::kChordNumChords + plaits::kChordNumNotes);
+ init_params(0.5f, 0.5f, 0.5f, {0.8f, 0.8f, false});
+ engine::addParam(V_OCT, &_pitch);
+
+ int32_t *pchord = (int32_t *)&static_cast(_plaitsEngine)->chords_.chord_index_quantizer_.quantized_value_;
+ *pchord = 8;
+ engine::addParam("Chord", pchord, 0,
+ static_cast(_plaitsEngine)->chords_.chord_index_quantizer_.num_steps() - 1,
+ (const char **)plaits::chord_names);
+
+ engine::addParam("Inv.", &timbre);
+ engine::addParam("Shape", &morph);
+ engine::addParam("Decay", &patch.decay);
+ if (_mode.output == 2)
+ engine::addParam("AuxMix", &out_aux_mix, out_aux_mix);
+ else
+ engine::addParam("Color", &patch.lpg_colour);
+ }
+ break;
+ // case 15: // speech_engine_
+ // alloc_engine(false, 0.8f, 0.8f);
+ // break;
+ // case 8: // swarm_engine_
+ // alloc_engine(false, -3.0f, 1.0f);
+ // break;
+ // case 9: // noise_engine_
+ // alloc_engine(false, -1.0f, -1.0f);
+ // break;
+ // case 10: // particle_engine_
+ // alloc_engine(false, -2.0f, 1.0f);
+ // break;
+ // case 11: // string_engine_
+ // alloc_engine(true, -1.0f, 0.8f);
+ // break;
+ // case 12: // modal_engine_
+ // alloc_engine(true, -0.5f, 0.8f);
+ // break;
+ case 13:
+ _base_pitch += -24.f;
+ alloc_engine();
+ init_params(0.8f, 0.5f, 0.5f, {0.8f, 0.8f, true});
+ engine::addParam("Pitch", &_pitch, -1.f, 1.f);
+ engine::addParam(_mode.output == 0 ? "Drive" : "Punch", &harmonics);
+ engine::addParam("Tone", &timbre);
+ engine::addParam("Decay", &morph);
+ break;
+ case 14:
+ alloc_engine();
+ init_params(0.5f, 0.5f, 0.5f, {0.8f, 0.8f, true});
+ engine::addParam("Pitch", &_pitch, -1.f, 1.f);
+ engine::addParam("Snappy", &harmonics);
+ engine::addParam("Tone", &timbre);
+ engine::addParam("Decay", &morph);
+ break;
+ case 15:
+ alloc_engine();
+ init_params(0.5f, 0.9f, 0.6f, {0.8f, 0.8f, true});
+ engine::addParam("Pitch", &_pitch, -1.f, 1.f);
+ engine::addParam("Noise", &harmonics);
+ engine::addParam("Tone", &timbre);
+ engine::addParam("Decay", &morph);
+ break;
+ // engines 2
+ case CLASSIC_VAVCF_ENGINE:
+ alloc_engine();
+ init_params(0.5f, 0.5f, 0.5f, {1.f, 1.f, false});
+ engine::addParam(V_OCT, &_pitch);
+ engine::addParam("Morph", &morph);
+ engine::addParam("Cutoff", &timbre);
+ engine::addParam("Harsh", &harmonics);
+ out_aux_mix = 0;
+ modulations.timbre_patched = false;
+ patch.timbre_modulation_amount = 0;
+ engine::addParam("EnvMod", &patch.timbre_modulation_amount, -1.f, 1.f);
+ patch.decay = 0.5f;
+ engine::addParam("Decay", &patch.decay, 0.f, 0.99f);
+ break;
+#if 0 //TODO....
+ case 17:
+ alloc_engine(plaits::kMaxBlockSize * 4);
+ _plaitsEngine->post_processing_settings = {0.7f, 0.7f, false};
+ break;
+ case 18:
+ case 19:
+ case 20:
+ alloc_engine(
+ plaits::kMaxBlockSize * 4 + plaits::kMaxBlockSize * plaits::kNumSixOpVoices + sizeof(plaits::fm::Patch) * 96 / sizeof(float));
+ init_params("", 0.0f, "Mod", 0.5f, "Env", 0.5f, {1.f, 1.f, false});
+ param[1].init_presets("Preset", &static_cast(_plaitsEngine)->patch_index, 0, 0, 95);
+ param[1].print_value = [&](char *name)
+ {
+ auto i = static_cast(_plaitsEngine)->patch_index;
+ sprintf(name, ">%.10s", static_cast(_plaitsEngine)->patches_[i].name);
+ };
+ _plaitsEngine->LoadUserData(plaits::fm_patches_table[0]);
+ modulations.morph_patched = false;
+ param[5].init("EnvMod", &patch.morph_modulation_amount, 0.0f, -1.f, 1.f);
+
+ modulations.timbre_patched = false;
+ param[4].init("ModMod", &patch.timbre_modulation_amount, 0.0f, -1.f, 1.f);
+ break;
+ case 21:
+ alloc_engine(plaits::kMaxBlockSize * 4);
+ _plaitsEngine->post_processing_settings = {0.7f, 0.7f, false};
+ patch.engine = (engine - 16);
+ break;
+ case 22:
+ alloc_engine(16 + 3 * (1024 + 265));
+ _plaitsEngine->post_processing_settings = {0.8f, 0.8f, false};
+ patch.engine = (engine - 16);
+ break;
+ case 23:
+ alloc_engine(plaits::kChordNumChords * plaits::kChordNumNotes + plaits::kChordNumChords + plaits::kChordNumNotes);
+ _plaitsEngine->post_processing_settings = {0.5f, 0.5f, false};
+ patch.engine = (engine - 16);
+ break;
+#endif
+ }
+
+ if (_mode.engine >= 16)
+ patch.engine = (_mode.engine - 16);
+
+ _plaitsEngine->Reset();
+}
+
+void engine::process()
+{
+ float a = bufferOut[0] / 256.f;
+ ONE_POLE(patch.harmonics, harmonics + a, 0.1f);
+ ONE_POLE(patch.timbre, timbre + a, 0.1f);
+ ONE_POLE(patch.morph, morph + a, 0.1f);
+
+ modulations.level_patched = false;
+ modulations.level = 1.f;
+
+ patch.note = _base_pitch + engine::cv() * 12;
+
+ float last_decay = patch.decay;
+ float last_morph = patch.morph;
+ // if (!frame.trigger && frame.gate)
+ // {
+ // if (is_drum())
+ // patch.morph = 1;
+ // else
+ // patch.decay = 1;
+
+ // modulations.level = 1.f;
+ // // modulations.level_patched = true;
+ // }
+ modulations.engine = patch.engine;
+ modulations.trigger = engine::trig() ? 1 : 0;
+
+ if (!is_drum())
+ modulations.trigger_patched = patch.decay < 1.f;
+
+ if (!__io->tr)
+ {
+ modulations.trigger_patched = false;
+ modulations.level_patched = true;
+ modulations.level = patch.decay;
+ patch.decay = 0.001f;
+ }
+ else
+ {
+ modulations.trigger_patched = true;
+ }
+
+ modulations.note = 0;
+ voice.Render(_plaitsEngine, patch, modulations, bufferOut, bufferAux, FRAME_BUFFER_SIZE);
+
+ patch.decay = last_decay;
+ patch.morph = last_morph;
+
+ switch (_mode.output)
+ {
+ case 0:
+ std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<0>());
+ std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<1>());
+ break;
+ case 1:
+ std::copy_n(bufferAux, FRAME_BUFFER_SIZE, engine::outputBuffer<0>());
+ std::copy_n(bufferAux, FRAME_BUFFER_SIZE, engine::outputBuffer<1>());
+ break;
+ case 2:
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
+ bufferOut[i] = stmlib::Crossfade(bufferOut[i], bufferAux[i], out_aux_mix);
+ std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<0>());
+ std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<1>());
+ break;
+ case 3:
+ std::copy_n(bufferOut, FRAME_BUFFER_SIZE, engine::outputBuffer<0>());
+ std::copy_n(bufferAux, FRAME_BUFFER_SIZE, engine::outputBuffer<1>());
+ break;
+ }
+}
+
+void engine::draw()
+{
+ engine::setParamName(&patch.decay, __io->tr ? "Decay" : "Level");
+}
+
+#include "stmlib/utils/random.cc"
+#include "lib/stmlib/dsp/units.cc"
+
+//${SCRIPT_PATH}/main.cc $(find lib/plaits/ -type f -name "*.cc")
+
+#include "lib/plaits/resources.cc"
+// lib/plaits/dsp/speech/sam_speech_synth.cc
+// lib/plaits/dsp/speech/lpc_speech_synth_controller.cc
+// lib/plaits/dsp/speech/lpc_speech_synth_words.cc
+// lib/plaits/dsp/speech/lpc_speech_synth_phonemes.cc
+// lib/plaits/dsp/speech/naive_speech_synth.cc
+// lib/plaits/dsp/speech/lpc_speech_synth.cc
+#include "lib/plaits/dsp/engine/string_engine.cc"
+#include "lib/plaits/dsp/engine/swarm_engine.cc"
+#include "lib/plaits/dsp/engine/chord_engine.cc"
+#include "lib/plaits/dsp/engine/waveshaping_engine.cc"
+#include "lib/plaits/dsp/engine/modal_engine.cc"
+#include "lib/plaits/dsp/engine/fm_engine.cc"
+#include "lib/plaits/dsp/engine/snare_drum_engine.cc"
+// #include "lib/plaits/dsp/engine/speech_engine.cc"
+#include "lib/plaits/dsp/engine/grain_engine.cc"
+#include "lib/plaits/dsp/engine/virtual_analog_engine.cc"
+#include "lib/plaits/dsp/engine/wavetable_engine.cc"
+#include "lib/plaits/dsp/engine/additive_engine.cc"
+#include "lib/plaits/dsp/engine/noise_engine.cc"
+#include "lib/plaits/dsp/engine/hi_hat_engine.cc"
+#include "lib/plaits/dsp/engine/particle_engine.cc"
+#include "lib/plaits/dsp/engine/bass_drum_engine.cc"
+// lib/plaits/dsp/engine2/chiptune_engine.cc
+// lib/plaits/dsp/engine2/six_op_engine.cc
+// lib/plaits/dsp/engine2/wave_terrain_engine.cc
+// lib/plaits/dsp/engine2/string_machine_engine.cc
+// lib/plaits/dsp/engine2/phase_distortion_engine.cc
+#include "lib/plaits/dsp/engine2/virtual_analog_vcf_engine.cc"
+#include "lib/plaits/dsp/chords/chord_bank.cc"
+#include "lib/plaits/dsp/physical_modelling/string_voice.cc"
+#include "lib/plaits/dsp/physical_modelling/string.cc"
+#include "lib/plaits/dsp/physical_modelling/modal_voice.cc"
+#include "lib/plaits/dsp/physical_modelling/resonator.cc"
+#include "lib/plaits/dsp/fm/algorithms.cc"
+#include "lib/plaits/dsp/fm/dx_units.cc"
+#include "lib/plaits/dsp/voice.cc"
diff --git a/app/build.sh b/app/build.sh
index 130c6e7..3aba5a4 100755
--- a/app/build.sh
+++ b/app/build.sh
@@ -13,6 +13,7 @@ pip install jinja2 pyelftools elf_size_analyze --upgrade pip
if [[ "$1" == "--rebuild" ]]; then
find "${SCRIPT_PATH}/" -type f -name "*.bin" -print0 -exec touch {} +
+ rm -f ${SCRIPT_PATH}/apps.txt
fi
for f in $(find "${SCRIPT_PATH}" -mindepth 2 -maxdepth 2 -type f -name '*.cpp'); do
@@ -23,27 +24,29 @@ if [ -f $oo ] && [ "$(date -R -r $X.bin)" = "$(date -R -r $f)" ]; then
fi
#-fno-rtti
-NAME=$(grep "ENGINE_NAME:" $f | cut -d':' -f2)
+NAME="$(grep "ENGINE_NAME:" $f | cut -d':' -f2 | sed 's/^ *//g')"
+NAME=${NAME//$'\n'/';'} #replace \n with ''
NAME=${NAME:-"$(realpath --relative-to=${SCRIPT_PATH} $X)"}
echo ----- "$NAME" -----
mkmodule=$(ls lib/udynlink/scripts/mkmodule | head -n1)
-BUILD_FLAGS=$(grep "build_flags:" $X.cpp | cut -d':' -f2-)
+BUILD_FLAGS=$(grep "build_flags:" $X.cpp | cut -d':' -f2- | xargs)
BUILD_FLAGS=${BUILD_FLAGS:-"-mfloat-abi=hard -mfpu=fpv5-d16 -ffast-math"}
-echo "BUILD_FLAGS:$BUILD_FLAGS"
-CPP_FILES=$(grep "cpp_files:" $X.cpp | cut -d':' -f2-)
+echo "BUILD_FLAGS:$BUILD_FLAGS"
+SRC_FILES=$(grep "src_files" $X.cpp | cut -d':' -f2 | xargs)
+find "$(dirname $X.cpp)" -type f -name '*.o' -delete
#--no-opt \
#-felide-constructors -fno-rtti -std=gnu++14 -Wno-error=narrowing -fno-threadsafe-statics
-$mkmodule $(realpath $X.cpp --relative-base=.) $CPP_FILES \
+$mkmodule $(realpath $X.cpp --relative-base=.) \
--no-opt \
- --build_flags="-fsingle-precision-constant -DFLASHMEM='__attribute__((section(\".text.flashmem\")))' -DNDEBUG -pedantic -fno-exceptions $BUILD_FLAGS -I. -I./lib/ " \
+ --build_flags="-fsingle-precision-constant -DNDEBUG -pedantic -fno-exceptions $BUILD_FLAGS -I. -I./lib/ " \
--public-symbols="setup,process,draw,screensaver,__ui_event_handler,__midi_event_handler" \
- --name="$NAME" > $X.log
+ --name="$NAME" $SRC_FILES> $X.log
sed -i "s|$(realpath .)|.|" $X.log
touch -d "$(date -R -r $X.cpp)" $X.bin
@@ -52,13 +55,15 @@ touch -d "$(date -R -r $X.cpp)" $X.bin
arm-none-eabi-objdump -Dztr --source $X.elf | arm-none-eabi-c++filt -t > $X.elf.txt
#arm-none-eabi-nm -l -t d -S -C --size-sort --synthetic --special-syms --with-symbol-versions --reverse-sort ./$X.elf > $X.log
which elf-size-analyze >/dev/null && elf-size-analyze -t arm-none-eabi- $(realpath $X.elf --relative-base=.) -F -R --no-color >> $X.log
-md5sum $(realpath $X.bin --relative-base=.) | tee -a $X.log
-echo "BIN_SIZE $(stat -c %s -- $X.bin)" | tee -a $X.log
+${SCRIPT_PATH}/dump.py "$(realpath $X.bin --relative-base=.)" | tee -a $X.log
#rm $X.elf
+if [[ "$1" == "--rebuild" ]]; then
+ ${SCRIPT_PATH}/dump.py "$(realpath $X.bin --relative-base=.)" >> ${SCRIPT_PATH}/apps.txt
+fi
+
grep "__aeabi_" $X.log && exit 1
-${SCRIPT_PATH}/dump.py "$X.bin"
#xxd -i $X.bin > ./$X.bin.h
#sed -i "s/unsigned char/const uint8_t/g" ./$X.bin.h
diff --git a/app/dump.py b/app/dump.py
index bbe3659..731cab8 100755
--- a/app/dump.py
+++ b/app/dump.py
@@ -1,11 +1,16 @@
-#!/bin/python3 -u
+#!/usr/bin/env python3
-import sys, zlib
+import sys, zlib, hashlib
+
+def md5sum(data):
+ h = hashlib.md5()
+ h.update(data)
+ return h.hexdigest()
f = open(sys.argv[1], "rb")
data = f.read()
f.close()
-print(data[0:4]) # sign
+#print(data[0:4]) # sign
l = int.from_bytes(data[4:6], byteorder='little')#num_lot
r = int.from_bytes(data[6:8], byteorder='little'); #num_rels
a = int.from_bytes(data[8:12], byteorder='little'); #symt_size
@@ -14,11 +19,12 @@
d = int.from_bytes(data[20:24], byteorder='little'); #bss_size
h = 24 + (r * 8) + a
+print("---------------------------------------------")
print("FILE_NAME", f.name)
print("RAM_SIZE", (l * 4) + c + d)
print("BIN_SIZE", h + b + c)
print("FILE_LEN", len(data))
-
crc32sum = zlib.crc32(data[0:-1])
print("CRC32 %x" % crc32sum)
+print("MD5 %s" % md5sum(data))
diff --git a/app/index.json b/app/index.json
index 61a86fc..b72dea7 100644
--- a/app/index.json
+++ b/app/index.json
@@ -1,6 +1,9 @@
{
"apps": [
- "CV/EnvGen_ADSR.bin",
+ "CV/V_OCT.bin",
+ "CV/EnvGen.bin",
+ "CV/LFO.bin",
+ "CV/EnvFollower.bin",
"NOISE/WhitePink.bin",
"NOISE/NES.bin",
"NOISE/808_squares.bin",
@@ -14,6 +17,7 @@
"DRUMS/TR909-HiHat.bin",
"DRUMS/TR909-Ride.bin",
"DRUMS/TR707.bin",
+ "DRUMS/Claps.bin",
"M-OSC/Waveforms.bin",
@@ -42,6 +46,8 @@
"FX/JU60_chorus.bin",
"GND/Scope.bin",
- "GND/FFT.bin"
+ "GND/FFT.bin",
+
+ "SYNTH/plaits.bin"
]
}
\ No newline at end of file
diff --git a/app/squares-and-circles-api.h b/app/squares-and-circles-api.h
index 1d6a30b..de5dc07 100644
--- a/app/squares-and-circles-api.h
+++ b/app/squares-and-circles-api.h
@@ -51,6 +51,10 @@ constexpr uint32_t ENGINE_MODE_STEREOLIZED = 1 << 9;
#define EXTERN_C extern "C"
#endif
+#ifndef FLASHMEM
+#define FLASHMEM
+#endif
+
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
diff --git a/app/upload.py b/app/upload.py
index a5b58d4..0f996b8 100755
--- a/app/upload.py
+++ b/app/upload.py
@@ -49,7 +49,7 @@ def sendFLASHDATA(name, data0):
flush(midiin)
data = bytes(name, "utf-8")[:8] + data0
crc32 = zlib.crc32(data)
- print(" Flashing", name, crc32)
+ print(" Flashing", name, crc32, end="")
midiout.send_message(
[0xF3, 0x7E]
) # midi_out.send(mido.Message('song_select', song=0x7e))
@@ -64,10 +64,10 @@ def sendFLASHDATA(name, data0):
msg = midiin.get_message()
if msg:
ack, t = msg
- print(" ACK:", ack)
+ print(" ACK:", ack, end="")
break
- print(" sending blob...", len(data))
+ print(" sending blob...", len(data), end="")
i = 0
time.sleep(1 / 10000)
while i < len(data) - 1:
@@ -115,24 +115,30 @@ def sendFLASHDATA(name, data0):
print(json.dumps(engines, indent=4))
# exit(0)
+# del engines[len(engines)-1:]
+midiout.send_message([0xF3, ord("U")]) # reset
+
def get_appid(binfile):
with open(binfile, "rb") as f:
data = f.read()
- l = int.from_bytes(data[4:6], byteorder="little") # num_lot
- r = int.from_bytes(data[6:8], byteorder="little") # num_rels
+ l = int.from_bytes(data[4:6], byteorder="little") # num_lot
+ r = int.from_bytes(data[6:8], byteorder="little") # num_rels
a = int.from_bytes(data[8:12], byteorder="little") # symt_size
- b = int.from_bytes(data[12:16], byteorder="little") # code_size
- c = int.from_bytes(data[16:20], byteorder="little") # data_size
- d = int.from_bytes(data[20:24], byteorder="little") # bss_size
+ b = int.from_bytes(data[12:16], byteorder="little") # code_size
+ c = int.from_bytes(data[16:20], byteorder="little") # data_size
+ d = int.from_bytes(data[20:24], byteorder="little") # bss_size
sym_off = int(int(24) + (r * 2 * 4))
name_off = (
int.from_bytes(data[sym_off + 4 : sym_off + 8], "little", signed=False)
& 0x0FFFFFFF
) + sym_off
- name = data[name_off : name_off + 24].decode("utf-8").split("\0")[0]
+ name = (
+ data[name_off : data.index(0, name_off)].decode("utf-8").split("\0")[0]
+ )
return name
+
apps_json = os.path.dirname(__file__) + "/index.json"
with open(apps_json) as f:
@@ -143,41 +149,45 @@ def get_appid(binfile):
if not os.path.exists(bin_file):
continue
app_id = get_appid(bin_file) # os.path.splitext(file)[0]
- print("name:", app_id)
bin_size = os.path.getsize(bin_file)
with open(bin_file, "rb") as f:
crc32sum = zlib.crc32(f.read())
- engine = next(
- (e for e in engines if e["id"] == app_id),
- None,
- )
-
- if engine != None and engine["crc32"] == "%x" % crc32sum:
- print(
- engine["addr"],
- os.path.splitext(file)[0],
- "%x" % crc32sum,
- "OK!",
- bin_size - int(engine["size"]),
- )
- continue
- print("->", file, engine)
+ engine = next(
+ (e for e in engines if e["id"] == app_id),
+ None,
+ )
if engine == None:
offset = int(1024 * 1024 / 2)
- if len(engines) > 0:
- offset = max((int(e["addr"], 16) + int(e["size"])) for e in engines)
- offset += 4096 - (offset % 4096)
+ for e in engines:
+ offset = int(e["addr"], 16) + int(e["size"])
+ offset += 4096 - (offset % 4096)
+ print("OFFSET %x" % offset)
engine = {}
engine["id"] = app_id
engine["addr"] = "%x" % offset
engine["size"] = "%s" % bin_size
- print("TODO - add new engine...", "0x%x" % offset, bin_file)
+ engine["crc32"] = "%x" % crc32sum
engines.append(engine)
- # continue
- # exit(0)
+ print("NEW ->", file, engine)
+ continue
+ #exit(0)
+ elif engine["crc32"] == "%x" % crc32sum:
+ onext = int(engine["addr"], 16) + int(engine["size"])
+ onext += 4096 - (onext % 4096)
+ print(
+ engine["addr"], engine["size"],
+ os.path.splitext(file)[0],
+ "%x" % crc32sum,
+ "OK!",
+ bin_size - int(engine["size"]),
+ "MEM-KB: %d" % ((onext - int(1024 * 1024 / 2)) / 1024)
+ )
+ continue
+
+ print("->", file, engine)
print(
os.path.splitext(file)[0], "%x" % crc32sum, bin_size - int(engine["size"])
diff --git a/doc/cv_ef.png b/doc/cv_ef.png
new file mode 100644
index 0000000..37a9323
Binary files /dev/null and b/doc/cv_ef.png differ
diff --git a/doc/engines.png b/doc/engines.png
index 574f1c9..dd5e0c4 100644
Binary files a/doc/engines.png and b/doc/engines.png differ
diff --git a/doc/seq_tm.png b/doc/seq_tm.png
new file mode 100644
index 0000000..48f732f
Binary files /dev/null and b/doc/seq_tm.png differ
diff --git a/lib/drumsynth/drumsynth.cpp b/lib/drumsynth/drumsynth.cpp
index 4272f0a..b45654a 100644
--- a/lib/drumsynth/drumsynth.cpp
+++ b/lib/drumsynth/drumsynth.cpp
@@ -33,7 +33,9 @@
#include "misc/Biquad.h"
#include "drumsynth.h"
+#ifndef SAMPLE_RATE
constexpr float SAMPLE_RATE = 48000.f;
+#endif
inline float dB2amp(float dB)
{
diff --git a/lib/drumsynth/drumsynth.h b/lib/drumsynth/drumsynth.h
index 80c0a19..7708079 100644
--- a/lib/drumsynth/drumsynth.h
+++ b/lib/drumsynth/drumsynth.h
@@ -23,6 +23,8 @@
// See http://creativecommons.org/licenses/MIT/ for more information.
//
+#pragma once
+
#include
#include
#include
diff --git a/lib/misc/noise.hxx b/lib/misc/noise.hxx
index 072ed25..140c22b 100644
--- a/lib/misc/noise.hxx
+++ b/lib/misc/noise.hxx
@@ -24,6 +24,7 @@
// See http://creativecommons.org/licenses/MIT/ for more information.
//
+#pragma once
#include
// 31-bit Park-Miller-Carta Pseudo-Random Number Generator
diff --git a/lib/plaits/resources.cc b/lib/plaits/resources.cc
index a7a4c51..9566efa 100644
--- a/lib/plaits/resources.cc
+++ b/lib/plaits/resources.cc
@@ -33,7 +33,7 @@
#include "plaits/resources.h"
#ifndef FLASHMEM
-#include "pgmspace.h"
+#define FLASHMEM
#endif
namespace plaits {
@@ -4031,10 +4031,8 @@ const int16_t* const lookup_table_i16_table[] FLASHMEM = {
lut_ws_double_bump,
};
-
-
-const int32_t* const lookup_table_i32_table[] FLASHMEM = {
-};
+// const int32_t* const lookup_table_i32_table[] FLASHMEM = {
+// };
const int8_t lut_lpc_excitation_pulse[] FLASHMEM = {
0, 0, 0, 0,
diff --git a/lib/streams/audio_cv_meter.h b/lib/streams/audio_cv_meter.h
new file mode 100644
index 0000000..e4486bc
--- /dev/null
+++ b/lib/streams/audio_cv_meter.h
@@ -0,0 +1,95 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Discriminate an ADC signal into audio or CV ; and provide RMS stats.
+
+#ifndef STREAMS_AUDIO_CV_METER_H_
+#define STREAMS_AUDIO_CV_METER_H_
+
+#include "stmlib/stmlib.h"
+
+namespace streams {
+
+class AudioCvMeter {
+ public:
+ AudioCvMeter() { }
+ ~AudioCvMeter() { }
+
+ void Init() {
+ peak_ = 0;
+
+ zero_crossing_interval_ = 0;
+ average_zero_crossing_interval_ = 0;
+
+ previous_sample_ = 0;
+ cv_ = false;
+ }
+
+ void Process(int32_t sample) {
+ if ((sample >> 1) * previous_sample_ < 0 ||
+ zero_crossing_interval_ >= 4096) {
+ int32_t error = zero_crossing_interval_ - average_zero_crossing_interval_;
+ average_zero_crossing_interval_ += error >> 3;
+ zero_crossing_interval_ = 0;
+ } else {
+ ++zero_crossing_interval_;
+ }
+
+ if (cv_ && average_zero_crossing_interval_ < 200) {
+ cv_ = false;
+ } else if (!cv_ && average_zero_crossing_interval_ > 400) {
+ cv_ = true;
+ }
+
+ previous_sample_ = sample;
+
+ if (sample < 0) {
+ sample = -sample;
+ }
+ int32_t error = sample - peak_;
+ int32_t coefficient = 33; // 250ms at 1kHz
+ if (error > 0) {
+ coefficient = 809; // 10ms at 1kHz
+ }
+ peak_ += error * coefficient >> 15;
+ }
+
+ inline bool cv() const { return cv_; }
+ inline int32_t peak() const { return peak_; }
+
+ private:
+ bool cv_;
+ int32_t peak_;
+ int32_t zero_crossing_interval_;
+ int32_t average_zero_crossing_interval_;
+ int32_t previous_sample_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioCvMeter);
+};
+
+} // namespace streams
+
+#endif // STREAMS_AUDIO_CV_METER_H_
diff --git a/lib/streams/compressor.cc b/lib/streams/compressor.cc
new file mode 100644
index 0000000..0e3fc17
--- /dev/null
+++ b/lib/streams/compressor.cc
@@ -0,0 +1,158 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Compressor.
+
+#include "streams/compressor.h"
+
+// #include
+
+#include "stmlib/utils/dsp.h"
+
+namespace streams {
+
+using namespace stmlib;
+
+// 256 LSB <=> 1.55dB
+const int32_t kGainConstant = 1 / (1.55 / 6.0 * 65536.0 / 256.0) * 65536;
+
+void Compressor::Init() {
+ detector_ = 0;
+}
+
+/* static */
+int32_t Compressor::Log2(int32_t value) {
+ if (value <= 0) {
+ value = 1;
+ }
+ int32_t log_value = 0;
+ while (value >= 512) {
+ value >>= 1;
+ log_value += 65536;
+ }
+ while (value < 256) {
+ value <<= 1;
+ log_value -= 65536;
+ }
+ // Value is between 256 and 512, we can use the LUT.
+ return log_value + lut_log2[value - 256];
+}
+
+/* static */
+int32_t Compressor::Exp2(int32_t value) {
+ int32_t num_shifts = 0;
+ while (value >= 65536) {
+ ++num_shifts;
+ value -= 65536;
+ }
+ while (value < 0) {
+ --num_shifts;
+ value += 65536;
+ }
+
+ // Value is between 0 and 65535, we can use the LUT.
+ int32_t a = lut_exp2[value >> 8];
+ int32_t b = lut_exp2[(value >> 8) + 1];
+ int32_t mantissa = a + ((b - a) * (value & 0xff) >> 8);
+ return num_shifts >= 0 ? mantissa << num_shifts : mantissa >> -num_shifts;
+}
+
+/* static */
+int32_t Compressor::Compress(
+ int32_t squared_level,
+ int32_t threshold,
+ int32_t ratio,
+ bool soft_knee) {
+ int32_t level = (Log2(squared_level) >> 1) - 15 * 65536; // 15-bit peak
+ int32_t position = level - threshold;
+
+ if (position < 0) {
+ return 0;
+ }
+
+ int32_t attenuation = position - (position * ratio >> 8);
+ if (attenuation < 65535 && soft_knee) {
+ int32_t a = lut_soft_knee[attenuation >> 8];
+ int32_t b = lut_soft_knee[(attenuation >> 8) + 1];
+ int32_t soft_knee = a + ((b - a) * (attenuation & 0xff) >> 8);
+ attenuation += \
+ (soft_knee - attenuation) * ((65535 - attenuation) >> 1) >> 15;
+ }
+ return -attenuation;
+}
+
+void Compressor::Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency) {
+ int32_t energy;
+ int64_t error;
+
+ // Detect the RMS level on the EXCITE input.
+ energy = excite;
+ energy *= energy;
+ error = energy - sidechain_signal_detector_;
+ if (error > 0) {
+ sidechain_signal_detector_ += error;
+ } else {
+ // Decay time: 5s.
+ sidechain_signal_detector_ += error * 14174 >> 31;
+ }
+
+ // If there is no signal on the "excite" input, disable sidechain and
+ // compress by metering input.
+ if (sidechain_signal_detector_ < (1024 * 1024)) {
+ energy = audio;
+ energy *= energy;
+ }
+
+ // Detect the RMS level on the EXCITE or AUDIO input - whichever active.
+ error = energy - detector_;
+ if (error > 0) {
+ if (attack_coefficient_ == -1) {
+ detector_ += error;
+ } else {
+ detector_ += error * attack_coefficient_ >> 31;
+ }
+ } else {
+ detector_ += error * decay_coefficient_ >> 31;
+ }
+
+ int32_t g = Compress(detector_, threshold_, ratio_, soft_knee_);
+ gain_reduction_ = g >> 3;
+ g = kUnityGain + ((g + makeup_gain_) * kGainConstant >> 16);
+ if (g > 65535) {
+ g = 65535;
+ }
+
+ *gain = g;
+ // float ogain = powf(10.0f, 1.55f / 20.0f * (g - kUnityGain) / 256.0f);
+ // printf("%f %f\n", gain_reduction_ / 32768.0 * 24, 20 * logf(ogain) / logf(10.0f));
+ *frequency = 65535;
+}
+
+} // namespace streams
diff --git a/lib/streams/compressor.h b/lib/streams/compressor.h
new file mode 100644
index 0000000..5fd1702
--- /dev/null
+++ b/lib/streams/compressor.h
@@ -0,0 +1,133 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Compressor.
+
+#ifndef STREAMS_COMPRESSOR_H_
+#define STREAMS_COMPRESSOR_H_
+
+#include "stmlib/stmlib.h"
+
+#include
+
+#include "streams/gain.h"
+#include "streams/resources.h"
+
+namespace streams {
+
+class Compressor {
+ public:
+ Compressor() { }
+ ~Compressor() { }
+
+ void Init();
+
+ void Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency);
+
+ void Configure(bool alternate, int32_t* parameters, int32_t* globals) {
+ uint16_t attack_time;
+ uint16_t decay_time;
+ uint16_t amount;
+ uint16_t threshold;
+
+ if (globals) {
+ attack_time = globals[0] * (128 + 128 + 99) >> 16; // 1ms to 500ms
+ decay_time = 128 + 99 + (globals[2] >> 8); // 50ms to 5000ms
+ threshold = globals[1];
+ amount = globals[3];
+ } else {
+ attack_time = !alternate ? 1 : 40; // 0.2ms or 2ms;
+ decay_time = !alternate ? 279 : 236; // 150ms or 70ms;
+ threshold = parameters[0];
+ amount = parameters[1];
+ }
+
+ attack_coefficient_ = lut_lp_coefficients[attack_time];
+ decay_coefficient_ = lut_lp_coefficients[decay_time];
+ soft_knee_ = alternate;
+ threshold_ = (-1280 + 5 * (threshold >> 8)) << 8;
+
+ if (amount < 32768) {
+ // Compression with no makeup gain.
+ ratio_ = lut_compressor_ratio[(32767 - amount) >> 7];
+ makeup_gain_ = 0;
+ } else {
+ // Adaptive compression with makeup gain.
+ amount -= 32768;
+
+ int32_t max_gain, knee_gain;
+ max_gain = kMaxExponentialGain;
+ makeup_gain_ = amount * (max_gain >> 8) >> 7;
+ knee_gain = threshold_+ makeup_gain_;
+ if (knee_gain >= 0) {
+ makeup_gain_ = -threshold_;
+ knee_gain = 0;
+ }
+
+ if (knee_gain > -4096) {
+ // So intense! Brickwall limiter mode. In this case, we use an
+ // instant attack to tame transients as soon as they appear.
+ ratio_ = 0;
+ attack_coefficient_ = -1;
+ } else {
+ ratio_ = knee_gain / (threshold_ >> 8);
+ }
+ }
+ }
+
+ inline int32_t gain_reduction() const { return gain_reduction_; }
+
+ private:
+ static int32_t Log2(int32_t value);
+ static int32_t Exp2(int32_t value);
+ static int32_t Compress(
+ int32_t squared_level,
+ int32_t threshold,
+ int32_t ratio,
+ bool soft_knee);
+
+ int32_t ratio_; // Reciprocal of the ratio, 8:8
+ int32_t threshold_;
+ int32_t makeup_gain_;
+
+ bool soft_knee_;
+
+ int64_t attack_coefficient_;
+ int64_t decay_coefficient_;
+ int64_t detector_;
+ int64_t sidechain_signal_detector_;
+ int32_t gain_reduction_;
+
+ DISALLOW_COPY_AND_ASSIGN(Compressor);
+};
+
+} // namespace streams
+
+#endif // STREAMS_COMPRESSOR_H_
diff --git a/lib/streams/envelope.cc b/lib/streams/envelope.cc
new file mode 100644
index 0000000..0572cca
--- /dev/null
+++ b/lib/streams/envelope.cc
@@ -0,0 +1,128 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Simple AD envelope - adapted from Peaks' multistage envelope.
+
+#include "streams/envelope.h"
+
+#include "stmlib/utils/dsp.h"
+
+#include "streams/resources.h"
+
+#include "streams/gain.h"
+
+#include
+
+namespace streams {
+
+using namespace std;
+using namespace stmlib;
+
+void Envelope::Init() {
+ fill(&shape_[0], &shape_[kMaxNumSegments], ENV_SHAPE_LINEAR);
+ set_ad(0, 8192);
+ segment_ = num_segments_;
+ phase_ = 0;
+ phase_increment_ = 0;
+ start_value_ = 0;
+ value_ = 0;
+ rate_modulation_ = 0;
+ gate_level_ = 0;
+ gate_ = false;
+ hard_reset_ = false;
+ attack_ = 0;
+ decay_ = 0;
+}
+
+void Envelope::Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency) {
+ // Smooth frequency amount parameters.
+ frequency_amount_ += (target_frequency_amount_ - frequency_amount_) >> 8;
+ frequency_offset_ += (target_frequency_offset_ - frequency_offset_) >> 8;
+
+ bool trigger = false;
+ bool release = false;
+ if (gate_ == false) {
+ if (excite > kSchmittTriggerThreshold) {
+ trigger = true;
+ gate_ = true;
+ set_hard_reset(false);
+ }
+ } else {
+ if (excite < (kSchmittTriggerThreshold >> 1)) {
+ gate_ = false;
+ release = false;
+ } else {
+ // Track the level of the signal while the GATE is held.
+ gate_level_ += (excite - gate_level_) >> 8;
+ }
+ }
+ if (trigger) {
+ start_value_ = (segment_ == num_segments_ || hard_reset_)
+ ? level_[0]
+ : value_;
+ segment_ = 0;
+ phase_ = 0;
+ } else if (release && sustain_point_) {
+ start_value_ = value_;
+ segment_ = sustain_point_;
+ phase_ = 0;
+ } else if (phase_ < phase_increment_) {
+ start_value_ = level_[segment_ + 1];
+ ++segment_;
+ phase_ = 0;
+ }
+
+ bool done = segment_ == num_segments_;
+ bool sustained = sustain_point_ && segment_ == sustain_point_ && gate_;
+ uint32_t increment = sustained || done ? 0 : lut_env_increments[time_[segment_] >> 8];
+
+ // Modulates the envelope rate by the actual excitation pulse.
+ rate_modulation_ += (static_cast(excite > kSchmittTriggerThreshold ? excite : 0) - rate_modulation_) >> 12;
+ increment += static_cast(increment >> 7) * (rate_modulation_ >> 7);
+
+ phase_increment_ = increment;
+
+ int32_t a = start_value_;
+ int32_t b = level_[segment_ + 1];
+ uint16_t t = Interpolate824(
+ lookup_table_table[LUT_ENV_LINEAR + shape_[segment_]], phase_);
+ value_ = a + ((b - a) * (t >> 1) >> 15);
+ phase_ += phase_increment_;
+
+ // Applies a variable amount of distortion, depending on the level.
+ int32_t compressed = 32767 - ((32767 - value_) * (32767 - value_) >> 15);
+ compressed = 32767 - ((32767 - compressed) * (32767 - compressed) >> 15);
+ int32_t scaled = value_ + ((compressed - value_) * gate_level_ >> 15);
+ scaled = scaled * (28672 + (gate_level_ >> 3)) >> 15;
+ *gain = scaled * kAboveUnityGain >> 15;
+ *frequency = frequency_offset_ + (scaled * frequency_amount_ >> 15);
+}
+
+} // namespace streams
diff --git a/lib/streams/envelope.h b/lib/streams/envelope.h
new file mode 100644
index 0000000..5794dd3
--- /dev/null
+++ b/lib/streams/envelope.h
@@ -0,0 +1,246 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Simple AD envelope - adapted from Peaks' multistage envelope.
+
+#ifndef STREAMS_ENVELOPE_H_
+#define STREAMS_ENVELOPE_H_
+
+#include "stmlib/stmlib.h"
+
+#include "streams/meta_parameters.h"
+
+namespace streams {
+
+enum EnvelopeShape {
+ ENV_SHAPE_LINEAR,
+ ENV_SHAPE_EXPONENTIAL,
+ ENV_SHAPE_QUARTIC
+};
+
+const uint16_t kMaxNumSegments = 8;
+
+class Envelope {
+ public:
+ Envelope() { }
+ ~Envelope() { }
+
+ void Init();
+ void Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency);
+
+ void Configure(bool alternate, int32_t* parameters, int32_t* globals) {
+ uint16_t a, d;
+ if (globals) {
+ a = globals[0];
+ d = globals[2];
+ ComputeAmountOffset(
+ parameters[1],
+ &target_frequency_amount_,
+ &target_frequency_offset_);
+ } else {
+ ComputeAttackDecay(parameters[0], &a, &d);
+ ComputeAmountOffset(
+ parameters[1],
+ &target_frequency_amount_,
+ &target_frequency_offset_);
+ }
+
+ if (a != attack_ || d != decay_ || alternate != alternate_) {
+ attack_ = a;
+ decay_ = d;
+ alternate_ = alternate;
+ if (alternate_) {
+ set_ar(a, d);
+ } else {
+ set_ad(a, d);
+ }
+ set_hard_reset(true);
+ }
+ }
+
+ inline void set_time(uint16_t segment, uint16_t time) {
+ time_[segment] = time;
+ }
+
+ inline void set_level(uint16_t segment, int16_t level) {
+ level_[segment] = level;
+ }
+
+ inline void set_num_segments(uint16_t num_segments) {
+ num_segments_ = num_segments;
+ }
+
+ inline void set_sustain_point(uint16_t sustain_point) {
+ sustain_point_ = sustain_point;
+ }
+
+ inline void set_ad(uint16_t attack, uint16_t decay) {
+ num_segments_ = 2;
+ sustain_point_ = 0;
+
+ level_[0] = 0;
+ level_[1] = 32767;
+ level_[2] = 0;
+
+ time_[0] = attack;
+ time_[1] = decay;
+
+ shape_[0] = ENV_SHAPE_LINEAR;
+ shape_[1] = ENV_SHAPE_EXPONENTIAL;
+ }
+
+ inline void set_adr(
+ uint16_t attack,
+ uint16_t decay,
+ uint16_t sustain,
+ uint16_t release) {
+ num_segments_ = 3;
+ sustain_point_ = 0;
+
+ level_[0] = 0;
+ level_[1] = 32767;
+ level_[2] = sustain;
+ level_[3] = 0;
+
+ time_[0] = attack;
+ time_[1] = decay;
+ time_[2] = release;
+
+ shape_[0] = ENV_SHAPE_LINEAR;
+ shape_[1] = ENV_SHAPE_LINEAR;
+ shape_[2] = ENV_SHAPE_LINEAR;
+ }
+
+ inline void set_ar(uint16_t attack, uint16_t decay) {
+ num_segments_ = 2;
+ sustain_point_ = 1;
+
+ level_[0] = 0;
+ level_[1] = 32767;
+ level_[2] = 0;
+
+ time_[0] = attack;
+ time_[1] = decay;
+
+ shape_[0] = ENV_SHAPE_LINEAR;
+ shape_[1] = ENV_SHAPE_LINEAR;
+ }
+
+ inline void set_adsar(
+ uint16_t attack,
+ uint16_t decay,
+ uint16_t sustain,
+ uint16_t release) {
+ num_segments_ = 4;
+ sustain_point_ = 2;
+
+ level_[0] = 0;
+ level_[1] = 32767;
+ level_[2] = sustain;
+ level_[3] = 32767;
+ level_[4] = 0;
+
+ time_[0] = attack;
+ time_[1] = decay;
+ time_[2] = attack;
+ time_[3] = release;
+
+ shape_[0] = ENV_SHAPE_LINEAR;
+ shape_[1] = ENV_SHAPE_LINEAR;
+ shape_[2] = ENV_SHAPE_LINEAR;
+ shape_[3] = ENV_SHAPE_LINEAR;
+ }
+
+ inline void set_adar(
+ uint16_t attack,
+ uint16_t decay,
+ uint16_t sustain,
+ uint16_t release) {
+ num_segments_ = 4;
+ sustain_point_ = 0;
+
+ level_[0] = 0;
+ level_[1] = 32767;
+ level_[2] = sustain;
+ level_[3] = 32767;
+ level_[4] = 0;
+
+ time_[0] = attack;
+ time_[1] = decay;
+ time_[2] = attack;
+ time_[3] = release;
+
+ shape_[0] = ENV_SHAPE_LINEAR;
+ shape_[1] = ENV_SHAPE_LINEAR;
+ shape_[2] = ENV_SHAPE_LINEAR;
+ shape_[3] = ENV_SHAPE_LINEAR;
+ }
+
+ inline void set_hard_reset(bool hard_reset) {
+ hard_reset_ = hard_reset;
+ }
+
+ private:
+ bool gate_;
+
+ int16_t level_[kMaxNumSegments];
+ uint16_t time_[kMaxNumSegments];
+ EnvelopeShape shape_[kMaxNumSegments];
+
+ int16_t segment_;
+ int16_t start_value_;
+ int16_t value_;
+
+ uint32_t phase_;
+ uint32_t phase_increment_;
+
+ uint16_t num_segments_;
+ uint16_t sustain_point_;
+
+ int32_t target_frequency_amount_;
+ int32_t target_frequency_offset_;
+ int32_t frequency_amount_;
+ int32_t frequency_offset_;
+
+ uint16_t attack_;
+ uint16_t decay_;
+
+ bool alternate_;
+ bool hard_reset_;
+
+ int32_t rate_modulation_;
+ int32_t gate_level_;
+
+ DISALLOW_COPY_AND_ASSIGN(Envelope);
+};
+
+} // namespace streams
+
+#endif // STREAMS_ENVELOPE_H_
diff --git a/lib/streams/filter_controller.h b/lib/streams/filter_controller.h
new file mode 100644
index 0000000..1267033
--- /dev/null
+++ b/lib/streams/filter_controller.h
@@ -0,0 +1,84 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Plain filter.
+
+#ifndef STREAMS_FILTER_CONTROLLER_H_
+#define STREAMS_FILTER_CONTROLLER_H_
+
+#include "stmlib/stmlib.h"
+
+namespace streams {
+
+class FilterController {
+ public:
+ FilterController() { }
+ ~FilterController() { }
+
+ void Init() {
+ frequency_offset_ = 0;
+ frequency_amount_ = 0;
+ }
+ void Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency) {
+ // Smooth frequency amount parameters.
+ frequency_amount_ += (target_frequency_amount_ - frequency_amount_) >> 8;
+ frequency_offset_ += (target_frequency_offset_ - frequency_offset_) >> 8;
+
+ int32_t f;
+ f = frequency_offset_ + (excite * frequency_amount_ >> 14);
+ if (f < 0) {
+ f = 0;
+ } else if (f > 65535) {
+ f = 65535;
+ }
+ *gain = 0;
+ *frequency = f;
+ }
+
+ void Configure(bool alternate, int32_t* parameters, int32_t* globals) {
+ int32_t amount = parameters[1];
+ amount -= 32768;
+ amount = amount * amount >> 15;
+ target_frequency_amount_ = parameters[1] < 32768 ? -amount : amount;
+ target_frequency_offset_ = parameters[0];
+ }
+
+ private:
+ int32_t target_frequency_amount_;
+ int32_t target_frequency_offset_;
+ int32_t frequency_amount_;
+ int32_t frequency_offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(FilterController);
+};
+
+} // namespace streams
+
+#endif // STREAMS_ENVELOPE_H_
diff --git a/lib/streams/follower.cc b/lib/streams/follower.cc
new file mode 100644
index 0000000..98d2863
--- /dev/null
+++ b/lib/streams/follower.cc
@@ -0,0 +1,137 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Follower.
+
+#include "streams/follower.h"
+
+#include "stmlib/utils/dsp.h"
+
+#include "streams/gain.h"
+#include "streams/resources.h"
+
+namespace streams {
+
+using namespace stmlib;
+
+void Follower::Init() {
+ analysis_low_.Init();
+ analysis_low_.set_frequency(45 << 7);
+ analysis_low_.set_resonance(0);
+ analysis_medium_.Init();
+ analysis_medium_.set_frequency(86 << 7);
+ analysis_medium_.set_resonance(0);
+
+ for (uint8_t i = 0; i < 3; ++i) {
+ energy_[i][0] = energy_[i][1] = 0;
+ follower_[i] = 0;
+ follower_lp_[i] = 0;
+ spectrum_[i] = 0;
+ }
+ centroid_ = 0;
+}
+
+void Follower::Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency) {
+ // Smooth frequency amount parameters.
+ frequency_amount_ += (target_frequency_amount_ - frequency_amount_) >> 8;
+ frequency_offset_ += (target_frequency_offset_ - frequency_offset_) >> 8;
+
+ analysis_low_.Process(excite);
+ analysis_medium_.Process(analysis_low_.hp());
+
+ int32_t channel[3];
+ channel[0] = analysis_low_.lp();
+ channel[1] = analysis_medium_.lp();
+ channel[2] = analysis_medium_.hp();
+
+ int32_t envelope = 0;
+ int32_t centroid_numerator = 0;
+ int32_t centroid_denominator = 0;
+ for (int32_t i = 0; i < 3; ++i) {
+ int32_t energy = channel[i];
+ energy *= energy;
+
+ // Ride an ascending peak.
+ if (energy_[i][0] < energy_[i][1] && energy_[i][1] < energy &&
+ energy > follower_[i]) {
+ follower_[i] = energy;
+ }
+ // Otherwise, hold and snap on local maxima.
+ if (energy_[i][0] <= energy_[i][1] && energy_[i][1] >= energy) {
+ follower_[i] = energy_[i][1];
+ }
+ energy_[i][0] = energy_[i][1];
+ energy_[i][1] = energy;
+
+ // Then let a low-pass filter smooth things out.
+ int64_t error = follower_[i] - follower_lp_[i];
+ if (error > 0) {
+ follower_lp_[i] += error * attack_coefficient_[i] >> 31;
+ } else {
+ follower_lp_[i] += error * decay_coefficient_[i] >> 31;
+ }
+ envelope += follower_lp_[i] >> 13;
+
+ // Integrate more slowly for spectrum estimation.
+ if (only_filter_) {
+ error = follower_lp_[i] - spectrum_[i];
+ spectrum_[i] += error >> 6;
+ } else {
+ error = follower_[i] - spectrum_[i];
+ spectrum_[i] += error >> 10;
+ }
+ centroid_numerator += i * (spectrum_[i] >> 1) >> 16;
+ centroid_denominator += spectrum_[i] >> 16;
+ }
+
+ if (envelope > 65535) {
+ envelope = 65535;
+ } else if (envelope < 0) {
+ envelope = 0;
+ }
+
+ uint16_t gain_mod = Interpolate824(lut_square_root, envelope << 16) >> 1;
+ int32_t centroid = (centroid_numerator << 15) / (centroid_denominator + 1);
+ if (gain_mod > 4096) {
+ centroid_ = centroid;
+ } else if (gain_mod > 2048) {
+ centroid_ += (centroid - centroid_) >> 8;
+ }
+
+ *gain = gain_mod * kUnityGain >> 15;
+ *frequency = frequency_offset_ + (centroid_ * frequency_amount_ >> 15);
+
+ if (only_filter_) {
+ *gain = *frequency;
+ *frequency = 65535;
+ }
+}
+
+} // namespace streams
diff --git a/lib/streams/follower.h b/lib/streams/follower.h
new file mode 100644
index 0000000..a6af6f8
--- /dev/null
+++ b/lib/streams/follower.h
@@ -0,0 +1,131 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Follower.
+
+#ifndef STREAMS_FOLLOWER_H_
+#define STREAMS_FOLLOWER_H_
+
+#include "stmlib/stmlib.h"
+
+#include "streams/meta_parameters.h"
+#include "streams/resources.h"
+#include "streams/svf.h"
+
+namespace streams {
+
+const uint16_t kNumBands = 3;
+
+class Follower {
+ public:
+ Follower() { }
+ ~Follower() { }
+
+ void Init();
+ void Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency);
+
+ void Configure(bool alternate, int32_t* parameters, int32_t* globals) {
+ uint16_t attack_time;
+ uint16_t decay_time;
+
+ if (globals) {
+ // Attack: 1ms to 100ms
+ attack_time = globals[0] >> 8;
+
+ // Decay: 10ms to 1000ms
+ decay_time = 128 + (globals[2] >> 8);
+
+ ComputeAmountOffset(
+ parameters[1],
+ &target_frequency_amount_,
+ &target_frequency_offset_);
+ } else {
+ uint16_t shape = parameters[0];
+ if (shape < 32768) {
+ // attack: 1ms to 2ms.
+ attack_time = (shape * 39 >> 15);
+ // decay: 10ms to 100ms.
+ decay_time = 128 + (shape * 128 >> 15);
+ } else {
+ shape -= 32768;
+ // attack: 2ms to 20ms.
+ attack_time = 39 + (shape * 128 >> 15);
+ // decay: 100ms to 200ms.
+ decay_time = 128 + 128 + (shape * 39 >> 15);
+ }
+
+ ComputeAmountOffset(
+ parameters[1],
+ &target_frequency_amount_,
+ &target_frequency_offset_);
+ }
+
+ // Slow down the attack detection on low frequencies.
+ attack_coefficient_[0] = lut_lp_coefficients[attack_time + 39];
+ attack_coefficient_[1] = lut_lp_coefficients[attack_time + 19];
+ attack_coefficient_[2] = lut_lp_coefficients[attack_time + 0];
+
+ // Slow down the decay detection on high frequencies as there is more noise.
+ decay_coefficient_[0] = lut_lp_coefficients[decay_time + 39];
+ decay_coefficient_[1] = lut_lp_coefficients[decay_time + 19];
+ decay_coefficient_[2] = lut_lp_coefficients[decay_time + 99];
+
+ only_filter_ = alternate;
+ }
+
+ private:
+ Svf analysis_low_;
+ Svf analysis_medium_;
+ int32_t energy_[kNumBands][2];
+ int64_t follower_[kNumBands];
+
+ int64_t attack_coefficient_[kNumBands];
+ int64_t decay_coefficient_[kNumBands];
+ int64_t follower_lp_[kNumBands];
+
+ int32_t spectrum_[kNumBands];
+
+ int32_t centroid_;
+
+ int32_t frequency_offset_;
+ int32_t frequency_amount_;
+ int32_t target_frequency_offset_;
+ int32_t target_frequency_amount_;
+
+ int32_t naive_;
+
+ bool only_filter_;
+
+ DISALLOW_COPY_AND_ASSIGN(Follower);
+};
+
+} // namespace streams
+
+#endif // STREAMS_FOLLOWER_H_
diff --git a/lib/streams/gain.h b/lib/streams/gain.h
new file mode 100644
index 0000000..a5ac597
--- /dev/null
+++ b/lib/streams/gain.h
@@ -0,0 +1,56 @@
+// Copyright 2013 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Value to output on the DAC to get unitary gain.
+
+#ifndef STREAMS_GAIN_H_
+#define STREAMS_GAIN_H_
+
+namespace streams {
+
+// The DAC sends up to 2.5V through 25k = 0.1mA over the range of the DAC.
+// The offness compensation resistor sends -10V through 10M = 0.001mA.
+// Assuming the op-amp offset is negligible, the two balance for a DAC code of
+// 65536 / 100.0
+
+const int32_t kDefaultOffset = 655;
+
+// DAC code giving a unitary gain.
+const int32_t kUnityGain = 32767;
+
+// Slightly above unitary gain.
+const int32_t kAboveUnityGain = 32896;
+
+// Maximum gain in dB in lin mode with a DAC code of 65535 (6 dB).
+const int32_t kMaxLinearGain = 65536;
+// Maximum gain in dB in lin mode with a DAC code of 65535 (18 dB).
+const int32_t kMaxExponentialGain = 218453;
+
+const uint16_t kSchmittTriggerThreshold = 32768 * 5 * 2 / 3 / 8;
+
+} // namespace streams
+
+#endif // STREAMS_GAIN_H_
\ No newline at end of file
diff --git a/lib/streams/lorenz_generator.cc b/lib/streams/lorenz_generator.cc
new file mode 100644
index 0000000..7076acb
--- /dev/null
+++ b/lib/streams/lorenz_generator.cc
@@ -0,0 +1,82 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Lorenz system.
+
+#include "streams/lorenz_generator.h"
+
+#include "streams/resources.h"
+
+namespace streams {
+
+using namespace stmlib;
+
+const int64_t sigma = 10.0 * (1 << 24);
+const int64_t rho = 28.0 * (1 << 24);
+const int64_t beta = 8.0 / 3.0 * (1 << 24);
+
+void LorenzGenerator::Init() {
+ x_ = 0.1 * (1 << 24);
+ y_ = 0;
+ z_ = 0;
+ vcf_amount_ = 0;
+ vca_amount_ = 0;
+}
+
+void LorenzGenerator::Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency) {
+ vcf_amount_ += (target_vcf_amount_ - vcf_amount_) >> 8;
+ vca_amount_ += (target_vca_amount_ - vca_amount_) >> 8;
+ int32_t rate = rate_ + (excite >> 8);
+ CONSTRAIN(rate, 0, 256);
+ int64_t dt = static_cast(lut_lorenz_rate[rate]);
+
+ int32_t x = x_ + (dt * ((sigma * (y_ - x_)) >> 24) >> 24);
+ int32_t y = y_ + (dt * ((x_ * (rho - z_) >> 24) - y_) >> 24);
+ int32_t z = z_ + (dt * ((x_ * int64_t(y_) >> 24) - (beta * z_ >> 24)) >> 24);
+
+ x_ = x;
+ y_ = y;
+ z_ = z;
+
+ int32_t z_scaled = z >> 14;
+ int32_t x_scaled = (x >> 14) + 32768;
+
+ if (index_) {
+ // On channel 2, z and y are inverted to get more variety!
+ z = z_scaled;
+ z_scaled = x_scaled;
+ x_scaled = z;
+ }
+
+ *gain = z_scaled * vca_amount_ >> 15;
+ *frequency = 65535 + ((x_scaled - 65535) * vcf_amount_ >> 15);
+}
+
+} // namespace streams
diff --git a/lib/streams/lorenz_generator.h b/lib/streams/lorenz_generator.h
new file mode 100644
index 0000000..c3331da
--- /dev/null
+++ b/lib/streams/lorenz_generator.h
@@ -0,0 +1,80 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Lorenz system.
+
+#ifndef STREAMS_LORENZ_GENERATOR_H_
+#define STREAMS_LORENZ_GENERATOR_H_
+
+#include "stmlib/stmlib.h"
+
+#include "streams/meta_parameters.h"
+
+namespace streams {
+
+class LorenzGenerator {
+ public:
+ LorenzGenerator() { }
+ ~LorenzGenerator() { }
+
+ void Init();
+ void Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency);
+
+ void set_index(uint8_t index) {
+ index_ = index;
+ }
+
+ void Configure(bool alternate, int32_t* parameters, int32_t* globals) {
+ rate_ = parameters[0] >> 8;
+ int32_t vcf_amount = 65535 - parameters[1];
+ int32_t vca_amount = parameters[1];
+ if (vcf_amount >= 32767) vcf_amount = 32767;
+ if (vca_amount >= 32767) vca_amount = 32767;
+ target_vcf_amount_ = vcf_amount;
+ target_vca_amount_ = vca_amount;
+ }
+
+
+ private:
+ int32_t x_, y_, z_;
+ int32_t rate_;
+ int32_t vcf_amount_;
+ int32_t vca_amount_;
+ int32_t target_vcf_amount_;
+ int32_t target_vca_amount_;
+
+ uint8_t index_;
+
+ DISALLOW_COPY_AND_ASSIGN(LorenzGenerator);
+};
+
+} // namespace streams
+
+#endif // STREAMS_LORENZ_GENERATOR_H_
diff --git a/lib/streams/meta_parameters.h b/lib/streams/meta_parameters.h
new file mode 100644
index 0000000..1c1e793
--- /dev/null
+++ b/lib/streams/meta_parameters.h
@@ -0,0 +1,66 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Control of several parameters from one single knob.
+
+#ifndef STREAMS_META_PARAMETERS_H_
+#define STREAMS_META_PARAMETERS_H_
+
+#include "stmlib/stmlib.h"
+
+namespace streams {
+
+inline void ComputeAmountOffset(
+ int32_t value,
+ int32_t* amount,
+ int32_t* offset) {
+ if (value < 32768) {
+ value = 32767 - value;
+ value = value * value >> 15;
+ *amount = (32767 - value) << 1;
+ *offset = 0;
+ } else {
+ *amount = 65535 - ((value - 32768) << 1);
+ *offset = (value - 32768) << 1;
+ }
+}
+
+inline void ComputeAttackDecay(int32_t shape, uint16_t* a, uint16_t* d) {
+ if (shape < 32768) {
+ *a = 0;
+ *d = 13 * (shape >> 3) + 12288;
+ } else if (shape < 49152) {
+ *a = (shape - 32768) << 1;
+ *d = 65535 - ((shape - 32768) >> 1) * 3;
+ } else {
+ *a = 32768 - ((shape - 49152) >> 2) * 5;
+ *d = 65535 - ((shape - 32768) >> 1) * 3;
+ }
+}
+
+} // namespace streams
+
+#endif // STREAMS_META_PARAMETERS_H_
diff --git a/lib/streams/resources.cc b/lib/streams/resources.cc
new file mode 100644
index 0000000..14c458e
--- /dev/null
+++ b/lib/streams/resources.cc
@@ -0,0 +1,1435 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Resources definitions.
+//
+// Automatically generated with:
+// make resources
+
+
+#include "streams/resources.h"
+
+namespace streams {
+
+static const char str_dummy[] = "dummy";
+
+
+const char* string_table[] = {
+ str_dummy,
+};
+
+const int16_t wav_gompertz[] = {
+ 0, 12, 24, 36,
+ 48, 60, 72, 84,
+ 96, 108, 120, 132,
+ 144, 156, 168, 179,
+ 191, 203, 215, 227,
+ 238, 250, 262, 274,
+ 286, 298, 310, 323,
+ 335, 348, 360, 373,
+ 386, 399, 412, 426,
+ 439, 453, 467, 481,
+ 496, 511, 526, 542,
+ 558, 574, 591, 608,
+ 625, 643, 662, 681,
+ 700, 720, 741, 762,
+ 784, 807, 830, 854,
+ 878, 903, 930, 956,
+ 984, 1013, 1042, 1072,
+ 1104, 1136, 1169, 1203,
+ 1238, 1275, 1312, 1350,
+ 1390, 1430, 1472, 1515,
+ 1559, 1605, 1651, 1699,
+ 1749, 1799, 1851, 1904,
+ 1959, 2015, 2072, 2131,
+ 2191, 2252, 2315, 2380,
+ 2446, 2513, 2582, 2652,
+ 2724, 2798, 2873, 2949,
+ 3027, 3106, 3187, 3270,
+ 3354, 3439, 3526, 3615,
+ 3705, 3796, 3889, 3984,
+ 4080, 4177, 4276, 4377,
+ 4479, 4582, 4686, 4793,
+ 4900, 5009, 5119, 5231,
+ 5344, 5458, 5574, 5690,
+ 5808, 5928, 6048, 6170,
+ 6293, 6417, 6542, 6668,
+ 6796, 6924, 7053, 7184,
+ 7315, 7448, 7581, 7715,
+ 7850, 7986, 8123, 8261,
+ 8399, 8538, 8678, 8819,
+ 8960, 9102, 9244, 9387,
+ 9531, 9675, 9820, 9965,
+ 10110, 10256, 10403, 10550,
+ 10697, 10844, 10992, 11140,
+ 11288, 11436, 11585, 11734,
+ 11882, 12031, 12181, 12330,
+ 12479, 12628, 12777, 12926,
+ 13075, 13224, 13373, 13522,
+ 13670, 13819, 13967, 14115,
+ 14263, 14410, 14558, 14705,
+ 14851, 14997, 15143, 15289,
+ 15434, 15579, 15723, 15867,
+ 16011, 16154, 16296, 16438,
+ 16580, 16721, 16861, 17001,
+ 17141, 17280, 17418, 17555,
+ 17692, 17829, 17964, 18099,
+ 18234, 18367, 18500, 18633,
+ 18764, 18895, 19026, 19155,
+ 19284, 19412, 19539, 19666,
+ 19792, 19917, 20041, 20165,
+ 20287, 20409, 20530, 20651,
+ 20770, 20889, 21007, 21124,
+ 21241, 21356, 21471, 21585,
+ 21698, 21810, 21922, 22032,
+ 22142, 22251, 22359, 22466,
+ 22573, 22679, 22783, 22887,
+ 22991, 23093, 23195, 23295,
+ 23395, 23494, 23592, 23690,
+ 23786, 23882, 23977, 24071,
+ 24165, 24257, 24349, 24440,
+ 24530, 24619, 24708, 24795,
+ 24882, 24969, 25054, 25139,
+ 25222, 25305, 25388, 25469,
+ 25550, 25630, 25709, 25788,
+ 25865, 25942, 26019, 26094,
+ 26169, 26243, 26316, 26389,
+ 26461, 26532, 26603, 26672,
+ 26741, 26810, 26878, 26945,
+ 27011, 27077, 27142, 27206,
+ 27270, 27333, 27395, 27457,
+ 27518, 27579, 27639, 27698,
+ 27756, 27814, 27872, 27929,
+ 27985, 28041, 28096, 28150,
+ 28204, 28257, 28310, 28362,
+ 28414, 28465, 28515, 28565,
+ 28614, 28663, 28712, 28759,
+ 28807, 28853, 28900, 28945,
+ 28991, 29035, 29080, 29123,
+ 29167, 29209, 29252, 29294,
+ 29335, 29376, 29416, 29456,
+ 29496, 29535, 29574, 29612,
+ 29650, 29687, 29724, 29760,
+ 29796, 29832, 29867, 29902,
+ 29937, 29971, 30005, 30038,
+ 30071, 30103, 30136, 30167,
+ 30199, 30230, 30261, 30291,
+ 30321, 30351, 30380, 30409,
+ 30438, 30466, 30494, 30521,
+ 30549, 30576, 30602, 30629,
+ 30655, 30681, 30706, 30731,
+ 30756, 30781, 30805, 30829,
+ 30853, 30876, 30899, 30922,
+ 30945, 30967, 30989, 31011,
+ 31032, 31054, 31075, 31096,
+ 31116, 31136, 31156, 31176,
+ 31196, 31215, 31234, 31253,
+ 31272, 31290, 31308, 31326,
+ 31344, 31362, 31379, 31396,
+ 31413, 31430, 31446, 31463,
+ 31479, 31495, 31510, 31526,
+ 31541, 31556, 31571, 31586,
+ 31601, 31615, 31630, 31644,
+ 31658, 31671, 31685, 31698,
+ 31712, 31725, 31738, 31750,
+ 31763, 31775, 31788, 31800,
+ 31812, 31824, 31836, 31847,
+ 31859, 31870, 31881, 31892,
+ 31903, 31914, 31924, 31935,
+ 31945, 31955, 31966, 31976,
+ 31985, 31995, 32005, 32014,
+ 32024, 32033, 32042, 32051,
+ 32060, 32069, 32078, 32086,
+ 32095, 32103, 32111, 32120,
+ 32128, 32136, 32144, 32151,
+ 32159, 32167, 32174, 32182,
+ 32189, 32196, 32203, 32210,
+ 32217, 32224, 32231, 32238,
+ 32244, 32251, 32257, 32264,
+ 32270, 32276, 32282, 32288,
+ 32294, 32300, 32306, 32312,
+ 32318, 32323, 32329, 32334,
+ 32340, 32345, 32350, 32356,
+ 32361, 32366, 32371, 32376,
+ 32381, 32386, 32390, 32395,
+ 32400, 32404, 32409, 32413,
+ 32418, 32422, 32427, 32431,
+ 32435, 32439, 32443, 32447,
+ 32451, 32455, 32459, 32463,
+ 32467, 32471, 32475, 32478,
+ 32482, 32485, 32489, 32492,
+ 32496, 32499, 32503, 32506,
+ 32509, 32513, 32516, 32519,
+ 32522, 32525, 32528, 32531,
+ 32534, 32537, 32540, 32543,
+ 32546, 32548, 32551, 32554,
+ 32557, 32559, 32562, 32564,
+ 32567, 32569, 32572, 32574,
+ 32577, 32579, 32582, 32584,
+ 32586, 32588, 32591, 32593,
+ 32595, 32597, 32599, 32602,
+ 32604, 32606, 32608, 32610,
+ 32612, 32614, 32616, 32618,
+ 32619, 32621, 32623, 32625,
+ 32627, 32628, 32630, 32632,
+ 32634, 32635, 32637, 32639,
+ 32640, 32642, 32643, 32645,
+ 32647, 32648, 32650, 32651,
+ 32652, 32654, 32655, 32657,
+ 32658, 32660, 32661, 32662,
+ 32664, 32665, 32666, 32667,
+ 32669, 32670, 32671, 32672,
+ 32674, 32675, 32676, 32677,
+ 32678, 32679, 32680, 32682,
+ 32683, 32684, 32685, 32686,
+ 32687, 32688, 32689, 32690,
+ 32691, 32692, 32693, 32694,
+ 32695, 32695, 32696, 32697,
+ 32698, 32699, 32700, 32701,
+ 32702, 32702, 32703, 32704,
+ 32705, 32706, 32706, 32707,
+ 32708, 32709, 32709, 32710,
+ 32711, 32712, 32712, 32713,
+ 32714, 32714, 32715, 32716,
+ 32716, 32717, 32718, 32718,
+ 32719, 32719, 32720, 32721,
+ 32721, 32722, 32722, 32723,
+ 32723, 32724, 32725, 32725,
+ 32726, 32726, 32727, 32727,
+ 32728, 32728, 32729, 32729,
+ 32730, 32730, 32731, 32731,
+ 32731, 32732, 32732, 32733,
+ 32733, 32734, 32734, 32735,
+ 32735, 32735, 32736, 32736,
+ 32737, 32737, 32737, 32738,
+ 32738, 32738, 32739, 32739,
+ 32739, 32740, 32740, 32741,
+ 32741, 32741, 32742, 32742,
+ 32742, 32742, 32743, 32743,
+ 32743, 32744, 32744, 32744,
+ 32745, 32745, 32745, 32745,
+ 32746, 32746, 32746, 32747,
+ 32747, 32747, 32747, 32748,
+ 32748, 32748, 32748, 32749,
+ 32749, 32749, 32749, 32749,
+ 32750, 32750, 32750, 32750,
+ 32751, 32751, 32751, 32751,
+ 32751, 32752, 32752, 32752,
+ 32752, 32752, 32753, 32753,
+ 32753, 32753, 32753, 32753,
+ 32754, 32754, 32754, 32754,
+ 32754, 32754, 32755, 32755,
+ 32755, 32755, 32755, 32755,
+ 32756, 32756, 32756, 32756,
+ 32756, 32756, 32756, 32757,
+ 32757, 32757, 32757, 32757,
+ 32757, 32757, 32757, 32758,
+ 32758, 32758, 32758, 32758,
+ 32758, 32758, 32758, 32758,
+ 32759, 32759, 32759, 32759,
+ 32759, 32759, 32759, 32759,
+ 32759, 32760, 32760, 32760,
+ 32760, 32760, 32760, 32760,
+ 32760, 32760, 32760, 32760,
+ 32761, 32761, 32761, 32761,
+ 32761, 32761, 32761, 32761,
+ 32761, 32761, 32761, 32761,
+ 32761, 32762, 32762, 32762,
+ 32762, 32762, 32762, 32762,
+ 32762, 32762, 32762, 32762,
+ 32762, 32762, 32762, 32762,
+ 32763, 32763, 32763, 32763,
+ 32763, 32763, 32763, 32763,
+ 32763, 32763, 32763, 32763,
+ 32763, 32763, 32763, 32763,
+ 32763, 32763, 32763, 32764,
+ 32764, 32764, 32764, 32764,
+ 32764, 32764, 32764, 32764,
+ 32764, 32764, 32764, 32764,
+ 32764, 32764, 32764, 32764,
+ 32764, 32764, 32764, 32764,
+ 32764, 32764, 32764, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32767,
+};
+const int16_t wav_db[] = {
+ -32768, -32768, -24576, -19783,
+ -16384, -13746, -11591, -9770,
+ -8192, -6799, -5554, -4428,
+ -3399, -2453, -1578, -762,
+ 0, 716, 1392, 2031,
+ 2637, 3213, 3763, 4289,
+ 4792, 5274, 5738, 6184,
+ 6613, 7028, 7429, 7816,
+ 8192, 8555, 8908, 9251,
+ 9584, 9907, 10223, 10530,
+ 10829, 11121, 11405, 11683,
+ 11955, 12221, 12481, 12735,
+ 12984, 13227, 13466, 13700,
+ 13930, 14155, 14376, 14592,
+ 14805, 15015, 15220, 15422,
+ 15621, 15816, 16008, 16197,
+ 16384, 16567, 16747, 16925,
+ 17100, 17273, 17443, 17610,
+ 17776, 17939, 18099, 18258,
+ 18415, 18569, 18722, 18872,
+ 19021, 19168, 19313, 19456,
+ 19597, 19737, 19875, 20012,
+ 20147, 20281, 20413, 20543,
+ 20673, 20800, 20927, 21052,
+ 21176, 21298, 21419, 21539,
+ 21658, 21776, 21892, 22007,
+ 22122, 22235, 22347, 22458,
+ 22568, 22676, 22784, 22891,
+ 22997, 23102, 23207, 23310,
+ 23412, 23514, 23614, 23714,
+ 23813, 23911, 24008, 24105,
+ 24200, 24295, 24389, 24483,
+ 24576, 24667, 24759, 24849,
+ 24939, 25028, 25117, 25205,
+ 25292, 25379, 25465, 25550,
+ 25635, 25719, 25802, 25885,
+ 25968, 26049, 26131, 26211,
+ 26291, 26371, 26450, 26529,
+ 26607, 26684, 26761, 26838,
+ 26914, 26989, 27064, 27139,
+ 27213, 27286, 27360, 27432,
+ 27505, 27576, 27648, 27719,
+ 27789, 27860, 27929, 27999,
+ 28067, 28136, 28204, 28272,
+ 28339, 28406, 28473, 28539,
+ 28605, 28670, 28735, 28800,
+ 28865, 28929, 28992, 29056,
+ 29119, 29181, 29244, 29306,
+ 29368, 29429, 29490, 29551,
+ 29611, 29671, 29731, 29791,
+ 29850, 29909, 29968, 30026,
+ 30084, 30142, 30199, 30257,
+ 30314, 30370, 30427, 30483,
+ 30539, 30594, 30650, 30705,
+ 30760, 30814, 30868, 30923,
+ 30976, 31030, 31083, 31136,
+ 31189, 31242, 31294, 31347,
+ 31399, 31450, 31502, 31553,
+ 31604, 31655, 31706, 31756,
+ 31806, 31856, 31906, 31955,
+ 32005, 32054, 32103, 32152,
+ 32200, 32248, 32297, 32345,
+ 32392, 32440, 32487, 32534,
+ 32581, 32628, 32675, 32721,
+ 32721,
+};
+
+
+const int16_t* waveforms_table[] = {
+ wav_gompertz,
+ wav_db,
+};
+
+const uint16_t lut_env_linear[] = {
+ 0, 257, 514, 771,
+ 1028, 1285, 1542, 1799,
+ 2056, 2313, 2570, 2827,
+ 3084, 3341, 3598, 3855,
+ 4112, 4369, 4626, 4883,
+ 5140, 5397, 5654, 5911,
+ 6168, 6425, 6682, 6939,
+ 7196, 7453, 7710, 7967,
+ 8224, 8481, 8738, 8995,
+ 9252, 9509, 9766, 10023,
+ 10280, 10537, 10794, 11051,
+ 11308, 11565, 11822, 12079,
+ 12336, 12593, 12850, 13107,
+ 13364, 13621, 13878, 14135,
+ 14392, 14649, 14906, 15163,
+ 15420, 15677, 15934, 16191,
+ 16448, 16705, 16962, 17219,
+ 17476, 17733, 17990, 18247,
+ 18504, 18761, 19018, 19275,
+ 19532, 19789, 20046, 20303,
+ 20560, 20817, 21074, 21331,
+ 21588, 21845, 22102, 22359,
+ 22616, 22873, 23130, 23387,
+ 23644, 23901, 24158, 24415,
+ 24672, 24929, 25186, 25443,
+ 25700, 25957, 26214, 26471,
+ 26728, 26985, 27242, 27499,
+ 27756, 28013, 28270, 28527,
+ 28784, 29041, 29298, 29555,
+ 29812, 30069, 30326, 30583,
+ 30840, 31097, 31354, 31611,
+ 31868, 32125, 32382, 32639,
+ 32896, 33153, 33410, 33667,
+ 33924, 34181, 34438, 34695,
+ 34952, 35209, 35466, 35723,
+ 35980, 36237, 36494, 36751,
+ 37008, 37265, 37522, 37779,
+ 38036, 38293, 38550, 38807,
+ 39064, 39321, 39578, 39835,
+ 40092, 40349, 40606, 40863,
+ 41120, 41377, 41634, 41891,
+ 42148, 42405, 42662, 42919,
+ 43176, 43433, 43690, 43947,
+ 44204, 44461, 44718, 44975,
+ 45232, 45489, 45746, 46003,
+ 46260, 46517, 46774, 47031,
+ 47288, 47545, 47802, 48059,
+ 48316, 48573, 48830, 49087,
+ 49344, 49601, 49858, 50115,
+ 50372, 50629, 50886, 51143,
+ 51400, 51657, 51914, 52171,
+ 52428, 52685, 52942, 53199,
+ 53456, 53713, 53970, 54227,
+ 54484, 54741, 54998, 55255,
+ 55512, 55769, 56026, 56283,
+ 56540, 56797, 57054, 57311,
+ 57568, 57825, 58082, 58339,
+ 58596, 58853, 59110, 59367,
+ 59624, 59881, 60138, 60395,
+ 60652, 60909, 61166, 61423,
+ 61680, 61937, 62194, 62451,
+ 62708, 62965, 63222, 63479,
+ 63736, 63993, 64250, 64507,
+ 64764, 65021, 65278, 65535,
+ 65535,
+};
+const uint16_t lut_env_expo[] = {
+ 0, 1035, 2054, 3057,
+ 4045, 5018, 5975, 6918,
+ 7846, 8760, 9659, 10545,
+ 11416, 12275, 13120, 13952,
+ 14771, 15577, 16371, 17152,
+ 17921, 18679, 19425, 20159,
+ 20881, 21593, 22294, 22983,
+ 23662, 24331, 24989, 25637,
+ 26274, 26902, 27520, 28129,
+ 28728, 29318, 29899, 30471,
+ 31034, 31588, 32133, 32670,
+ 33199, 33720, 34232, 34737,
+ 35233, 35722, 36204, 36678,
+ 37145, 37604, 38056, 38502,
+ 38940, 39371, 39796, 40215,
+ 40626, 41032, 41431, 41824,
+ 42211, 42592, 42967, 43336,
+ 43699, 44057, 44409, 44756,
+ 45097, 45434, 45764, 46090,
+ 46411, 46727, 47037, 47344,
+ 47645, 47941, 48233, 48521,
+ 48804, 49083, 49357, 49627,
+ 49893, 50155, 50412, 50666,
+ 50916, 51162, 51404, 51642,
+ 51877, 52108, 52335, 52559,
+ 52780, 52997, 53210, 53421,
+ 53628, 53831, 54032, 54230,
+ 54424, 54616, 54804, 54990,
+ 55173, 55353, 55530, 55704,
+ 55876, 56045, 56211, 56375,
+ 56536, 56695, 56851, 57005,
+ 57157, 57306, 57453, 57597,
+ 57740, 57880, 58018, 58153,
+ 58287, 58419, 58548, 58676,
+ 58801, 58925, 59047, 59167,
+ 59285, 59401, 59515, 59628,
+ 59739, 59848, 59955, 60061,
+ 60165, 60267, 60368, 60468,
+ 60566, 60662, 60757, 60850,
+ 60942, 61032, 61121, 61209,
+ 61295, 61380, 61464, 61546,
+ 61628, 61707, 61786, 61863,
+ 61939, 62014, 62088, 62161,
+ 62233, 62303, 62372, 62441,
+ 62508, 62574, 62639, 62703,
+ 62767, 62829, 62890, 62950,
+ 63010, 63068, 63125, 63182,
+ 63238, 63293, 63347, 63400,
+ 63452, 63504, 63554, 63604,
+ 63654, 63702, 63750, 63797,
+ 63843, 63888, 63933, 63977,
+ 64021, 64063, 64105, 64147,
+ 64188, 64228, 64267, 64306,
+ 64344, 64382, 64419, 64456,
+ 64492, 64527, 64562, 64596,
+ 64630, 64664, 64696, 64729,
+ 64760, 64792, 64822, 64853,
+ 64883, 64912, 64941, 64969,
+ 64997, 65025, 65052, 65079,
+ 65105, 65131, 65157, 65182,
+ 65206, 65231, 65255, 65278,
+ 65302, 65324, 65347, 65369,
+ 65391, 65412, 65434, 65454,
+ 65475, 65495, 65515, 65535,
+ 65535,
+};
+const uint16_t lut_env_quartic[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 1, 1,
+ 2, 3, 4, 5,
+ 6, 8, 9, 11,
+ 14, 16, 19, 22,
+ 25, 29, 33, 37,
+ 42, 48, 53, 59,
+ 66, 73, 81, 89,
+ 98, 107, 117, 128,
+ 139, 151, 164, 177,
+ 191, 206, 222, 238,
+ 256, 274, 293, 313,
+ 334, 355, 378, 402,
+ 427, 453, 480, 508,
+ 537, 567, 599, 631,
+ 665, 700, 737, 775,
+ 814, 854, 896, 939,
+ 984, 1030, 1077, 1127,
+ 1177, 1230, 1283, 1339,
+ 1396, 1455, 1515, 1577,
+ 1641, 1707, 1775, 1844,
+ 1916, 1989, 2064, 2141,
+ 2220, 2302, 2385, 2470,
+ 2557, 2647, 2739, 2833,
+ 2929, 3027, 3128, 3231,
+ 3336, 3444, 3554, 3667,
+ 3782, 3899, 4019, 4142,
+ 4267, 4395, 4525, 4658,
+ 4794, 4933, 5074, 5218,
+ 5365, 5515, 5668, 5824,
+ 5983, 6144, 6309, 6477,
+ 6648, 6822, 6999, 7179,
+ 7363, 7550, 7740, 7933,
+ 8130, 8330, 8534, 8741,
+ 8951, 9165, 9383, 9604,
+ 9829, 10057, 10289, 10525,
+ 10765, 11008, 11255, 11507,
+ 11761, 12020, 12283, 12550,
+ 12821, 13096, 13375, 13658,
+ 13945, 14237, 14532, 14832,
+ 15137, 15445, 15758, 16076,
+ 16397, 16724, 17054, 17390,
+ 17730, 18074, 18423, 18777,
+ 19136, 19499, 19868, 20241,
+ 20618, 21001, 21389, 21781,
+ 22179, 22582, 22990, 23403,
+ 23821, 24244, 24672, 25106,
+ 25545, 25990, 26440, 26895,
+ 27355, 27821, 28293, 28770,
+ 29253, 29742, 30236, 30735,
+ 31241, 31752, 32270, 32793,
+ 33321, 33856, 34397, 34944,
+ 35497, 36056, 36621, 37192,
+ 37769, 38353, 38943, 39539,
+ 40142, 40751, 41366, 41988,
+ 42617, 43251, 43893, 44541,
+ 45196, 45857, 46526, 47201,
+ 47882, 48571, 49267, 49969,
+ 50678, 51395, 52118, 52849,
+ 53587, 54332, 55084, 55843,
+ 56610, 57384, 58165, 58954,
+ 59750, 60553, 61364, 62183,
+ 63010, 63843, 64685, 65535,
+ 65535,
+};
+const uint16_t lut_square_root[] = {
+ 0, 4095, 5792, 7094,
+ 8191, 9158, 10032, 10836,
+ 11585, 12287, 12952, 13584,
+ 14188, 14768, 15325, 15863,
+ 16383, 16887, 17377, 17853,
+ 18317, 18769, 19211, 19643,
+ 20065, 20479, 20885, 21283,
+ 21673, 22057, 22434, 22805,
+ 23170, 23529, 23883, 24231,
+ 24575, 24914, 25249, 25579,
+ 25904, 26226, 26544, 26858,
+ 27169, 27476, 27779, 28080,
+ 28377, 28671, 28962, 29250,
+ 29536, 29818, 30098, 30376,
+ 30651, 30923, 31193, 31461,
+ 31726, 31990, 32251, 32510,
+ 32767, 33022, 33275, 33526,
+ 33775, 34023, 34269, 34512,
+ 34755, 34995, 35234, 35471,
+ 35707, 35941, 36174, 36405,
+ 36635, 36863, 37090, 37315,
+ 37539, 37762, 37984, 38204,
+ 38423, 38640, 38857, 39072,
+ 39286, 39499, 39711, 39922,
+ 40131, 40340, 40547, 40754,
+ 40959, 41163, 41366, 41569,
+ 41770, 41970, 42170, 42368,
+ 42566, 42762, 42958, 43153,
+ 43347, 43540, 43732, 43924,
+ 44114, 44304, 44493, 44681,
+ 44868, 45055, 45241, 45426,
+ 45610, 45793, 45976, 46158,
+ 46340, 46520, 46700, 46880,
+ 47058, 47236, 47413, 47590,
+ 47766, 47941, 48116, 48290,
+ 48463, 48636, 48808, 48980,
+ 49151, 49321, 49491, 49660,
+ 49829, 49997, 50164, 50331,
+ 50498, 50663, 50829, 50994,
+ 51158, 51321, 51485, 51647,
+ 51809, 51971, 52132, 52293,
+ 52453, 52613, 52772, 52931,
+ 53089, 53247, 53404, 53561,
+ 53717, 53873, 54029, 54184,
+ 54338, 54492, 54646, 54799,
+ 54952, 55105, 55257, 55408,
+ 55559, 55710, 55861, 56011,
+ 56160, 56309, 56458, 56606,
+ 56754, 56902, 57049, 57196,
+ 57343, 57489, 57634, 57780,
+ 57925, 58069, 58214, 58358,
+ 58501, 58644, 58787, 58930,
+ 59072, 59214, 59355, 59496,
+ 59637, 59778, 59918, 60058,
+ 60197, 60336, 60475, 60614,
+ 60752, 60890, 61028, 61165,
+ 61302, 61439, 61575, 61711,
+ 61847, 61982, 62117, 62252,
+ 62387, 62521, 62655, 62789,
+ 62922, 63056, 63189, 63321,
+ 63453, 63586, 63717, 63849,
+ 63980, 64111, 64242, 64372,
+ 64502, 64632, 64762, 64891,
+ 65020, 65149, 65278, 65406,
+ 65406,
+};
+const uint16_t lut_svf_cutoff[] = {
+ 54, 57, 60, 64,
+ 68, 72, 76, 81,
+ 85, 91, 96, 102,
+ 108, 114, 121, 128,
+ 136, 144, 153, 162,
+ 171, 182, 192, 204,
+ 216, 229, 243, 257,
+ 272, 289, 306, 324,
+ 343, 364, 385, 408,
+ 433, 458, 486, 515,
+ 545, 578, 612, 648,
+ 687, 728, 771, 817,
+ 866, 917, 972, 1030,
+ 1091, 1156, 1225, 1297,
+ 1375, 1456, 1543, 1635,
+ 1732, 1835, 1944, 2060,
+ 2182, 2312, 2449, 2595,
+ 2749, 2912, 3085, 3269,
+ 3463, 3669, 3887, 4118,
+ 4362, 4621, 4895, 5186,
+ 5494, 5819, 6165, 6530,
+ 6917, 7327, 7760, 8219,
+ 8705, 9220, 9764, 10340,
+ 10949, 11593, 12275, 12995,
+ 13757, 14562, 15412, 16309,
+ 17257, 18256, 19310, 20421,
+ 21591, 22822, 24116, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078, 25078, 25078, 25078,
+ 25078,
+};
+const uint16_t lut_svf_damp[] = {
+ 65534, 49166, 46069, 43993,
+ 42386, 41058, 39917, 38910,
+ 38007, 37184, 36427, 35726,
+ 35070, 34454, 33873, 33322,
+ 32798, 32299, 31820, 31361,
+ 30920, 30496, 30086, 29690,
+ 29306, 28935, 28574, 28224,
+ 27883, 27551, 27228, 26912,
+ 26605, 26304, 26010, 25723,
+ 25441, 25166, 24896, 24631,
+ 24371, 24116, 23866, 23620,
+ 23379, 23141, 22908, 22678,
+ 22452, 22229, 22010, 21794,
+ 21581, 21371, 21164, 20960,
+ 20759, 20560, 20365, 20171,
+ 19980, 19791, 19605, 19421,
+ 19239, 19059, 18882, 18706,
+ 18532, 18360, 18190, 18022,
+ 17856, 17691, 17528, 17367,
+ 17207, 17049, 16892, 16737,
+ 16583, 16431, 16280, 16131,
+ 15982, 15836, 15690, 15546,
+ 15403, 15261, 15120, 14981,
+ 14843, 14705, 14569, 14434,
+ 14300, 14167, 14036, 13905,
+ 13775, 13646, 13518, 13391,
+ 13265, 13140, 13015, 12892,
+ 12769, 12648, 12527, 12407,
+ 12287, 12169, 12051, 11934,
+ 11818, 11703, 11588, 11474,
+ 11361, 11249, 11137, 11026,
+ 10915, 10805, 10696, 10588,
+ 10480, 10373, 10266, 10160,
+ 10055, 9950, 9846, 9742,
+ 9639, 9537, 9435, 9333,
+ 9233, 9132, 9033, 8933,
+ 8835, 8737, 8639, 8542,
+ 8445, 8349, 8253, 8158,
+ 8063, 7969, 7875, 7782,
+ 7689, 7596, 7504, 7413,
+ 7321, 7231, 7140, 7050,
+ 6961, 6872, 6783, 6695,
+ 6607, 6519, 6432, 6346,
+ 6259, 6173, 6088, 6003,
+ 5918, 5833, 5749, 5665,
+ 5582, 5499, 5416, 5334,
+ 5251, 5170, 5088, 5007,
+ 4926, 4846, 4766, 4686,
+ 4607, 4527, 4449, 4370,
+ 4292, 4214, 4136, 4059,
+ 3982, 3905, 3828, 3752,
+ 3676, 3601, 3525, 3450,
+ 3375, 3301, 3226, 3152,
+ 3078, 3005, 2932, 2859,
+ 2786, 2713, 2641, 2569,
+ 2497, 2426, 2355, 2284,
+ 2213, 2142, 2072, 2002,
+ 1932, 1862, 1793, 1724,
+ 1655, 1586, 1518, 1449,
+ 1381, 1313, 1246, 1178,
+ 1111, 1044, 977, 911,
+ 844, 778, 712, 647,
+ 581, 516, 450, 385,
+ 321, 256, 192, 127,
+ 63,
+};
+const uint16_t lut_2164_gain[] = {
+ 32767, 31340, 29975, 28670,
+ 27421, 26227, 25085, 23993,
+ 22948, 21948, 20993, 20078,
+ 19204, 18368, 17568, 16803,
+ 16071, 15371, 14702, 14062,
+ 13449, 12864, 12303, 11768,
+ 11255, 10765, 10296, 9848,
+ 9419, 9009, 8617, 8241,
+ 7882, 7539, 7211, 6897,
+ 6596, 6309, 6034, 5772,
+ 5520, 5280, 5050, 4830,
+ 4620, 4418, 4226, 4042,
+ 3866, 3698, 3537, 3383,
+ 3235, 3094, 2960, 2831,
+ 2707, 2589, 2477, 2369,
+ 2266, 2167, 2073, 1982,
+ 1896, 1813, 1734, 1659,
+ 1587, 1517, 1451, 1388,
+ 1328, 1270, 1215, 1162,
+ 1111, 1063, 1016, 972,
+ 930, 889, 850, 813,
+ 778, 744, 712, 681,
+ 651, 623, 595, 569,
+ 545, 521, 498, 477,
+ 456, 436, 417, 399,
+ 381, 365, 349, 334,
+ 319, 305, 292, 279,
+ 267, 255, 244, 233,
+ 223, 214, 204, 195,
+ 187, 179, 171, 163,
+ 156, 149, 143, 137,
+ 131, 125, 119, 114,
+ 109, 104, 100, 96,
+ 91, 87, 84, 80,
+ 76, 73, 70, 67,
+ 64, 61, 58, 56,
+ 53, 51, 49, 47,
+ 45, 43, 41, 39,
+ 37, 36, 34, 32,
+ 31, 30, 28, 27,
+ 26, 25, 24, 23,
+ 22, 21, 20, 19,
+ 18, 17, 16, 16,
+ 15, 14, 14, 13,
+ 12, 12, 11, 11,
+ 10, 10, 9, 9,
+ 9, 8, 8, 7,
+ 7, 7, 6, 6,
+ 6, 6, 5, 5,
+ 5, 5, 4, 4,
+ 4, 4, 4, 3,
+ 3, 3, 3, 3,
+ 3, 2, 2, 2,
+ 2, 2, 2, 2,
+ 2, 2, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0,
+};
+const uint16_t lut_compressor_ratio[] = {
+ 256, 255, 255, 255,
+ 254, 253, 252, 251,
+ 250, 248, 246, 245,
+ 243, 241, 238, 236,
+ 234, 231, 228, 226,
+ 223, 220, 217, 214,
+ 211, 208, 205, 202,
+ 198, 195, 192, 189,
+ 186, 183, 179, 176,
+ 173, 170, 167, 164,
+ 161, 158, 155, 152,
+ 149, 146, 144, 141,
+ 138, 136, 133, 131,
+ 128, 126, 123, 121,
+ 119, 116, 114, 112,
+ 110, 108, 106, 104,
+ 102, 100, 98, 96,
+ 95, 93, 91, 89,
+ 88, 86, 85, 83,
+ 82, 80, 79, 77,
+ 76, 75, 73, 72,
+ 71, 70, 69, 67,
+ 66, 65, 64, 63,
+ 62, 61, 60, 59,
+ 58, 57, 56, 55,
+ 54, 54, 53, 52,
+ 51, 50, 50, 49,
+ 48, 47, 47, 46,
+ 45, 45, 44, 43,
+ 43, 42, 41, 41,
+ 40, 40, 39, 39,
+ 38, 38, 37, 37,
+ 36, 36, 35, 35,
+ 34, 34, 33, 33,
+ 32, 32, 32, 31,
+ 31, 30, 30, 30,
+ 29, 29, 29, 28,
+ 28, 28, 27, 27,
+ 27, 26, 26, 26,
+ 25, 25, 25, 24,
+ 24, 24, 24, 23,
+ 23, 23, 23, 22,
+ 22, 22, 22, 21,
+ 21, 21, 21, 20,
+ 20, 20, 20, 20,
+ 19, 19, 19, 19,
+ 19, 18, 18, 18,
+ 18, 18, 18, 17,
+ 17, 17, 17, 17,
+ 16, 16, 16, 16,
+ 16, 16, 16, 15,
+ 15, 15, 15, 15,
+ 15, 15, 14, 14,
+ 14, 14, 14, 14,
+ 14, 14, 13, 13,
+ 13, 13, 13, 13,
+ 13, 13, 12, 12,
+ 12, 12, 12, 12,
+ 12, 12, 12, 12,
+ 11, 11, 11, 11,
+ 11, 11, 11, 11,
+ 11, 11, 11, 10,
+ 10, 10, 10, 10,
+ 10, 10, 10, 10,
+ 10,
+};
+const uint16_t lut_soft_knee[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 1,
+ 1, 2, 3, 5,
+ 6, 8, 10, 13,
+ 15, 19, 22, 26,
+ 31, 36, 41, 47,
+ 53, 61, 68, 76,
+ 85, 95, 105, 116,
+ 127, 140, 153, 167,
+ 182, 197, 214, 231,
+ 249, 269, 289, 310,
+ 332, 355, 380, 405,
+ 431, 459, 488, 518,
+ 549, 581, 615, 649,
+ 685, 723, 762, 802,
+ 843, 886, 930, 976,
+ 1023, 1072, 1123, 1174,
+ 1228, 1283, 1339, 1398,
+ 1457, 1519, 1582, 1647,
+ 1714, 1783, 1853, 1925,
+ 1999, 2075, 2153, 2233,
+ 2315, 2398, 2484, 2572,
+ 2661, 2753, 2847, 2943,
+ 3041, 3141, 3244, 3349,
+ 3455, 3565, 3676, 3790,
+ 3906, 4024, 4145, 4268,
+ 4393, 4521, 4652, 4785,
+ 4920, 5058, 5199, 5342,
+ 5487, 5636, 5787, 5940,
+ 6097, 6256, 6417, 6582,
+ 6749, 6920, 7093, 7268,
+ 7447, 7629, 7813, 8001,
+ 8191, 8385, 8581, 8781,
+ 8984, 9189, 9398, 9610,
+ 9825, 10044, 10265, 10490,
+ 10718, 10949, 11184, 11422,
+ 11663, 11908, 12156, 12408,
+ 12663, 12921, 13183, 13448,
+ 13717, 13990, 14266, 14546,
+ 14829, 15116, 15407, 15701,
+ 15999, 16301, 16607, 16916,
+ 17229, 17547, 17868, 18192,
+ 18521, 18854, 19191, 19531,
+ 19876, 20225, 20577, 20934,
+ 21295, 21660, 22029, 22403,
+ 22780, 23162, 23548, 23939,
+ 24333, 24732, 25135, 25543,
+ 25955, 26371, 26792, 27217,
+ 27647, 28081, 28520, 28963,
+ 29411, 29864, 30321, 30783,
+ 31249, 31720, 32196, 32676,
+ 33162, 33652, 34147, 34646,
+ 35151, 35660, 36175, 36694,
+ 37218, 37747, 38282, 38821,
+ 39365, 39914, 40469, 41028,
+ 41593, 42162, 42737, 43317,
+ 43903, 44493, 45089, 45691,
+ 46297, 46909, 47526, 48149,
+ 48777, 49410, 50049, 50694,
+ 51343, 51999, 52660, 53326,
+ 53999, 54676, 55360, 56049,
+ 56744, 57444, 58151, 58863,
+ 59581, 60304, 61034, 61769,
+ 62510, 63257, 64010, 64770,
+ 65535,
+};
+
+
+const uint16_t* lookup_table_table[] = {
+ lut_env_linear,
+ lut_env_expo,
+ lut_env_quartic,
+ lut_square_root,
+ lut_svf_cutoff,
+ lut_svf_damp,
+ lut_2164_gain,
+ lut_compressor_ratio,
+ lut_soft_knee,
+};
+
+const uint32_t lut_env_increments[] = {
+ 276301411, 231949934, 196150997, 166999666,
+ 143068141, 123273939, 106787653, 92967541,
+ 81312526, 71428035, 63000899, 55780710,
+ 49565850, 44192924, 39528695, 35463892,
+ 31908401, 28787528, 26039050, 23610894,
+ 21459288, 19547282, 17843559, 16321476,
+ 14958281, 13734481, 12633316, 11640330,
+ 10743016, 9930523, 9193410, 8523437,
+ 7913397, 7356972, 6848604, 6383397,
+ 5957029, 5565672, 5205932, 4874792,
+ 4569569, 4287864, 4027536, 3786669,
+ 3563542, 3356609, 3164482, 2985906,
+ 2819752, 2664995, 2520711, 2386061,
+ 2260283, 2142684, 2032635, 1929561,
+ 1832939, 1742290, 1657176, 1577196,
+ 1501984, 1431202, 1364541, 1301717,
+ 1242466, 1186549, 1133742, 1083841,
+ 1036655, 992009, 949741, 909701,
+ 871748, 835755, 801600, 769172,
+ 738367, 709089, 681248, 654760,
+ 629547, 605536, 582659, 560852,
+ 540056, 520215, 501277, 483193,
+ 465917, 449406, 433620, 418521,
+ 404074, 390245, 377002, 364316,
+ 352160, 340506, 329331, 318610,
+ 308322, 298445, 288962, 279851,
+ 271097, 262683, 254593, 246811,
+ 239325, 232121, 225185, 218507,
+ 212074, 205876, 199903, 194146,
+ 188594, 183239, 178072, 173087,
+ 168275, 163628, 159142, 154807,
+ 150620, 146573, 142661, 138879,
+ 135221, 131683, 128260, 124947,
+ 121741, 118636, 115630, 112719,
+ 109899, 107166, 104518, 101951,
+ 99463, 97050, 94709, 92439,
+ 90236, 88099, 86025, 84011,
+ 82056, 80157, 78313, 76521,
+ 74781, 73090, 71446, 69848,
+ 68295, 66785, 65316, 63887,
+ 62497, 61145, 59829, 58549,
+ 57302, 56089, 54907, 53756,
+ 52636, 51544, 50480, 49444,
+ 48434, 47450, 46491, 45556,
+ 44644, 43755, 42888, 42043,
+ 41218, 40413, 39628, 38862,
+ 38114, 37384, 36671, 35976,
+ 35296, 34633, 33985, 33353,
+ 32735, 32131, 31541, 30965,
+ 30401, 29851, 29313, 28786,
+ 28272, 27769, 27277, 26796,
+ 26326, 25866, 25416, 24975,
+ 24545, 24123, 23710, 23307,
+ 22911, 22524, 22146, 21775,
+ 21412, 21056, 20708, 20367,
+ 20033, 19705, 19385, 19071,
+ 18763, 18461, 18166, 17876,
+ 17592, 17314, 17041, 16774,
+ 16512, 16254, 16002, 15755,
+ 15513, 15275, 15041, 14812,
+ 14588, 14368, 14151, 13939,
+ 13731, 13527, 13326, 13130,
+ 12936, 12747, 12561, 12378,
+ 12198, 12022, 11849, 11679,
+ 11512,
+};
+const uint32_t lut_lp_coefficients[] = {
+ 590672516, 319034455, 133800766, 67976239,
+ 63327094, 62214607, 61121376, 60047077,
+ 58991393, 57954009, 56934619, 55932918,
+ 54948609, 53981397, 53030993, 52097114,
+ 51179478, 50277811, 49391841, 48521302,
+ 47665932, 46825472, 45999668, 45188271,
+ 44391035, 43607717, 42838081, 42081892,
+ 41338919, 40608937, 39891723, 39187058,
+ 38494727, 37814517, 37146221, 36489633,
+ 35844551, 35210779, 34588120, 33976383,
+ 33375380, 32784926, 32204838, 31634936,
+ 31075046, 30524993, 29984607, 29453721,
+ 28932170, 28419793, 27916429, 27421923,
+ 26936121, 26458872, 25990026, 25529439,
+ 25076965, 24632464, 24195797, 23766828,
+ 23345422, 22931447, 22524774, 22125276,
+ 21732827, 21347304, 20968586, 20596554,
+ 20231092, 19872084, 19519417, 19172981,
+ 18832666, 18498365, 18169974, 17847387,
+ 17530504, 17219225, 16913451, 16613085,
+ 16318033, 16028202, 15743500, 15463836,
+ 15189122, 14919272, 14654199, 14393820,
+ 14138052, 13886814, 13640026, 13397610,
+ 13159489, 12925588, 12695832, 12470147,
+ 12248464, 12030709, 11816816, 11606715,
+ 11400339, 11197623, 10998503, 10802914,
+ 10610795, 10422085, 10236722, 10054649,
+ 9875806, 9700137, 9527587, 9358098,
+ 9191619, 9028094, 8867473, 8709704,
+ 8554736, 8402520, 8253007, 8106150,
+ 7961901, 7820214, 7681044, 7544346,
+ 7410077, 7278193, 7148653, 7021415,
+ 6896437, 6773681, 6653106, 6534675,
+ 6418348, 6304089, 6191861, 6081629,
+ 5973356, 5867008, 5762550, 5659950,
+ 5559175, 5460191, 5362968, 5267474,
+ 5173678, 5081550, 4991061, 4902182,
+ 4814883, 4729137, 4644917, 4562195,
+ 4480945, 4401140, 4322755, 4245764,
+ 4170144, 4095869, 4022916, 3951261,
+ 3880881, 3811754, 3743857, 3677168,
+ 3611666, 3547330, 3484139, 3422073,
+ 3361112, 3301236, 3242425, 3184662,
+ 3127927, 3072202, 3017468, 2963710,
+ 2910908, 2859047, 2808109, 2758078,
+ 2708937, 2660672, 2613266, 2566704,
+ 2520972, 2476054, 2431935, 2388602,
+ 2346041, 2304238, 2263180, 2222853,
+ 2183243, 2144340, 2106129, 2068599,
+ 2031737, 1995532, 1959971, 1925044,
+ 1890740, 1857046, 1823952, 1791448,
+ 1759523, 1728167, 1697369, 1667120,
+ 1637410, 1608229, 1579568, 1551417,
+ 1523768, 1496612, 1469939, 1443741,
+ 1418011, 1392739, 1367917, 1343537,
+ 1319591, 1296073, 1272973, 1250285,
+ 1228001, 1206114, 1184617, 1163504,
+ 1142766, 1122398, 1102393, 1082744,
+ 1063446, 1044491, 1025874, 1007589,
+ 989630, 971991, 954666, 937650,
+ 920937, 904521, 888399, 872564,
+ 857011, 841735, 826731, 811995,
+ 797521, 783305, 769343, 755630,
+ 742160, 728931, 715938, 703176,
+ 690642, 678331, 666240, 654364,
+ 642699, 631243, 619991, 608939,
+ 598084, 587423, 576952, 566667,
+ 556566, 546644, 536900, 527329,
+ 517929, 508696, 499628, 490722,
+ 481974, 473383, 464944, 456656,
+ 448515, 440520, 432667, 424954,
+ 417379, 409938, 402631, 395453,
+ 388404, 381480, 374679, 368000,
+ 361440, 354997, 348668, 342453,
+ 336348, 330352, 324463, 318678,
+ 312997, 307418, 301937, 296555,
+ 291268, 286076, 280976, 275967,
+ 271047, 266215, 261469, 256808,
+ 252230, 247733, 243317, 238979,
+ 234719, 230535, 226425, 222388,
+ 218424, 214530, 210705, 206949,
+ 203260, 199636, 196077, 192582,
+ 189148, 185776, 182465, 179212,
+ 176017, 172879, 169797, 166770,
+ 163797, 160877, 158009, 155192,
+ 152425, 149708, 147039, 144417,
+ 141843, 139314, 136830, 134391,
+ 131995, 129642, 127331, 125061,
+ 122831, 120641, 118491, 116378,
+ 114304, 112266, 110264, 108299,
+ 106368, 104472, 102609, 100780,
+ 98983, 97218, 95485, 93783,
+ 92111, 90469, 88856, 87272,
+ 85716, 84188, 82687, 81213,
+ 79765, 78343, 76946, 75574,
+ 74227, 72904, 71604, 70328,
+ 69074, 67842, 66633, 65445,
+ 64278, 63132, 62007, 60901,
+ 59815, 58749, 57702, 56673,
+ 55663, 54670, 53696, 52738,
+ 51798, 50875, 49968, 49077,
+ 48202, 47343, 46498, 45669,
+ 44855, 44056, 43270, 42499,
+ 41741, 40997, 40266, 39548,
+ 38843, 38151, 37470, 36802,
+ 36146, 35502, 34869, 34247,
+ 33637, 33037, 32448, 31870,
+ 31301, 30743, 30195, 29657,
+ 29128, 28609, 28099, 27598,
+ 27106, 26623, 26148, 25682,
+ 25224, 24774, 24332, 23899,
+ 23473, 23054, 22643, 22239,
+ 21843, 21454, 21071, 20695,
+ 20326, 19964, 19608, 19258,
+ 18915, 18578, 18247, 17921,
+ 17602, 17288, 16980, 16677,
+ 16380, 16088, 15801, 15519,
+ 15243, 14971, 14704, 14442,
+ 14184, 13931, 13683, 13439,
+ 13199, 12964, 12733, 12506,
+ 12283, 12064, 11849, 11638,
+ 11430, 11226, 11026, 10830,
+ 10637, 10447, 10261, 10078,
+ 9898, 9722, 9548, 9378,
+ 9211, 9047, 8885, 8727,
+ 8571, 8418, 8268, 8121,
+ 7976, 7834, 7694, 7557,
+ 7422, 7290, 7160, 7032,
+ 6907, 6784, 6663, 6544,
+ 6427, 6313, 6200, 6090,
+ 5981, 5875, 5770, 5667,
+ 5566, 5467, 5369, 5273,
+ 5179, 5087, 4996, 4907,
+ 4820, 4734, 4649, 4567,
+ 4485, 4405, 4327, 4249,
+ 4174, 4099, 4026, 3954,
+ 3884, 3815, 3747, 3680,
+ 3614, 3550, 3486, 3424,
+ 3363, 3303, 3244, 3187,
+ 3130, 3074, 3019, 2965,
+ 2912, 2860, 2809, 2759,
+ 2710, 2662, 2614, 2568,
+ 2522, 2477, 2433, 2389,
+ 2347, 2305, 2264, 2224,
+ 2184, 2145, 2107, 2069,
+ 2032, 1996, 1960, 1925,
+ 1891, 1857, 1824, 1792,
+ 1760, 1728, 1698, 1667,
+ 1638, 1608, 1580, 1551,
+ 1524, 1497, 1470, 1444,
+ 1418, 1393, 1368, 1343,
+ 1319, 1296, 1273, 1250,
+ 1228, 1206, 1184, 1163,
+ 1143, 1122, 1102, 1083,
+ 1063, 1044, 1026, 1007,
+ 989, 972, 954, 937,
+ 921, 904, 888, 872,
+ 857, 841, 826, 812,
+ 797, 783, 769, 755,
+ 742, 729, 716, 703,
+};
+const uint32_t lut_exp2[] = {
+ 65536, 65713, 65891, 66070,
+ 66249, 66429, 66609, 66789,
+ 66971, 67152, 67334, 67517,
+ 67700, 67883, 68067, 68252,
+ 68437, 68623, 68809, 68995,
+ 69182, 69370, 69558, 69747,
+ 69936, 70125, 70315, 70506,
+ 70697, 70889, 71081, 71274,
+ 71467, 71661, 71855, 72050,
+ 72245, 72441, 72638, 72834,
+ 73032, 73230, 73429, 73628,
+ 73827, 74027, 74228, 74429,
+ 74631, 74833, 75036, 75240,
+ 75444, 75648, 75853, 76059,
+ 76265, 76472, 76679, 76887,
+ 77096, 77305, 77514, 77725,
+ 77935, 78147, 78359, 78571,
+ 78784, 78998, 79212, 79427,
+ 79642, 79858, 80074, 80292,
+ 80509, 80727, 80946, 81166,
+ 81386, 81607, 81828, 82050,
+ 82272, 82495, 82719, 82943,
+ 83168, 83394, 83620, 83846,
+ 84074, 84302, 84530, 84759,
+ 84989, 85220, 85451, 85682,
+ 85915, 86148, 86381, 86615,
+ 86850, 87086, 87322, 87559,
+ 87796, 88034, 88273, 88512,
+ 88752, 88993, 89234, 89476,
+ 89718, 89962, 90206, 90450,
+ 90695, 90941, 91188, 91435,
+ 91683, 91932, 92181, 92431,
+ 92681, 92933, 93185, 93437,
+ 93691, 93945, 94199, 94455,
+ 94711, 94968, 95225, 95483,
+ 95742, 96002, 96262, 96523,
+ 96785, 97047, 97310, 97574,
+ 97839, 98104, 98370, 98637,
+ 98904, 99172, 99441, 99711,
+ 99981, 100252, 100524, 100797,
+ 101070, 101344, 101619, 101894,
+ 102170, 102447, 102725, 103004,
+ 103283, 103563, 103844, 104125,
+ 104408, 104691, 104975, 105259,
+ 105545, 105831, 106118, 106405,
+ 106694, 106983, 107273, 107564,
+ 107856, 108148, 108441, 108735,
+ 109030, 109326, 109622, 109919,
+ 110217, 110516, 110816, 111116,
+ 111418, 111720, 112023, 112326,
+ 112631, 112936, 113243, 113550,
+ 113857, 114166, 114476, 114786,
+ 115097, 115409, 115722, 116036,
+ 116351, 116666, 116982, 117300,
+ 117618, 117936, 118256, 118577,
+ 118898, 119221, 119544, 119868,
+ 120193, 120519, 120846, 121173,
+ 121502, 121831, 122162, 122493,
+ 122825, 123158, 123492, 123827,
+ 124162, 124499, 124837, 125175,
+ 125514, 125855, 126196, 126538,
+ 126881, 127225, 127570, 127916,
+ 128263, 128611, 128959, 129309,
+ 129660, 130011, 130364, 130717,
+ 131072,
+};
+const uint32_t lut_log2[] = {
+ 524288, 524656, 525023, 525389,
+ 525753, 526116, 526478, 526838,
+ 527197, 527554, 527910, 528265,
+ 528619, 528971, 529322, 529671,
+ 530019, 530366, 530712, 531057,
+ 531400, 531742, 532082, 532422,
+ 532760, 533097, 533433, 533768,
+ 534101, 534434, 534765, 535095,
+ 535424, 535751, 536078, 536403,
+ 536728, 537051, 537373, 537694,
+ 538014, 538333, 538651, 538968,
+ 539283, 539598, 539912, 540224,
+ 540536, 540846, 541156, 541464,
+ 541772, 542078, 542384, 542688,
+ 542992, 543294, 543596, 543896,
+ 544196, 544495, 544793, 545089,
+ 545385, 545680, 545974, 546268,
+ 546560, 546851, 547142, 547431,
+ 547720, 548008, 548295, 548581,
+ 548866, 549150, 549434, 549717,
+ 549998, 550279, 550560, 550839,
+ 551117, 551395, 551672, 551948,
+ 552223, 552498, 552771, 553044,
+ 553316, 553588, 553858, 554128,
+ 554397, 554665, 554932, 555199,
+ 555465, 555730, 555995, 556259,
+ 556522, 556784, 557045, 557306,
+ 557566, 557826, 558084, 558342,
+ 558600, 558856, 559112, 559367,
+ 559622, 559876, 560129, 560381,
+ 560633, 560884, 561135, 561384,
+ 561634, 561882, 562130, 562377,
+ 562624, 562870, 563115, 563359,
+ 563603, 563847, 564089, 564332,
+ 564573, 564814, 565054, 565294,
+ 565533, 565771, 566009, 566247,
+ 566483, 566719, 566955, 567190,
+ 567424, 567658, 567891, 568124,
+ 568356, 568587, 568818, 569048,
+ 569278, 569507, 569736, 569964,
+ 570192, 570419, 570645, 570871,
+ 571096, 571321, 571545, 571769,
+ 571992, 572215, 572437, 572659,
+ 572880, 573101, 573321, 573541,
+ 573760, 573978, 574197, 574414,
+ 574631, 574848, 575064, 575280,
+ 575495, 575709, 575923, 576137,
+ 576350, 576563, 576775, 576987,
+ 577198, 577409, 577619, 577829,
+ 578039, 578248, 578456, 578664,
+ 578872, 579079, 579286, 579492,
+ 579698, 579903, 580108, 580312,
+ 580516, 580720, 580923, 581125,
+ 581328, 581530, 581731, 581932,
+ 582132, 582332, 582532, 582731,
+ 582930, 583129, 583327, 583524,
+ 583721, 583918, 584115, 584311,
+ 584506, 584701, 584896, 585090,
+ 585284, 585478, 585671, 585864,
+ 586056, 586248, 586440, 586631,
+ 586822, 587012, 587202, 587392,
+ 587581, 587770, 587959, 588147,
+ 588335, 588522, 588709, 588896,
+ 589082, 589268, 589453, 589639,
+ 589824,
+};
+const uint32_t lut_lorenz_rate[] = {
+ 3, 3, 3, 4,
+ 4, 4, 4, 4,
+ 5, 5, 5, 5,
+ 6, 6, 6, 7,
+ 7, 7, 8, 8,
+ 8, 9, 9, 10,
+ 10, 11, 11, 12,
+ 12, 13, 13, 14,
+ 15, 15, 16, 17,
+ 18, 18, 19, 20,
+ 21, 22, 23, 24,
+ 25, 27, 28, 29,
+ 30, 32, 33, 35,
+ 36, 38, 40, 42,
+ 44, 46, 48, 50,
+ 52, 55, 57, 60,
+ 63, 66, 69, 72,
+ 75, 78, 82, 86,
+ 90, 94, 98, 103,
+ 107, 112, 118, 123,
+ 129, 135, 141, 147,
+ 154, 161, 168, 176,
+ 184, 193, 201, 211,
+ 220, 230, 241, 252,
+ 263, 275, 288, 301,
+ 315, 329, 344, 360,
+ 377, 394, 412, 431,
+ 451, 471, 493, 515,
+ 539, 563, 589, 616,
+ 644, 674, 705, 737,
+ 770, 806, 843, 881,
+ 921, 963, 1007, 1054,
+ 1102, 1152, 1205, 1260,
+ 1317, 1378, 1441, 1506,
+ 1575, 1647, 1722, 1801,
+ 1883, 1970, 2060, 2154,
+ 2252, 2355, 2463, 2575,
+ 2693, 2816, 2945, 3079,
+ 3220, 3367, 3521, 3682,
+ 3850, 4026, 4210, 4402,
+ 4603, 4814, 5034, 5264,
+ 5504, 5756, 6019, 6294,
+ 6581, 6882, 7196, 7525,
+ 7869, 8229, 8605, 8998,
+ 9409, 9839, 10288, 10758,
+ 11250, 11764, 12302, 12864,
+ 13451, 14066, 14709, 15381,
+ 16083, 16818, 17587, 18390,
+ 19230, 20109, 21028, 21989,
+ 22993, 24044, 25142, 26291,
+ 27492, 28748, 30062, 31435,
+ 32872, 34374, 35944, 37586,
+ 39304, 41099, 42977, 44941,
+ 46994, 49141, 51386, 53734,
+ 56189, 58756, 61441, 64248,
+ 67184, 70253, 73463, 76819,
+ 80329, 83999, 87837, 91850,
+ 96047, 100435, 105024, 109822,
+ 114840, 120087, 125573, 131310,
+ 137310, 143583, 150144, 157003,
+ 164177, 171678, 179521, 187723,
+ 196300, 205269, 214647, 224454,
+ 234709, 245433, 256646, 268372,
+ 280634, 293455, 306863, 320883,
+ 335544,
+};
+
+
+const uint32_t* lookup_table_32_table[] = {
+ lut_env_increments,
+ lut_lp_coefficients,
+ lut_exp2,
+ lut_log2,
+ lut_lorenz_rate,
+};
+
+
+} // namespace streams
diff --git a/lib/streams/resources.h b/lib/streams/resources.h
new file mode 100644
index 0000000..1f464f7
--- /dev/null
+++ b/lib/streams/resources.h
@@ -0,0 +1,105 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Resources definitions.
+//
+// Automatically generated with:
+// make resources
+
+
+#ifndef STREAMS_RESOURCES_H_
+#define STREAMS_RESOURCES_H_
+
+
+#include "stmlib/stmlib.h"
+
+
+
+namespace streams {
+
+typedef uint8_t ResourceId;
+
+extern const char* string_table[];
+
+extern const int16_t* waveforms_table[];
+
+extern const uint16_t* lookup_table_table[];
+
+extern const uint32_t* lookup_table_32_table[];
+
+extern const int16_t wav_gompertz[];
+extern const int16_t wav_db[];
+extern const uint16_t lut_env_linear[];
+extern const uint16_t lut_env_expo[];
+extern const uint16_t lut_env_quartic[];
+extern const uint16_t lut_square_root[];
+extern const uint16_t lut_svf_cutoff[];
+extern const uint16_t lut_svf_damp[];
+extern const uint16_t lut_2164_gain[];
+extern const uint16_t lut_compressor_ratio[];
+extern const uint16_t lut_soft_knee[];
+extern const uint32_t lut_env_increments[];
+extern const uint32_t lut_lp_coefficients[];
+extern const uint32_t lut_exp2[];
+extern const uint32_t lut_log2[];
+extern const uint32_t lut_lorenz_rate[];
+#define STR_DUMMY 0 // dummy
+#define WAV_GOMPERTZ 0
+#define WAV_GOMPERTZ_SIZE 1025
+#define WAV_DB 1
+#define WAV_DB_SIZE 257
+#define LUT_ENV_LINEAR 0
+#define LUT_ENV_LINEAR_SIZE 257
+#define LUT_ENV_EXPO 1
+#define LUT_ENV_EXPO_SIZE 257
+#define LUT_ENV_QUARTIC 2
+#define LUT_ENV_QUARTIC_SIZE 257
+#define LUT_SQUARE_ROOT 3
+#define LUT_SQUARE_ROOT_SIZE 257
+#define LUT_SVF_CUTOFF 4
+#define LUT_SVF_CUTOFF_SIZE 257
+#define LUT_SVF_DAMP 5
+#define LUT_SVF_DAMP_SIZE 257
+#define LUT_2164_GAIN 6
+#define LUT_2164_GAIN_SIZE 257
+#define LUT_COMPRESSOR_RATIO 7
+#define LUT_COMPRESSOR_RATIO_SIZE 257
+#define LUT_SOFT_KNEE 8
+#define LUT_SOFT_KNEE_SIZE 257
+#define LUT_ENV_INCREMENTS 0
+#define LUT_ENV_INCREMENTS_SIZE 257
+#define LUT_LP_COEFFICIENTS 1
+#define LUT_LP_COEFFICIENTS_SIZE 640
+#define LUT_EXP2 2
+#define LUT_EXP2_SIZE 257
+#define LUT_LOG2 3
+#define LUT_LOG2_SIZE 257
+#define LUT_LORENZ_RATE 4
+#define LUT_LORENZ_RATE_SIZE 257
+
+} // namespace streams
+
+#endif // STREAMS_RESOURCES_H_
diff --git a/lib/streams/svf.cc b/lib/streams/svf.cc
new file mode 100644
index 0000000..3206e6c
--- /dev/null
+++ b/lib/streams/svf.cc
@@ -0,0 +1,65 @@
+// Copyright 2013 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// SVF used for modeling the bridged T-networks.
+
+#include "streams/svf.h"
+
+#include "stmlib/utils/dsp.h"
+
+#include "streams/resources.h"
+
+namespace streams {
+
+using namespace stmlib;
+
+void Svf::Init() {
+ lp_ = 0;
+ bp_ = 0;
+ frequency_ = 33 << 7;
+ resonance_ = 16384;
+ dirty_ = true;
+}
+
+void Svf::Process(int32_t in) {
+ if (dirty_) {
+ f_ = Interpolate824(lut_svf_cutoff, frequency_ << 17);
+ damp_ = Interpolate824(lut_svf_damp, resonance_ << 17);
+ dirty_ = false;
+ }
+ int32_t f = f_;
+ int32_t damp = damp_;
+ int32_t notch = in - (bp_ * damp >> 15);
+ lp_ += f * bp_ >> 15;
+ CLIP(lp_)
+ hp_ = notch - lp_;
+ bp_ += f * hp_ >> 15;
+ CLIP(bp_)
+ CLIP(hp_)
+}
+
+
+} // namespace streams
diff --git a/lib/streams/svf.h b/lib/streams/svf.h
new file mode 100644
index 0000000..9806803
--- /dev/null
+++ b/lib/streams/svf.h
@@ -0,0 +1,76 @@
+// Copyright 2013 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// SVF used for the envelope follower filter bank.
+
+#ifndef STREAMS_SVF_H_
+#define STREAMS_SVF_H_
+
+#include "stmlib/stmlib.h"
+
+namespace streams {
+
+class Svf {
+ public:
+ Svf() { }
+ ~Svf() { }
+
+ void Init();
+
+ void set_frequency(int16_t frequency) {
+ dirty_ = dirty_ || (frequency_ != frequency);
+ frequency_ = frequency;
+ }
+
+ void set_resonance(int16_t resonance) {
+ resonance_ = resonance;
+ dirty_ = true;
+ }
+
+ void Process(int32_t sample);
+ inline int32_t lp() const { return lp_; }
+ inline int32_t bp() const { return bp_; }
+ inline int32_t hp() const { return hp_; }
+
+ private:
+ bool dirty_;
+
+ int16_t frequency_;
+ int16_t resonance_;
+
+ int32_t f_;
+ int32_t damp_;
+
+ int32_t lp_;
+ int32_t bp_;
+ int32_t hp_;
+
+ DISALLOW_COPY_AND_ASSIGN(Svf);
+};
+
+} // namespace streams
+
+#endif // STREAMS_SVF_H_
diff --git a/lib/streams/vactrol.cc b/lib/streams/vactrol.cc
new file mode 100644
index 0000000..21ddce7
--- /dev/null
+++ b/lib/streams/vactrol.cc
@@ -0,0 +1,186 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Vactrol.
+
+#include "streams/vactrol.h"
+
+#include "stmlib/utils/dsp.h"
+
+#include "streams/gain.h"
+#include "streams/resources.h"
+
+namespace streams {
+
+using namespace stmlib;
+
+void Vactrol::Init() {
+ state_[0] = 0;
+ state_[1] = 0;
+ state_[2] = 0;
+ state_[3] = 0;
+
+ excite_ = 0;
+}
+
+void Vactrol::Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency) {
+ // Smooth frequency amount parameters.
+ frequency_amount_ += (target_frequency_amount_ - frequency_amount_) >> 8;
+ frequency_offset_ += (target_frequency_offset_ - frequency_offset_) >> 8;
+
+ int32_t input;
+ int32_t error;
+ int64_t coefficient = 0;
+
+ if (excite < 0) {
+ excite = 0;
+ }
+
+ // Simple plucked mode.
+ if (plucked_) {
+ if (gate_ == false) {
+ if (excite > kSchmittTriggerThreshold) {
+ gate_ = true;
+ state_[0] = 32767 << 16;
+ state_[1] = 32767 << 16;
+ }
+ } else {
+ if (excite < (kSchmittTriggerThreshold >> 1)) {
+ gate_ = false;
+ }
+ }
+
+ // Filter the excitation pulses.
+ state_[0] -= static_cast(
+ state_[0]) * fast_decay_coefficient_ >> 31;
+ state_[1] -= static_cast(
+ state_[1]) * decay_coefficient_ >> 31;
+
+ // VCF envelope.
+ error = state_[0] - state_[2];
+ coefficient = error > 0
+ ? fast_attack_coefficient_ : fast_decay_coefficient_;
+ state_[2] += static_cast(error) * coefficient >> 31;
+
+ // VCA envelope.
+ error = state_[1] - state_[3];
+ coefficient = error > 0 ? fast_attack_coefficient_ : decay_coefficient_;
+ // Increase the duration of the tail
+ int64_t strength = error > 0 ? error : -error;
+ coefficient = (coefficient >> 1) + (coefficient * strength >> 31);
+ state_[3] += static_cast(error) * coefficient >> 31;
+
+ uint16_t vcf_amount = state_[2] >> 16;
+ uint16_t vca_mount = Interpolate1022(wav_gompertz, (state_[3] >> 2) * 3);
+
+ *gain = kAboveUnityGain * vca_mount >> 15;
+ *frequency = frequency_offset_ + \
+ (frequency_amount_ * vcf_amount >> 15);
+
+ return;
+ }
+
+ // Low-pass filter the negative edges to prevent fast pulse to immediately
+ // decay before the vactrol has started reacting. This allows the EXCITE
+ // input to be used for both controlling the vactrol or just plucking it
+ // from a trigger.
+ error = excite - excite_;
+ coefficient = error > 0 ? (1 << 30) : (decay_coefficient_ << 1);
+ excite_ += static_cast(error) * coefficient >> 31;
+ excite = excite_;
+
+ input = frequency_offset_;
+ input += frequency_amount_ >> 1;
+ input = (65535 + input) >> 1;
+ input *= excite;
+
+ state_[3] += static_cast(input - state_[3]) * 67976239 >> 31;
+
+ error = input - state_[0];
+ coefficient = 0;
+ if (error > 0) {
+ if (state_[1] > 0) {
+ coefficient = attack_coefficient_;
+ // Increase attack time when the photocell has been desensitized.
+ coefficient += coefficient * (255 - (state_[2] >> 23)) >> 6;
+ } else {
+ coefficient = fast_attack_coefficient_;
+ }
+ } else {
+ if (state_[1] < 0) {
+ coefficient = decay_coefficient_;
+ } else {
+ coefficient = fast_decay_coefficient_;
+ }
+ }
+ // First order.
+ state_[0] += static_cast(error) * coefficient >> 31;
+
+ // Second order.
+ state_[1] += static_cast(error - state_[1]) * coefficient >> 31;
+
+ // Memory effect.
+ int32_t sensitivity = state_[0];
+ if (sensitivity > (1 << 28)) {
+ sensitivity = 1 << 31;
+ } else {
+ sensitivity <<= 3;
+ }
+ error = sensitivity - state_[2];
+ if (error > 0) {
+ // Get into the "sensitized" state in 1s.
+ state_[2] += static_cast(error) * 138132 >> 31;
+ } else {
+ // Get out of the "sensitized" state in 60s.
+ state_[2] += static_cast(error) * 1151 >> 31;
+ }
+
+ // Apply non-linearity.
+ int32_t index = state_[0] >> 1;
+
+ // A little hack to add overshoot...
+ index += (state_[3] >> 15) * (state_[1] >> 15) >> 1;
+ if (index < 0) {
+ index = 0;
+ } else if (index >= (1 << 30)) {
+ index = (1 << 30) - 1;
+ }
+ uint16_t amplitude = index < 536870912
+ ? Interpolate1022(wav_gompertz, static_cast(index) << 3)
+ : 32767;
+ uint16_t cutoff = index >> 14;
+ if (cutoff >= 32767) cutoff = 32767;
+ cutoff = cutoff * cutoff >> 15;
+ *gain = kAboveUnityGain * amplitude >> 15;
+ *frequency = frequency_offset_ + \
+ (frequency_amount_ * cutoff >> 15);
+}
+
+} // namespace streams
diff --git a/lib/streams/vactrol.h b/lib/streams/vactrol.h
new file mode 100644
index 0000000..81d9457
--- /dev/null
+++ b/lib/streams/vactrol.h
@@ -0,0 +1,139 @@
+// Copyright 2014 Emilie Gillet.
+//
+// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// See http://creativecommons.org/licenses/MIT/ for more information.
+//
+// -----------------------------------------------------------------------------
+//
+// Vactrol.
+
+#ifndef STREAMS_VACTROL_H_
+#define STREAMS_VACTROL_H_
+
+#include "stmlib/stmlib.h"
+
+#include "streams/meta_parameters.h"
+#include "streams/resources.h"
+
+namespace streams {
+
+class Vactrol {
+ public:
+ Vactrol() { }
+ ~Vactrol() { }
+
+ void Init();
+ void Process(
+ int16_t audio,
+ int16_t excite,
+ uint16_t* gain,
+ uint16_t* frequency);
+
+ void Configure(bool alternate, int32_t* parameters, int32_t* globals) {
+ uint16_t attack_time;
+ uint16_t decay_time;
+
+ if (globals) {
+ // Attack: 10ms to 1000ms
+ attack_time = 128 + (globals[0] >> 8);
+ // Decay: 10ms to 5000ms
+ decay_time = 128 + (globals[2] * 355 >> 16);
+ ComputeAmountOffset(
+ parameters[1],
+ &target_frequency_amount_,
+ &target_frequency_offset_);
+ } else {
+ uint16_t shape = parameters[0];
+ ComputeAmountOffset(
+ parameters[1],
+ &target_frequency_amount_,
+ &target_frequency_offset_);
+
+ if (shape < 32768) {
+ // attack: 10ms
+ attack_time = 128;
+ // decay: 50ms to 2000ms
+ decay_time = 227 + (shape * 196 >> 15);
+ } else if (shape < 49512) {
+ shape -= 32768;
+ // attack: 10ms to 500ms.
+ attack_time = 128 + (shape * 227 >> 15);
+ // decay: 2000ms to 1000ms.
+ decay_time = 423 - (89 * shape >> 15);
+ } else {
+ shape -= 49512;
+ // attack: 500ms to 50ms.
+ attack_time = 355 - (shape >> 7);
+ // decay: 1000ms to 100ms.
+ decay_time = 384 - (128 * shape >> 15);
+ }
+ }
+
+ attack_coefficient_ = lut_lp_coefficients[attack_time];
+ fast_attack_coefficient_ = lut_lp_coefficients[attack_time - 128];
+ decay_coefficient_ = lut_lp_coefficients[decay_time];
+ fast_decay_coefficient_ = lut_lp_coefficients[decay_time - 128];
+
+ plucked_ = alternate;
+ if (alternate) {
+ fast_attack_coefficient_ <<= 4;
+ } else {
+ decay_coefficient_ >>= 1;
+ }
+
+ int32_t ringing_tail = 8192;
+ int32_t headroom = 65535 - target_frequency_offset_;
+ if (ringing_tail > headroom) {
+ ringing_tail = headroom;
+ }
+ if (ringing_tail > target_frequency_amount_) {
+ ringing_tail = target_frequency_amount_;
+ }
+
+ target_frequency_offset_ += ringing_tail;
+ target_frequency_amount_ -= ringing_tail;
+ }
+
+
+ private:
+ int32_t target_frequency_amount_;
+ int32_t target_frequency_offset_;
+ int32_t frequency_amount_;
+ int32_t frequency_offset_;
+
+ int32_t attack_coefficient_;
+ int32_t decay_coefficient_;
+ int32_t fast_attack_coefficient_;
+ int32_t fast_decay_coefficient_;
+
+ int32_t state_[4];
+ int32_t excite_;
+
+ bool gate_;
+ bool plucked_;
+
+ DISALLOW_COPY_AND_ASSIGN(Vactrol);
+};
+
+} // namespace streams
+
+#endif // STREAMS_VACTROL_H_
diff --git a/lib/udynlink b/lib/udynlink
index 7337f22..c8773d2 160000
--- a/lib/udynlink
+++ b/lib/udynlink
@@ -1 +1 @@
-Subproject commit 7337f22fd7995540b102cbe44fe6b4ffccd58200
+Subproject commit c8773d288f73285bd6eef0a72ecebc9716ad0f3d
diff --git a/platformio.ini b/platformio.ini
index c8cf4f9..03f42d8 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -9,5 +9,5 @@
[env:squares-and-circles]
apps_json = ./app/index.json
-squares_and_circles_loader = 6e9bfa8 ; minimum loader version
-platform = ./.pio/
+squares_and_circles_loader = 5e1e08e ; minimum loader version
+platform = .pio/
\ No newline at end of file