diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 10535ad..be7d553 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -25,13 +25,11 @@ jobs:
export GCC_PATH=/$(realpath .)/xpack-arm-none-eabi-gcc-10.3.1-2.1/bin/
export PATH="${PATH}:/$(realpath .)/xpack-arm-none-eabi-gcc-10.3.1-2.1/bin/"
arm-none-eabi-gcc --version
- pip install intelhex subprocess32 pyelftools Jinja2
+ pip install intelhex subprocess32 pyelftools Jinja2 platformio
find ./app -type f -name *.bin -exec touch {} +
git submodule update --init
sh ./app/build.sh
git status
- pip install --upgrade platformio mido python-rtmidi intelhex
- pio run -v --environment squares-and-circles
- name: pack_artifacts
run: |
export hash=$(git rev-parse --short HEAD)
@@ -42,6 +40,6 @@ jobs:
mv -v "$f" $HEX_FILE
zip -j -9 $ZIP_FILE $HEX_FILE .github/workflows/LICENSE.txt $(dirname ${f%.*})/loader.sha
sha256sum $ZIP_FILE
- curl -fs -X PUT -u ${{ secrets.UPLOAD_KEY }} ${{ secrets.LATEST_DROP_FOLDER }}/${FIRMWARE}_engines_latest.zip --upload-file $ZIP_FILE || true
- curl -fs -X PUT -u ${{ secrets.UPLOAD_KEY }} ${{ secrets.LATEST_DROP_FOLDER }}/${FIRMWARE}_engines_latest.sha -d "$hash"
+ curl -fs -X PUT -u ${{ secrets.UPLOAD_KEY }} ${{ secrets.LATEST_DROP_FOLDER }}/$ZIP_FILE --upload-file $ZIP_FILE || true
+ curl -fs -X PUT -u ${{ secrets.UPLOAD_KEY }} ${{ secrets.LATEST_DROP_FOLDER }}/${FIRMWARE}_latest.sha -d "$hash"
done
\ No newline at end of file
diff --git a/README.md b/README.md
index 2b7a9d7..c08bc05 100644
--- a/README.md
+++ b/README.md
@@ -9,9 +9,25 @@
ChangeLog
````
-== 2025-07-02
- * Bugfix: DSM0 "CRC32:0x63F R:1"
-== 2024-06-15
+== 2024-09-27
+ * Enhancement:
+ * Mod/SEQ - 4-step sequencer modulation #91
+ * Multitrigs (TR707 etc) #29
+ * TR707 - midi mapping (GM Standard Drum Map) #29
+ * Mod/LFO - New paramter: Waveform #89
+ * CV/LFO - New paramter: Scale, Offset, Waveform #89
+ * IO-PAGE - Listing of modulation trig/cv inputs
+ * Bugfix:
+ * M-OSC/Waveforms - display correct waveform instead of "shape"
+ * out of memory handling / memory fragmentation - no new/delete usings in open303
+ * crash-reporting improvment
+ * Sporadic midi stops working while update with webflasher
+ * New Engines:
+ * SEQ/EuclidRythm
+ * SEQ/EuclidArp
+ * DSM:
+ * One-Engine-Mode
+== 2024-06-14
* Enhancement:
* T1 Clock - resets to begin after 200milis silence
* internal crc32 checks for debugging
@@ -157,9 +173,9 @@ E.g you can chain the mono audio signal from an oscillator machine to the neighb
->[Long press [LEFT]] enters the machine-selection-page.
->[Short press [R-ENCODER]] loads the selected engine.
->[Long press [R-ENCODER]] loads the selected engine - extended mode.
+* [Long press [LEFT]] enters the machine-selection-page.
+* [Short press [R-ENCODER]] loads the selected engine.
+* [Long press [R-ENCODER]] loads the selected engine - extended mode.
* Load & reset I/O settings
* Load & keep IO settings
* Copy #1-4 (parameter values + modulations + I/O settings)
@@ -175,50 +191,69 @@ E.g you can chain the mono audio signal from an oscillator machine to the neighb
## Engines
* **GND**
* `---`
- * Scope
- * FFT
+ * [Scope](https://github.com/eh2k/squares-and-circles/wiki/Scope)
+ * [FFT](https://github.com/eh2k/squares-and-circles/wiki/FFT)
* **CV**
* [V/OCT](https://github.com/eh2k/squares-and-circles/wiki/V_OCT)
- * EnvGen_AD
- * EnvGen_ADSR
- * LFO
- * EnvFollower
+ * [EnvGen_AD](https://github.com/eh2k/squares-and-circles/wiki/EnvGen_AD)
+ * [EnvGen_ADSR](https://github.com/eh2k/squares-and-circles/wiki/EnvGen_ADSR)
+ * [LFO](https://github.com/eh2k/squares-and-circles/wiki/LFO)
+ * [EnvFollower](https://github.com/eh2k/squares-and-circles/wiki/EnvFollower)
* **Drums**
- * Analog-BD, Analog SD, Analog HH, Analog HH2
- * 909ish-BD, 909ish-SD, [TR909-HiHat, TR909-Ride](https://github.com/eh2k/squares-and-circles/wiki/TR909_HiHats)
- * 808ish-BD, 808ish-SD, 808ish-HiHat
- * TR707, TR707-HiHat
+ * [Analog-BD](https://github.com/eh2k/squares-and-circles/wiki/Analog-BD),
+ * [Analog-SD](https://github.com/eh2k/squares-and-circles/wiki/Analog-SD),
+ * [Analog-HH](https://github.com/eh2k/squares-and-circles/wiki/Analog-HH),
+ * [Analog-HH2](https://github.com/eh2k/squares-and-circles/wiki/Analog-HH2),
+ * [909ish-BD](https://github.com/eh2k/squares-and-circles/wiki/909ish-BD),
+ * [909ish-SD](https://github.com/eh2k/squares-and-circles/wiki/909ish-SD),
+ * [TR909-HiHat, TR909-Ride](https://github.com/eh2k/squares-and-circles/wiki/TR909_HiHats)
+ * [808ish-BD](https://github.com/eh2k/squares-and-circles/wiki/808ish-BD),
+ * [808ish-SD](https://github.com/eh2k/squares-and-circles/wiki/808ish-SD),
+ * [808ish-HiHat](https://github.com/eh2k/squares-and-circles/wiki/808ish-HiHat),
+ * [TR707](https://github.com/eh2k/squares-and-circles/wiki/TR707),
+ * [DMX](https://github.com/eh2k/squares-and-circles/wiki/DMX),
+ * [Linn](https://github.com/eh2k/squares-and-circles/wiki/Linn),
* [FM-Drum](https://github.com/eh2k/squares-and-circles/wiki/FM-Drum)
- * Djembe
+ * [Djembe](https://github.com/eh2k/squares-and-circles/wiki/Djembe)
* [Claps](https://github.com/eh2k/squares-and-circles/wiki/Claps)
* **M-OSC**
* [Waveforms](https://github.com/eh2k/squares-and-circles/wiki/Waveforms)
- * Virt.Analog, Waveshaping, FM, Grain, Additive, Wavetable, Chord
+ * [Virt.Analog](https://github.com/eh2k/squares-and-circles/wiki/Virt.Analog)
+ * [Waveshaping](https://github.com/eh2k/squares-and-circles/wiki/Waveshaping)
+ * [2-OP-FM](https://github.com/eh2k/squares-and-circles/wiki/2-OP-FM)
+ * [Formant/PD](https://github.com/eh2k/squares-and-circles/wiki/Formant-PD)
+ * [Harmonic](https://github.com/eh2k/squares-and-circles/wiki/Harmonic)
+ * [Wavetable](https://github.com/eh2k/squares-and-circles/wiki/Waveforms)
+ * [Chord](https://github.com/eh2k/squares-and-circles/wiki/Waveforms)
* **SYNTH**
- * Resonator
+ * [Resonator](https://github.com/eh2k/squares-and-circles/wiki/Resonator)
* [DxFM](https://github.com/eh2k/squares-and-circles/wiki/DxFM)
* [DxFM_BNK1-3](lib/plaits/resources.cc#L41)
* [Open303](https://github.com/eh2k/squares-and-circles/wiki/Open303)
* [ClassicVAVCF](lib/plaits/dsp/engine2/virtual_analog_vcf_engine.cc)
* **Stereo-FX**
* [Reverb](https://github.com/eh2k/squares-and-circles/wiki/clouds_reverb)
- * ReverbSC
- * Rev-Dattorro
- * Delay
- * Gated-Reverb
- * Reverb-HP-LP
+ * [ReverbSC](https://github.com/eh2k/squares-and-circles/wiki/ReverbSC)
+ * [Rev-Dattorro](https://github.com/eh2k/squares-and-circles/wiki/Rev-Dattorro)
+ * [Delay](https://github.com/eh2k/squares-and-circles/wiki/Delay)
+ * [Gated-Reverb](https://github.com/eh2k/squares-and-circles/wiki/Gated-Reverb)
+ * [Reverb-HP-LP](https://github.com/eh2k/squares-and-circles/wiki/Reverb-HP-LP)
* [JU60_chorus](https://github.com/eh2k/squares-and-circles/wiki/JU60_chorus)
* **NOISE**
* [White/Pink](https://github.com/eh2k/squares-and-circles/wiki/White_Pink_noise)
* [NES_noise](https://github.com/eh2k/squares-and-circles/wiki/NES_noise)
* [808_squares](https://github.com/eh2k/squares-and-circles/wiki/808_squares)
* **SPEECH**
- * LPC
+ * [LPC](https://github.com/eh2k/squares-and-circles/wiki/LPC)
* [SAM](https://github.com/eh2k/squares-and-circles/wiki/SAM)
* **MIDI**
- * Monitor
- * Clock
- * VAx6
+ * [Monitor](https://github.com/eh2k/squares-and-circles/wiki/Monitor)
+ * [Clock](https://github.com/eh2k/squares-and-circles/wiki/Clock)
+ * [VAx6](https://github.com/eh2k/squares-and-circles/wiki/VAx6)
+* **SEQ**
+ * [EuclidRythm](https://github.com/eh2k/squares-and-circles/wiki/EuclidRythm)
+ * [EuclidArp](https://github.com/eh2k/squares-and-circles/wiki/EuclidArp)
+
## Machine/Engine
@@ -257,16 +292,21 @@ For each parameter a modulation can be assigned:
* DECAY
* **LFO**: Free/Triggered Sine-LFO
* TRIG: `-`, `!`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4`
- * SHAPE
- * FREQUENCY
+ * SHAPE: `SIN`, `TRI`, `SQR`, `STEPS`, `NOISE`
+ * FREQUENCY: `0-127`
+ * WAVEFORM: `0-127`
* **EF**: Envelope Follower
* SRC: `C1`, `C2`, `C3`, `C4`
* ATTACK
* RELEASE
* **TM**: Turing Machine
- * TRIG: `!`, `CLK`, `T1`, `T2`, `T3`, `T4`
+ * TRIG: `!`, `CLK`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4`
* PROB: `0-9` (0-100%)
* STEPS: `1-16`
+ * **SEQ**: 4-Step Sequencer
+ * TRIG: `!`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4`, `CLK/1`, `CLK/4`, `CLK/16`, `CLK/32`, `CLK/96`
+ * RESET: `-`, `T1`, `T2`, `T3`, `T4`, `C1`, `C2`, `C3`, `C4`
+ * 4-STEPS: `-64..64`
>`!` = current engine trigger
>`CLK` = internal clock
All modulations have an attenuverter parameter (-/+).
diff --git a/app/CV/EnvGen_ADSR.bin b/app/CV/EnvGen_ADSR.bin
new file mode 100644
index 0000000..a957d2e
Binary files /dev/null and b/app/CV/EnvGen_ADSR.bin differ
diff --git a/app/CV/EnvGen_ADSR.cpp b/app/CV/EnvGen_ADSR.cpp
new file mode 100644
index 0000000..5eb8366
--- /dev/null
+++ b/app/CV/EnvGen_ADSR.cpp
@@ -0,0 +1,117 @@
+// 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 "peaks/modulations/multistage_envelope.h"
+#include "peaks/modulations/multistage_envelope.cc"
+#include "../DRUMS/resources/peaks_lut_env.hpp"
+
+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;
+
+peaks::GateFlags flags[FRAME_BUFFER_SIZE];
+int16_t buffer[FRAME_BUFFER_SIZE];
+
+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);
+ engine::addParam("Sustain", &_sustain, 0, UINT16_MAX);
+ engine::addParam("Release", &_release, 0, UINT16_MAX);
+ engine::setMode(ENGINE_MODE_COMPACT | ENGINE_MODE_CV_OUT);
+}
+
+void engine::process()
+{
+ uint16_t params[4];
+ params[0] = _attack;
+ params[1] = _decay;
+ params[2] = _sustain;
+ params[3] = _release;
+ _processor.Configure(params, peaks::CONTROL_MODE_FULL);
+
+ 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);
+ }
+
+ _processor.Process(flags, buffer, FRAME_BUFFER_SIZE);
+
+ static float 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++)
+ engine::outputBuffer<0>()[i] = (float)buffer[i] / -INT16_MIN * 8.f;
+}
+
+void engine::draw()
+{
+ _scope.draw(56);
+}
\ No newline at end of file
diff --git a/app/DRUMS/Djembe.bin b/app/DRUMS/Djembe.bin
index 33a93dd..df3e3c5 100644
Binary files a/app/DRUMS/Djembe.bin and b/app/DRUMS/Djembe.bin differ
diff --git a/app/DRUMS/TR707-HiHat.bin b/app/DRUMS/TR707-HiHat.bin
deleted file mode 100644
index 372a933..0000000
Binary files a/app/DRUMS/TR707-HiHat.bin and /dev/null differ
diff --git a/app/DRUMS/TR707-HiHat.cpp b/app/DRUMS/TR707-HiHat.cpp
deleted file mode 100644
index 96f6bc2..0000000
--- a/app/DRUMS/TR707-HiHat.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "../squares-and-circles-api.h"
-
-// #include "eproms/tr707/IC35_TR707_SNDROM.h"
-const uint8_t *IC35_TR707_SNDROM_bin = machine::fs_read("707_IC35");
-
-constexpr static int ch_start = 24576;
-
-static float _ch_vol = 1.f;
-static float _ch_dec = 0.2f;
-static float _oh_dec = 0.5f;
-
-int32_t _select = 0;
-void *_ch;
-void *_oh;
-
-void engine::setup()
-{
- const uint8_t *HH = &IC35_TR707_SNDROM_bin[0x2000];
- _ch = dsp_sample_u8(HH, 0x2000, 25000, 0);
- _oh = dsp_sample_u8(HH, 0x2000, 25000, 0);
-
- engine::addParam("", &_select, 0, 0); // . = hidden
- engine::addParam("CH-Lev", &_ch_vol);
- engine::addParam("CH-Dec", &_ch_dec);
- engine::addParam("OH-Dec", &_oh_dec);
-}
-
-void engine::process()
-{
- auto outputL = engine::outputBuffer<0>();
- memset(outputL, 0, sizeof(float) * FRAME_BUFFER_SIZE);
- dsp_process_hihats(_ch, _oh, _ch_vol, _ch_dec, _oh_dec, outputL);
-}
\ No newline at end of file
diff --git a/app/DRUMS/TR707.bin b/app/DRUMS/TR707.bin
index 4a2d6c4..366a5fe 100644
Binary files a/app/DRUMS/TR707.bin and b/app/DRUMS/TR707.bin differ
diff --git a/app/DRUMS/TR707.cpp b/app/DRUMS/TR707.cpp
index ad27f34..dac4991 100644
--- a/app/DRUMS/TR707.cpp
+++ b/app/DRUMS/TR707.cpp
@@ -3,17 +3,16 @@
// #include "eproms/tr707/IC34_TR707_SNDROM.h"
// #include "eproms/tr707/IC35_TR707_SNDROM.h"
-static auto IC34_TR707_SNDROM_bin = machine::fs_read("707_IC34");
-static auto IC35_TR707_SNDROM_bin = machine::fs_read("707_IC35");
static float _pitch = 0.5f;
static float _start = 0.f;
static float _end = 1.f;
static float _amp = 1.f;
+int32_t _midi_trigs = 0;
int32_t _select = 0;
-const char *sample_names[12];
-void *sample_ptr[12];
+const char *sample_names[13];
+void *sample_ptr[13];
#define SETUP_SAMPLE(name, ptr) \
sample_names[_select] = name; \
sample_ptr[_select] = ptr; \
@@ -21,6 +20,9 @@ void *sample_ptr[12];
void engine::setup()
{
+ auto IC34_TR707_SNDROM_bin = machine::fs_read("707_IC34");
+ auto IC35_TR707_SNDROM_bin = machine::fs_read("707_IC35");
+
auto BD0 = &IC34_TR707_SNDROM_bin[0x0000];
auto BD1 = &IC34_TR707_SNDROM_bin[0x0001];
auto SD0 = &IC34_TR707_SNDROM_bin[0x2000];
@@ -47,19 +49,116 @@ void engine::setup()
SETUP_SAMPLE("LT", dsp_sample_u8(LT, 0x1000, 25000, 0));
SETUP_SAMPLE("MT", dsp_sample_u8(MT, 0x1000, 25000, 0));
SETUP_SAMPLE("HT", dsp_sample_u8(HT, 0x1000, 25000, 0));
- SETUP_SAMPLE("HH", dsp_sample_u8(HH, 0x1000, 25000, 0));
+ SETUP_SAMPLE("CH", dsp_sample_u8(HH, 0x1000, 25000, 0));
+ SETUP_SAMPLE("OH", dsp_sample_u8(HH, 0x1000, 25000, 0));
engine::addParam("Pitch", &_pitch);
- engine::addParam(">Sample", &_select, 0, LEN_OF(sample_names) - 1, sample_names); // . = hidden
+ engine::addParam(MULTI_TRIGS, &_select, 0, LEN_OF(sample_names) - 1, sample_names); // . = hidden
_select = 0;
engine::addParam("Start", &_start);
engine::addParam("End", &_end);
+
+ engine::setMode(ENGINE_MODE_MIDI_IN);
}
void engine::process()
{
auto outputL = engine::outputBuffer<0>();
memset(outputL, 0, sizeof(float) * FRAME_BUFFER_SIZE);
- dsp_process_sample(sample_ptr[_select], _start, _end, _pitch, outputL);
+
+ for (uint32_t i = 0; i < LEN_OF(sample_ptr); i++)
+ {
+ if (engine::trig() & (1 << i) || _midi_trigs & (1 << i))
+ {
+ if (i == 11) // CH
+ {
+ if (!(engine::trig() & (1 << (i + 1)))) // OH
+ {
+ dsp_set_sample_pos(sample_ptr[i], _start, 0.7f, 0.2f);
+ dsp_set_sample_pos(sample_ptr[i + 1], _start, 0, 1.0f);
+ }
+ }
+ else
+ {
+ dsp_set_sample_pos(sample_ptr[i], _start, 1.f, 1.f);
+ }
+
+ _midi_trigs &= ~(1 << i);
+ }
+
+ dsp_process_sample(sample_ptr[i], _start, _end, -2.f + (_pitch * 4), outputL);
+ }
+}
+
+void engine::draw()
+{
+ gfx::drawSample(sample_ptr[_select]);
+}
+
+void engine::onMidiNote(uint8_t key, uint8_t velocity) // NoteOff: velocity == 0
+{
+ if (velocity > 0)
+ {
+ switch (key)
+ {
+ case 35: // BD0
+ _midi_trigs |= (1 << 0);
+ break;
+ case 36: // BD1
+ _midi_trigs |= (1 << 1);
+ break;
+ case 38: // SD0
+ _midi_trigs |= (1 << 2);
+ break;
+ case 40: // SD1
+ _midi_trigs |= (1 << 3);
+ break;
+ case 39: // CP
+ _midi_trigs |= (1 << 4);
+ break;
+ case 54: // TMB
+ _midi_trigs |= (1 << 5);
+ break;
+ case 37: // RM
+ _midi_trigs |= (1 << 6);
+ break;
+ case 56: // CB
+ _midi_trigs |= (1 << 7);
+ break;
+ case 41: // LT
+ case 43: // LT
+ _midi_trigs |= (1 << 8);
+ break;
+ case 45: // MT
+ case 47: // MT
+ _midi_trigs |= (1 << 9);
+ break;
+ case 48: // HT
+ case 50: // HT
+ _midi_trigs |= (1 << 10);
+ break;
+ case 42: // CH
+ case 44: // CH
+ case 46: // OH
+ _midi_trigs |= (1 << 11);
+ break;
+ }
+ }
+ else
+ {
+ }
+}
+
+void engine::onMidiPitchbend(int16_t pitch)
+{
+}
+
+void engine::onMidiCC(uint8_t ccc, uint8_t value)
+{
+ // nothing implemented..
+}
+
+void engine::onMidiSysex(uint8_t byte)
+{
}
\ No newline at end of file
diff --git a/app/DRUMS/TR909-HiHat.bin b/app/DRUMS/TR909-HiHat.bin
index 9b61560..b16aab7 100644
Binary files a/app/DRUMS/TR909-HiHat.bin and b/app/DRUMS/TR909-HiHat.bin differ
diff --git a/app/DRUMS/TR909-HiHat.cpp b/app/DRUMS/TR909-HiHat.cpp
index c6a50f7..e489e52 100644
--- a/app/DRUMS/TR909-HiHat.cpp
+++ b/app/DRUMS/TR909-HiHat.cpp
@@ -27,5 +27,17 @@ void engine::process()
{
auto outputL = engine::outputBuffer<0>();
memset(outputL, 0, sizeof(float) * FRAME_BUFFER_SIZE);
- dsp_process_hihats(_ch, _oh, _ch_vol, _ch_dec, _oh_dec, outputL);
+
+ if (engine::accent()) // OH
+ {
+ dsp_set_sample_pos(_oh, 0, 1.f, _oh_dec);
+ }
+ else if (engine::trig()) // CH
+ {
+ dsp_set_sample_pos(_ch, 0, _ch_vol, _ch_dec);
+ dsp_set_sample_pos(_oh, 0, 0, _oh_dec);
+ }
+
+ dsp_process_sample(_ch, 0, 1, engine::cv(), outputL);
+ dsp_process_sample(_oh, 0, 1, engine::cv(), outputL);
}
\ No newline at end of file
diff --git a/app/DRUMS/TR909-Ride.bin b/app/DRUMS/TR909-Ride.bin
index 9bc3767..57d87b6 100644
Binary files a/app/DRUMS/TR909-Ride.bin and b/app/DRUMS/TR909-Ride.bin differ
diff --git a/app/DRUMS/TR909-Ride.cpp b/app/DRUMS/TR909-Ride.cpp
index c85b9e2..a416e0e 100644
--- a/app/DRUMS/TR909-Ride.cpp
+++ b/app/DRUMS/TR909-Ride.cpp
@@ -28,5 +28,18 @@ void engine::process()
{
auto outputL = engine::outputBuffer<0>();
memset(outputL, 0, sizeof(float) * FRAME_BUFFER_SIZE);
- dsp_process_hihats(_ch, _oh, _ch_vol, _ch_dec, _oh_dec, outputL);
+
+ if (engine::accent()) //OH
+ {
+ dsp_set_sample_pos(_ch, 0, 0, _oh_dec);
+ dsp_set_sample_pos(_oh, 0, 1.f, _oh_dec);
+ }
+ else if (engine::trig()) // CH
+ {
+ dsp_set_sample_pos(_ch, 0, _ch_vol, _ch_dec);
+ dsp_set_sample_pos(_oh, 0, 0, _oh_dec);
+ }
+
+ dsp_process_sample(_ch, 0, 1, engine::cv(), outputL);
+ dsp_process_sample(_oh, 0, 1, engine::cv(), outputL);
}
\ No newline at end of file
diff --git a/app/DRUMS/resources/braids_lut_env.hpp b/app/DRUMS/resources/braids_lut_env.hpp
new file mode 100644
index 0000000..83a20bf
--- /dev/null
+++ b/app/DRUMS/resources/braids_lut_env.hpp
@@ -0,0 +1,105 @@
+namespace braids {
+ const uint16_t lut_env_expo[] FLASHMEM = {
+ 0, 1034, 2053, 3057,
+ 4044, 5016, 5974, 6916,
+ 7844, 8757, 9656, 10542,
+ 11413, 12271, 13116, 13948,
+ 14766, 15572, 16366, 17147,
+ 17916, 18673, 19419, 20153,
+ 20875, 21587, 22287, 22976,
+ 23655, 24323, 24981, 25629,
+ 26267, 26894, 27512, 28121,
+ 28720, 29310, 29890, 30462,
+ 31024, 31578, 32124, 32661,
+ 33189, 33710, 34222, 34727,
+ 35223, 35712, 36193, 36667,
+ 37134, 37593, 38045, 38490,
+ 38928, 39360, 39785, 40203,
+ 40615, 41020, 41419, 41812,
+ 42198, 42579, 42954, 43323,
+ 43686, 44044, 44396, 44743,
+ 45084, 45420, 45751, 46077,
+ 46397, 46713, 47024, 47330,
+ 47631, 47927, 48219, 48507,
+ 48790, 49068, 49342, 49612,
+ 49878, 50140, 50398, 50651,
+ 50901, 51147, 51389, 51627,
+ 51862, 52092, 52320, 52544,
+ 52764, 52981, 53195, 53405,
+ 53612, 53816, 54016, 54214,
+ 54408, 54600, 54788, 54974,
+ 55156, 55336, 55513, 55688,
+ 55859, 56028, 56195, 56358,
+ 56520, 56678, 56835, 56988,
+ 57140, 57289, 57436, 57580,
+ 57723, 57863, 58001, 58136,
+ 58270, 58402, 58531, 58659,
+ 58784, 58908, 59029, 59149,
+ 59267, 59383, 59498, 59610,
+ 59721, 59830, 59937, 60043,
+ 60147, 60250, 60351, 60450,
+ 60548, 60644, 60739, 60832,
+ 60924, 61014, 61103, 61191,
+ 61277, 61362, 61446, 61528,
+ 61609, 61689, 61768, 61845,
+ 61921, 61996, 62070, 62143,
+ 62214, 62285, 62354, 62422,
+ 62490, 62556, 62621, 62685,
+ 62748, 62810, 62871, 62932,
+ 62991, 63049, 63107, 63163,
+ 63219, 63274, 63328, 63381,
+ 63434, 63485, 63536, 63586,
+ 63635, 63683, 63731, 63778,
+ 63824, 63870, 63914, 63958,
+ 64002, 64045, 64087, 64128,
+ 64169, 64209, 64248, 64287,
+ 64326, 64363, 64400, 64437,
+ 64473, 64508, 64543, 64577,
+ 64611, 64645, 64677, 64710,
+ 64741, 64773, 64803, 64834,
+ 64863, 64893, 64922, 64950,
+ 64978, 65006, 65033, 65060,
+ 65086, 65112, 65137, 65162,
+ 65187, 65212, 65236, 65259,
+ 65282, 65305, 65328, 65350,
+ 65372, 65393, 65414, 65435,
+ 65456, 65476, 65496, 65515,
+ 65535,
+};
+
+const uint32_t lut_env_portamento_increments[] FLASHMEM = {
+ 1431655765, 1208633567, 1025339217, 873854034,
+ 747996982, 642910145, 554750639, 480459775,
+ 417588783, 364166300, 318596895, 279582889,
+ 246063710, 217168604, 192179528, 170501890,
+ 151641346, 135185326, 120788231, 108159539,
+ 97054201, 87264844, 78615425, 70956050,
+ 64158714, 58113796, 52727166, 47917783,
+ 43615697, 39760385, 36299356, 33186980,
+ 30383504, 27854220, 25568762, 23500507,
+ 21626072, 19924877, 18378778, 16971748,
+ 15689604, 14519780, 13451115, 12473688,
+ 11578663, 10758156, 10005128, 9313280,
+ 8676970, 8091136, 7551232, 7053169,
+ 6593263, 6168194, 5774964, 5410864,
+ 5073442, 4760475, 4469950, 4200037,
+ 3949073, 3715547, 3498079, 3295415,
+ 3106409, 2930012, 2765269, 2611303,
+ 2467313, 2332562, 2206377, 2088136,
+ 1977272, 1873260, 1775618, 1683902,
+ 1597702, 1516641, 1440370, 1368566,
+ 1300932, 1237191, 1177088, 1120388,
+ 1066869, 1016330, 968580, 923445,
+ 880761, 840376, 802150, 765951,
+ 731657, 699152, 668331, 639094,
+ 611349, 585008, 559991, 536221,
+ 513628, 492146, 471711, 452267,
+ 433757, 416131, 399341, 383341,
+ 368089, 353545, 339672, 326434,
+ 313798, 301733, 290209, 279199,
+ 268677, 258617, 248997, 239795,
+ 230990, 222562, 214494, 206767,
+ 199365, 192272, 185474, 178956,
+};
+
+}
\ No newline at end of file
diff --git a/app/DRUMS/resources/peaks_lut_env.hpp b/app/DRUMS/resources/peaks_lut_env.hpp
new file mode 100644
index 0000000..4825475
--- /dev/null
+++ b/app/DRUMS/resources/peaks_lut_env.hpp
@@ -0,0 +1,271 @@
+namespace peaks {
+const uint16_t lut_env_linear[] FLASHMEM = {
+ 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[] FLASHMEM = {
+ 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[] FLASHMEM = {
+ 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 uint32_t lut_env_increments[] FLASHMEM = {
+ 178956970, 162203921, 147263779, 133914742,
+ 121965179, 111249129, 101622525, 92960022,
+ 85152324, 78103929, 71731214, 65960813,
+ 60728233, 55976673, 51656020, 47721976,
+ 44135321, 40861270, 37868923, 35130786,
+ 32622357, 30321772, 28209484, 26268003,
+ 24481648, 22836346, 21319451, 19919582,
+ 18626484, 17430905, 16324491, 15299685,
+ 14349647, 13468178, 12649652, 11888959,
+ 11181454, 10522909, 9909470, 9337624,
+ 8804164, 8306157, 7840925, 7406012,
+ 6999170, 6618338, 6261623, 5927288,
+ 5613733, 5319488, 5043200, 4783621,
+ 4539601, 4310076, 4094068, 3890668,
+ 3699040, 3518407, 3348049, 3187303,
+ 3035548, 2892213, 2756766, 2628711,
+ 2507588, 2392971, 2284460, 2181685,
+ 2084301, 1991984, 1904435, 1821372,
+ 1742534, 1667676, 1596567, 1528995,
+ 1464759, 1403670, 1345553, 1290243,
+ 1237585, 1187435, 1139655, 1094119,
+ 1050706, 1009303, 969803, 932108,
+ 896122, 861758, 828932, 797565,
+ 767584, 738918, 711503, 685274,
+ 660174, 636148, 613143, 591109,
+ 569999, 549770, 530379, 511787,
+ 493956, 476850, 460436, 444683,
+ 429558, 415035, 401085, 387683,
+ 374804, 362424, 350523, 339078,
+ 328069, 317479, 307287, 297478,
+ 288035, 278942, 270184, 261748,
+ 253620, 245786, 238236, 230956,
+ 223936, 217166, 210635, 204334,
+ 198253, 192383, 186717, 181245,
+ 175961, 170858, 165927, 161162,
+ 156558, 152107, 147805, 143644,
+ 139621, 135729, 131964, 128321,
+ 124796, 121384, 118081, 114883,
+ 111787, 108788, 105883, 103069,
+ 100343, 97700, 95139, 92657,
+ 90250, 87917, 85654, 83459,
+ 81330, 79265, 77261, 75316,
+ 73428, 71596, 69817, 68090,
+ 66413, 64784, 63202, 61666,
+ 60173, 58722, 57312, 55942,
+ 54610, 53315, 52056, 50832,
+ 49641, 48484, 47357, 46262,
+ 45196, 44159, 43149, 42167,
+ 41211, 40280, 39374, 38492,
+ 37632, 36796, 35981, 35187,
+ 34414, 33660, 32926, 32211,
+ 31513, 30834, 30172, 29526,
+ 28896, 28282, 27684, 27100,
+ 26531, 25975, 25434, 24905,
+ 24390, 23886, 23395, 22916,
+ 22449, 21992, 21546, 21111,
+ 20687, 20272, 19867, 19471,
+ 19085, 18708, 18339, 17979,
+ 17627, 17283, 16947, 16619,
+ 16298, 15985, 15678, 15378,
+ 15085, 14799, 14519, 14245,
+ 13977, 13716, 13459, 13209,
+ 12964, 12724, 12490, 12260,
+ 12036, 11816, 11601, 11390,
+ 11184,
+};
+}
\ No newline at end of file
diff --git a/app/DRUMS/resources/peaks_lut_osc.hpp b/app/DRUMS/resources/peaks_lut_osc.hpp
new file mode 100644
index 0000000..90c2822
--- /dev/null
+++ b/app/DRUMS/resources/peaks_lut_osc.hpp
@@ -0,0 +1,548 @@
+namespace peaks {
+const int16_t wav_sine[] FLASHMEM = {
+ 0, 201, 402, 603,
+ 804, 1005, 1206, 1406,
+ 1607, 1808, 2009, 2209,
+ 2410, 2610, 2811, 3011,
+ 3211, 3411, 3611, 3811,
+ 4011, 4210, 4409, 4608,
+ 4807, 5006, 5205, 5403,
+ 5601, 5799, 5997, 6195,
+ 6392, 6589, 6786, 6982,
+ 7179, 7375, 7571, 7766,
+ 7961, 8156, 8351, 8545,
+ 8739, 8932, 9126, 9319,
+ 9511, 9703, 9895, 10087,
+ 10278, 10469, 10659, 10849,
+ 11038, 11227, 11416, 11604,
+ 11792, 11980, 12166, 12353,
+ 12539, 12724, 12909, 13094,
+ 13278, 13462, 13645, 13827,
+ 14009, 14191, 14372, 14552,
+ 14732, 14911, 15090, 15268,
+ 15446, 15623, 15799, 15975,
+ 16150, 16325, 16499, 16672,
+ 16845, 17017, 17189, 17360,
+ 17530, 17699, 17868, 18036,
+ 18204, 18371, 18537, 18702,
+ 18867, 19031, 19194, 19357,
+ 19519, 19680, 19840, 20000,
+ 20159, 20317, 20474, 20631,
+ 20787, 20942, 21096, 21249,
+ 21402, 21554, 21705, 21855,
+ 22004, 22153, 22301, 22448,
+ 22594, 22739, 22883, 23027,
+ 23169, 23311, 23452, 23592,
+ 23731, 23869, 24006, 24143,
+ 24278, 24413, 24546, 24679,
+ 24811, 24942, 25072, 25201,
+ 25329, 25456, 25582, 25707,
+ 25831, 25954, 26077, 26198,
+ 26318, 26437, 26556, 26673,
+ 26789, 26905, 27019, 27132,
+ 27244, 27355, 27466, 27575,
+ 27683, 27790, 27896, 28001,
+ 28105, 28208, 28309, 28410,
+ 28510, 28608, 28706, 28802,
+ 28897, 28992, 29085, 29177,
+ 29268, 29358, 29446, 29534,
+ 29621, 29706, 29790, 29873,
+ 29955, 30036, 30116, 30195,
+ 30272, 30349, 30424, 30498,
+ 30571, 30643, 30713, 30783,
+ 30851, 30918, 30984, 31049,
+ 31113, 31175, 31236, 31297,
+ 31356, 31413, 31470, 31525,
+ 31580, 31633, 31684, 31735,
+ 31785, 31833, 31880, 31926,
+ 31970, 32014, 32056, 32097,
+ 32137, 32176, 32213, 32249,
+ 32284, 32318, 32350, 32382,
+ 32412, 32441, 32468, 32495,
+ 32520, 32544, 32567, 32588,
+ 32609, 32628, 32646, 32662,
+ 32678, 32692, 32705, 32717,
+ 32727, 32736, 32744, 32751,
+ 32757, 32761, 32764, 32766,
+ 32767, 32766, 32764, 32761,
+ 32757, 32751, 32744, 32736,
+ 32727, 32717, 32705, 32692,
+ 32678, 32662, 32646, 32628,
+ 32609, 32588, 32567, 32544,
+ 32520, 32495, 32468, 32441,
+ 32412, 32382, 32350, 32318,
+ 32284, 32249, 32213, 32176,
+ 32137, 32097, 32056, 32014,
+ 31970, 31926, 31880, 31833,
+ 31785, 31735, 31684, 31633,
+ 31580, 31525, 31470, 31413,
+ 31356, 31297, 31236, 31175,
+ 31113, 31049, 30984, 30918,
+ 30851, 30783, 30713, 30643,
+ 30571, 30498, 30424, 30349,
+ 30272, 30195, 30116, 30036,
+ 29955, 29873, 29790, 29706,
+ 29621, 29534, 29446, 29358,
+ 29268, 29177, 29085, 28992,
+ 28897, 28802, 28706, 28608,
+ 28510, 28410, 28309, 28208,
+ 28105, 28001, 27896, 27790,
+ 27683, 27575, 27466, 27355,
+ 27244, 27132, 27019, 26905,
+ 26789, 26673, 26556, 26437,
+ 26318, 26198, 26077, 25954,
+ 25831, 25707, 25582, 25456,
+ 25329, 25201, 25072, 24942,
+ 24811, 24679, 24546, 24413,
+ 24278, 24143, 24006, 23869,
+ 23731, 23592, 23452, 23311,
+ 23169, 23027, 22883, 22739,
+ 22594, 22448, 22301, 22153,
+ 22004, 21855, 21705, 21554,
+ 21402, 21249, 21096, 20942,
+ 20787, 20631, 20474, 20317,
+ 20159, 20000, 19840, 19680,
+ 19519, 19357, 19194, 19031,
+ 18867, 18702, 18537, 18371,
+ 18204, 18036, 17868, 17699,
+ 17530, 17360, 17189, 17017,
+ 16845, 16672, 16499, 16325,
+ 16150, 15975, 15799, 15623,
+ 15446, 15268, 15090, 14911,
+ 14732, 14552, 14372, 14191,
+ 14009, 13827, 13645, 13462,
+ 13278, 13094, 12909, 12724,
+ 12539, 12353, 12166, 11980,
+ 11792, 11604, 11416, 11227,
+ 11038, 10849, 10659, 10469,
+ 10278, 10087, 9895, 9703,
+ 9511, 9319, 9126, 8932,
+ 8739, 8545, 8351, 8156,
+ 7961, 7766, 7571, 7375,
+ 7179, 6982, 6786, 6589,
+ 6392, 6195, 5997, 5799,
+ 5601, 5403, 5205, 5006,
+ 4807, 4608, 4409, 4210,
+ 4011, 3811, 3611, 3411,
+ 3211, 3011, 2811, 2610,
+ 2410, 2209, 2009, 1808,
+ 1607, 1406, 1206, 1005,
+ 804, 603, 402, 201,
+ 0, -201, -402, -603,
+ -804, -1005, -1206, -1406,
+ -1607, -1808, -2009, -2209,
+ -2410, -2610, -2811, -3011,
+ -3211, -3411, -3611, -3811,
+ -4011, -4210, -4409, -4608,
+ -4807, -5006, -5205, -5403,
+ -5601, -5799, -5997, -6195,
+ -6392, -6589, -6786, -6982,
+ -7179, -7375, -7571, -7766,
+ -7961, -8156, -8351, -8545,
+ -8739, -8932, -9126, -9319,
+ -9511, -9703, -9895, -10087,
+ -10278, -10469, -10659, -10849,
+ -11038, -11227, -11416, -11604,
+ -11792, -11980, -12166, -12353,
+ -12539, -12724, -12909, -13094,
+ -13278, -13462, -13645, -13827,
+ -14009, -14191, -14372, -14552,
+ -14732, -14911, -15090, -15268,
+ -15446, -15623, -15799, -15975,
+ -16150, -16325, -16499, -16672,
+ -16845, -17017, -17189, -17360,
+ -17530, -17699, -17868, -18036,
+ -18204, -18371, -18537, -18702,
+ -18867, -19031, -19194, -19357,
+ -19519, -19680, -19840, -20000,
+ -20159, -20317, -20474, -20631,
+ -20787, -20942, -21096, -21249,
+ -21402, -21554, -21705, -21855,
+ -22004, -22153, -22301, -22448,
+ -22594, -22739, -22883, -23027,
+ -23169, -23311, -23452, -23592,
+ -23731, -23869, -24006, -24143,
+ -24278, -24413, -24546, -24679,
+ -24811, -24942, -25072, -25201,
+ -25329, -25456, -25582, -25707,
+ -25831, -25954, -26077, -26198,
+ -26318, -26437, -26556, -26673,
+ -26789, -26905, -27019, -27132,
+ -27244, -27355, -27466, -27575,
+ -27683, -27790, -27896, -28001,
+ -28105, -28208, -28309, -28410,
+ -28510, -28608, -28706, -28802,
+ -28897, -28992, -29085, -29177,
+ -29268, -29358, -29446, -29534,
+ -29621, -29706, -29790, -29873,
+ -29955, -30036, -30116, -30195,
+ -30272, -30349, -30424, -30498,
+ -30571, -30643, -30713, -30783,
+ -30851, -30918, -30984, -31049,
+ -31113, -31175, -31236, -31297,
+ -31356, -31413, -31470, -31525,
+ -31580, -31633, -31684, -31735,
+ -31785, -31833, -31880, -31926,
+ -31970, -32014, -32056, -32097,
+ -32137, -32176, -32213, -32249,
+ -32284, -32318, -32350, -32382,
+ -32412, -32441, -32468, -32495,
+ -32520, -32544, -32567, -32588,
+ -32609, -32628, -32646, -32662,
+ -32678, -32692, -32705, -32717,
+ -32727, -32736, -32744, -32751,
+ -32757, -32761, -32764, -32766,
+ -32767, -32766, -32764, -32761,
+ -32757, -32751, -32744, -32736,
+ -32727, -32717, -32705, -32692,
+ -32678, -32662, -32646, -32628,
+ -32609, -32588, -32567, -32544,
+ -32520, -32495, -32468, -32441,
+ -32412, -32382, -32350, -32318,
+ -32284, -32249, -32213, -32176,
+ -32137, -32097, -32056, -32014,
+ -31970, -31926, -31880, -31833,
+ -31785, -31735, -31684, -31633,
+ -31580, -31525, -31470, -31413,
+ -31356, -31297, -31236, -31175,
+ -31113, -31049, -30984, -30918,
+ -30851, -30783, -30713, -30643,
+ -30571, -30498, -30424, -30349,
+ -30272, -30195, -30116, -30036,
+ -29955, -29873, -29790, -29706,
+ -29621, -29534, -29446, -29358,
+ -29268, -29177, -29085, -28992,
+ -28897, -28802, -28706, -28608,
+ -28510, -28410, -28309, -28208,
+ -28105, -28001, -27896, -27790,
+ -27683, -27575, -27466, -27355,
+ -27244, -27132, -27019, -26905,
+ -26789, -26673, -26556, -26437,
+ -26318, -26198, -26077, -25954,
+ -25831, -25707, -25582, -25456,
+ -25329, -25201, -25072, -24942,
+ -24811, -24679, -24546, -24413,
+ -24278, -24143, -24006, -23869,
+ -23731, -23592, -23452, -23311,
+ -23169, -23027, -22883, -22739,
+ -22594, -22448, -22301, -22153,
+ -22004, -21855, -21705, -21554,
+ -21402, -21249, -21096, -20942,
+ -20787, -20631, -20474, -20317,
+ -20159, -20000, -19840, -19680,
+ -19519, -19357, -19194, -19031,
+ -18867, -18702, -18537, -18371,
+ -18204, -18036, -17868, -17699,
+ -17530, -17360, -17189, -17017,
+ -16845, -16672, -16499, -16325,
+ -16150, -15975, -15799, -15623,
+ -15446, -15268, -15090, -14911,
+ -14732, -14552, -14372, -14191,
+ -14009, -13827, -13645, -13462,
+ -13278, -13094, -12909, -12724,
+ -12539, -12353, -12166, -11980,
+ -11792, -11604, -11416, -11227,
+ -11038, -10849, -10659, -10469,
+ -10278, -10087, -9895, -9703,
+ -9511, -9319, -9126, -8932,
+ -8739, -8545, -8351, -8156,
+ -7961, -7766, -7571, -7375,
+ -7179, -6982, -6786, -6589,
+ -6392, -6195, -5997, -5799,
+ -5601, -5403, -5205, -5006,
+ -4807, -4608, -4409, -4210,
+ -4011, -3811, -3611, -3411,
+ -3211, -3011, -2811, -2610,
+ -2410, -2209, -2009, -1808,
+ -1607, -1406, -1206, -1005,
+ -804, -603, -402, -201,
+ 0,
+};
+
+const uint32_t lut_oscillator_increments[] FLASHMEM = {
+ 594570139, 598878640, 603218361, 607589530,
+ 611992374, 616427123, 620894008, 625393262,
+ 629925120, 634489817, 639087591, 643718683,
+ 648383334, 653081787, 657814287, 662581081,
+ 667382416, 672218544, 677089717, 681996188,
+ 686938214, 691916051, 696929960, 701980202,
+ 707067040, 712190739, 717351567, 722549792,
+ 727785686, 733059521, 738371572, 743722117,
+ 749111434, 754539804, 760007511, 765514839,
+ 771062075, 776649508, 782277431, 787946136,
+ 793655918, 799407076, 805199909, 811034720,
+ 816911812, 822831491, 828794068, 834799851,
+ 840849155, 846942294, 853079587, 859261354,
+ 865487916, 871759598, 878076727, 884439633,
+ 890848647, 897304104, 903806339, 910355693,
+ 916952505, 923597121, 930289887, 937031151,
+ 943821265, 950660583, 957549461, 964488259,
+ 971477339, 978517064, 985607802, 992749922,
+ 999943798, 1007189803, 1014488315, 1021839716,
+ 1029244387, 1036702717, 1044215092, 1051781905,
+ 1059403550, 1067080425, 1074812930, 1082601467,
+ 1090446444, 1098348268, 1106307352, 1114324111,
+ 1122398963, 1130532329, 1138724632, 1146976300,
+ 1155287763, 1163659455, 1172091811, 1180585271,
+ 1189140279,
+};
+const int16_t wav_overdrive[] FLASHMEM = {
+ -32767, -32767, -32767, -32767,
+ -32767, -32767, -32767, -32767,
+ -32766, -32766, -32766, -32766,
+ -32766, -32766, -32766, -32766,
+ -32766, -32766, -32766, -32766,
+ -32766, -32765, -32765, -32765,
+ -32765, -32765, -32765, -32765,
+ -32765, -32765, -32765, -32765,
+ -32764, -32764, -32764, -32764,
+ -32764, -32764, -32764, -32764,
+ -32763, -32763, -32763, -32763,
+ -32763, -32763, -32763, -32763,
+ -32762, -32762, -32762, -32762,
+ -32762, -32762, -32761, -32761,
+ -32761, -32761, -32761, -32761,
+ -32760, -32760, -32760, -32760,
+ -32760, -32759, -32759, -32759,
+ -32759, -32759, -32758, -32758,
+ -32758, -32758, -32757, -32757,
+ -32757, -32757, -32756, -32756,
+ -32756, -32756, -32755, -32755,
+ -32755, -32754, -32754, -32754,
+ -32753, -32753, -32753, -32752,
+ -32752, -32752, -32751, -32751,
+ -32751, -32750, -32750, -32749,
+ -32749, -32749, -32748, -32748,
+ -32747, -32747, -32746, -32746,
+ -32745, -32745, -32744, -32744,
+ -32743, -32743, -32742, -32742,
+ -32741, -32741, -32740, -32740,
+ -32739, -32738, -32738, -32737,
+ -32736, -32736, -32735, -32734,
+ -32734, -32733, -32732, -32732,
+ -32731, -32730, -32729, -32728,
+ -32728, -32727, -32726, -32725,
+ -32724, -32723, -32722, -32721,
+ -32720, -32719, -32718, -32717,
+ -32716, -32715, -32714, -32713,
+ -32712, -32711, -32710, -32709,
+ -32707, -32706, -32705, -32704,
+ -32702, -32701, -32700, -32698,
+ -32697, -32695, -32694, -32692,
+ -32691, -32689, -32688, -32686,
+ -32684, -32683, -32681, -32679,
+ -32678, -32676, -32674, -32672,
+ -32670, -32668, -32666, -32664,
+ -32662, -32660, -32658, -32655,
+ -32653, -32651, -32649, -32646,
+ -32644, -32641, -32639, -32636,
+ -32633, -32631, -32628, -32625,
+ -32622, -32619, -32617, -32614,
+ -32610, -32607, -32604, -32601,
+ -32597, -32594, -32591, -32587,
+ -32584, -32580, -32576, -32572,
+ -32568, -32564, -32560, -32556,
+ -32552, -32548, -32543, -32539,
+ -32534, -32530, -32525, -32520,
+ -32515, -32510, -32505, -32500,
+ -32495, -32489, -32484, -32478,
+ -32473, -32467, -32461, -32455,
+ -32448, -32442, -32436, -32429,
+ -32422, -32416, -32409, -32402,
+ -32394, -32387, -32380, -32372,
+ -32364, -32356, -32348, -32340,
+ -32331, -32323, -32314, -32305,
+ -32296, -32287, -32277, -32268,
+ -32258, -32248, -32237, -32227,
+ -32216, -32206, -32195, -32183,
+ -32172, -32160, -32148, -32136,
+ -32124, -32111, -32098, -32085,
+ -32072, -32058, -32044, -32030,
+ -32016, -32001, -31986, -31971,
+ -31955, -31939, -31923, -31907,
+ -31890, -31873, -31855, -31838,
+ -31819, -31801, -31782, -31763,
+ -31743, -31723, -31703, -31682,
+ -31661, -31640, -31618, -31596,
+ -31573, -31550, -31526, -31502,
+ -31478, -31453, -31427, -31401,
+ -31375, -31348, -31320, -31293,
+ -31264, -31235, -31205, -31175,
+ -31145, -31113, -31082, -31049,
+ -31016, -30983, -30948, -30913,
+ -30878, -30842, -30805, -30767,
+ -30729, -30690, -30650, -30610,
+ -30569, -30527, -30484, -30440,
+ -30396, -30351, -30305, -30258,
+ -30211, -30162, -30113, -30063,
+ -30012, -29959, -29906, -29853,
+ -29798, -29742, -29685, -29627,
+ -29568, -29508, -29447, -29385,
+ -29321, -29257, -29191, -29125,
+ -29057, -28988, -28918, -28846,
+ -28774, -28700, -28625, -28548,
+ -28470, -28391, -28311, -28229,
+ -28146, -28061, -27975, -27887,
+ -27798, -27708, -27616, -27522,
+ -27427, -27331, -27232, -27132,
+ -27031, -26928, -26823, -26717,
+ -26609, -26499, -26387, -26274,
+ -26158, -26041, -25923, -25802,
+ -25679, -25555, -25428, -25300,
+ -25170, -25038, -24904, -24767,
+ -24629, -24489, -24346, -24202,
+ -24056, -23907, -23756, -23603,
+ -23448, -23291, -23131, -22970,
+ -22806, -22640, -22471, -22301,
+ -22128, -21952, -21775, -21595,
+ -21413, -21228, -21041, -20852,
+ -20660, -20466, -20270, -20071,
+ -19870, -19666, -19460, -19252,
+ -19041, -18828, -18613, -18395,
+ -18174, -17951, -17726, -17499,
+ -17269, -17036, -16802, -16565,
+ -16325, -16083, -15839, -15593,
+ -15344, -15093, -14840, -14584,
+ -14327, -14067, -13805, -13540,
+ -13274, -13005, -12735, -12462,
+ -12187, -11910, -11632, -11351,
+ -11068, -10784, -10498, -10210,
+ -9920, -9628, -9335, -9040,
+ -8744, -8446, -8146, -7845,
+ -7543, -7239, -6934, -6628,
+ -6320, -6012, -5702, -5391,
+ -5079, -4766, -4453, -4138,
+ -3823, -3507, -3190, -2873,
+ -2555, -2237, -1918, -1599,
+ -1279, -960, -640, -320,
+ 0, 320, 640, 960,
+ 1279, 1599, 1918, 2237,
+ 2555, 2873, 3190, 3507,
+ 3823, 4138, 4453, 4766,
+ 5079, 5391, 5702, 6012,
+ 6320, 6628, 6934, 7239,
+ 7543, 7845, 8146, 8446,
+ 8744, 9040, 9335, 9628,
+ 9920, 10210, 10498, 10784,
+ 11068, 11351, 11632, 11910,
+ 12187, 12462, 12735, 13005,
+ 13274, 13540, 13805, 14067,
+ 14327, 14584, 14840, 15093,
+ 15344, 15593, 15839, 16083,
+ 16325, 16565, 16802, 17036,
+ 17269, 17499, 17726, 17951,
+ 18174, 18395, 18613, 18828,
+ 19041, 19252, 19460, 19666,
+ 19870, 20071, 20270, 20466,
+ 20660, 20852, 21041, 21228,
+ 21413, 21595, 21775, 21952,
+ 22128, 22301, 22471, 22640,
+ 22806, 22970, 23131, 23291,
+ 23448, 23603, 23756, 23907,
+ 24056, 24202, 24346, 24489,
+ 24629, 24767, 24904, 25038,
+ 25170, 25300, 25428, 25555,
+ 25679, 25802, 25923, 26041,
+ 26158, 26274, 26387, 26499,
+ 26609, 26717, 26823, 26928,
+ 27031, 27132, 27232, 27331,
+ 27427, 27522, 27616, 27708,
+ 27798, 27887, 27975, 28061,
+ 28146, 28229, 28311, 28391,
+ 28470, 28548, 28625, 28700,
+ 28774, 28846, 28918, 28988,
+ 29057, 29125, 29191, 29257,
+ 29321, 29385, 29447, 29508,
+ 29568, 29627, 29685, 29742,
+ 29798, 29853, 29906, 29959,
+ 30012, 30063, 30113, 30162,
+ 30211, 30258, 30305, 30351,
+ 30396, 30440, 30484, 30527,
+ 30569, 30610, 30650, 30690,
+ 30729, 30767, 30805, 30842,
+ 30878, 30913, 30948, 30983,
+ 31016, 31049, 31082, 31113,
+ 31145, 31175, 31205, 31235,
+ 31264, 31293, 31320, 31348,
+ 31375, 31401, 31427, 31453,
+ 31478, 31502, 31526, 31550,
+ 31573, 31596, 31618, 31640,
+ 31661, 31682, 31703, 31723,
+ 31743, 31763, 31782, 31801,
+ 31819, 31838, 31855, 31873,
+ 31890, 31907, 31923, 31939,
+ 31955, 31971, 31986, 32001,
+ 32016, 32030, 32044, 32058,
+ 32072, 32085, 32098, 32111,
+ 32124, 32136, 32148, 32160,
+ 32172, 32183, 32195, 32206,
+ 32216, 32227, 32237, 32248,
+ 32258, 32268, 32277, 32287,
+ 32296, 32305, 32314, 32323,
+ 32331, 32340, 32348, 32356,
+ 32364, 32372, 32380, 32387,
+ 32394, 32402, 32409, 32416,
+ 32422, 32429, 32436, 32442,
+ 32448, 32455, 32461, 32467,
+ 32473, 32478, 32484, 32489,
+ 32495, 32500, 32505, 32510,
+ 32515, 32520, 32525, 32530,
+ 32534, 32539, 32543, 32548,
+ 32552, 32556, 32560, 32564,
+ 32568, 32572, 32576, 32580,
+ 32584, 32587, 32591, 32594,
+ 32597, 32601, 32604, 32607,
+ 32610, 32614, 32617, 32619,
+ 32622, 32625, 32628, 32631,
+ 32633, 32636, 32639, 32641,
+ 32644, 32646, 32649, 32651,
+ 32653, 32655, 32658, 32660,
+ 32662, 32664, 32666, 32668,
+ 32670, 32672, 32674, 32676,
+ 32678, 32679, 32681, 32683,
+ 32684, 32686, 32688, 32689,
+ 32691, 32692, 32694, 32695,
+ 32697, 32698, 32700, 32701,
+ 32702, 32704, 32705, 32706,
+ 32707, 32709, 32710, 32711,
+ 32712, 32713, 32714, 32715,
+ 32716, 32717, 32718, 32719,
+ 32720, 32721, 32722, 32723,
+ 32724, 32725, 32726, 32727,
+ 32728, 32728, 32729, 32730,
+ 32731, 32732, 32732, 32733,
+ 32734, 32734, 32735, 32736,
+ 32736, 32737, 32738, 32738,
+ 32739, 32740, 32740, 32741,
+ 32741, 32742, 32742, 32743,
+ 32743, 32744, 32744, 32745,
+ 32745, 32746, 32746, 32747,
+ 32747, 32748, 32748, 32749,
+ 32749, 32749, 32750, 32750,
+ 32751, 32751, 32751, 32752,
+ 32752, 32752, 32753, 32753,
+ 32753, 32754, 32754, 32754,
+ 32755, 32755, 32755, 32756,
+ 32756, 32756, 32756, 32757,
+ 32757, 32757, 32757, 32758,
+ 32758, 32758, 32758, 32759,
+ 32759, 32759, 32759, 32759,
+ 32760, 32760, 32760, 32760,
+ 32760, 32761, 32761, 32761,
+ 32761, 32761, 32761, 32762,
+ 32762, 32762, 32762, 32762,
+ 32762, 32763, 32763, 32763,
+ 32763, 32763, 32763, 32763,
+ 32763, 32764, 32764, 32764,
+ 32764, 32764, 32764, 32764,
+ 32764, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32765, 32765, 32765, 32765,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32766, 32766, 32766,
+ 32766, 32767, 32767, 32767,
+ 32767, 32767, 32767, 32767,
+ 32767,
+};
+}
\ No newline at end of file
diff --git a/app/DRUMS/resources/peaks_lut_svf.hpp b/app/DRUMS/resources/peaks_lut_svf.hpp
new file mode 100644
index 0000000..d652143
--- /dev/null
+++ b/app/DRUMS/resources/peaks_lut_svf.hpp
@@ -0,0 +1,203 @@
+namespace peaks {
+ const uint16_t lut_svf_cutoff[] FLASHMEM = {
+ 35, 37, 39, 41,
+ 44, 46, 49, 52,
+ 55, 58, 62, 66,
+ 70, 74, 78, 83,
+ 88, 93, 99, 105,
+ 111, 117, 124, 132,
+ 140, 148, 157, 166,
+ 176, 187, 198, 210,
+ 222, 235, 249, 264,
+ 280, 297, 314, 333,
+ 353, 374, 396, 420,
+ 445, 471, 499, 529,
+ 561, 594, 629, 667,
+ 706, 748, 793, 840,
+ 890, 943, 999, 1059,
+ 1122, 1188, 1259, 1334,
+ 1413, 1497, 1586, 1681,
+ 1781, 1886, 1999, 2117,
+ 2243, 2377, 2518, 2668,
+ 2826, 2994, 3172, 3361,
+ 3560, 3772, 3996, 4233,
+ 4485, 4751, 5033, 5332,
+ 5648, 5983, 6337, 6713,
+ 7111, 7532, 7978, 8449,
+ 8949, 9477, 10037, 10628,
+ 11254, 11916, 12616, 13356,
+ 14138, 14964, 15837, 16758,
+ 17730, 18756, 19837, 20975,
+ 22174, 23435, 24761, 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[] FLASHMEM = {
+ 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_svf_scale[] FLASHMEM = {
+ 32767, 28381, 27473, 26846,
+ 26352, 25936, 25573, 25248,
+ 24953, 24682, 24429, 24193,
+ 23970, 23759, 23557, 23365,
+ 23181, 23003, 22832, 22667,
+ 22507, 22352, 22201, 22055,
+ 21912, 21772, 21636, 21503,
+ 21373, 21245, 21120, 20998,
+ 20877, 20759, 20643, 20528,
+ 20416, 20305, 20196, 20088,
+ 19982, 19877, 19774, 19672,
+ 19571, 19471, 19373, 19275,
+ 19179, 19083, 18989, 18896,
+ 18803, 18712, 18621, 18531,
+ 18442, 18353, 18266, 18179,
+ 18092, 18007, 17922, 17837,
+ 17754, 17671, 17588, 17506,
+ 17424, 17343, 17263, 17183,
+ 17103, 17024, 16946, 16868,
+ 16790, 16713, 16636, 16559,
+ 16483, 16407, 16331, 16256,
+ 16181, 16107, 16033, 15959,
+ 15885, 15812, 15739, 15666,
+ 15594, 15522, 15450, 15378,
+ 15306, 15235, 15164, 15093,
+ 15022, 14952, 14882, 14812,
+ 14742, 14672, 14602, 14533,
+ 14464, 14395, 14326, 14257,
+ 14188, 14120, 14051, 13983,
+ 13915, 13847, 13779, 13711,
+ 13643, 13575, 13508, 13440,
+ 13372, 13305, 13238, 13170,
+ 13103, 13036, 12969, 12902,
+ 12835, 12768, 12701, 12634,
+ 12567, 12500, 12433, 12366,
+ 12299, 12232, 12165, 12098,
+ 12031, 11964, 11897, 11830,
+ 11762, 11695, 11628, 11561,
+ 11493, 11426, 11359, 11291,
+ 11223, 11156, 11088, 11020,
+ 10952, 10884, 10816, 10747,
+ 10679, 10610, 10542, 10473,
+ 10404, 10335, 10266, 10196,
+ 10127, 10057, 9987, 9917,
+ 9846, 9776, 9705, 9634,
+ 9563, 9491, 9420, 9348,
+ 9276, 9203, 9130, 9057,
+ 8984, 8910, 8836, 8762,
+ 8687, 8613, 8537, 8461,
+ 8385, 8309, 8232, 8155,
+ 8077, 7998, 7920, 7841,
+ 7761, 7680, 7600, 7518,
+ 7436, 7354, 7270, 7187,
+ 7102, 7017, 6931, 6844,
+ 6756, 6668, 6578, 6488,
+ 6397, 6305, 6211, 6117,
+ 6021, 5925, 5827, 5727,
+ 5626, 5524, 5420, 5315,
+ 5207, 5098, 4987, 4873,
+ 4758, 4639, 4518, 4394,
+ 4267, 4137, 4002, 3864,
+ 3720, 3571, 3417, 3255,
+ 3086, 2907, 2717, 2514,
+ 2293, 2049, 1774, 1447,
+ 1022,
+};
+}
\ No newline at end of file
diff --git a/app/FX/Delay.bin b/app/FX/Delay.bin
index beb6f05..e75b100 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 91e9048..b1acd91 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 520979e..d6627de 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 9b8a5ac..d88ba96 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 89904d8..d25e2c1 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 28b801b..597bbb5 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 4e77236..ab477dc 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 a3e20e6..753c111 100644
Binary files a/app/GND/FFT.bin and b/app/GND/FFT.bin differ
diff --git a/app/GND/FFT.cpp b/app/GND/FFT.cpp
index 6c72e41..f813765 100644
--- a/app/GND/FFT.cpp
+++ b/app/GND/FFT.cpp
@@ -133,7 +133,7 @@ float fft_read(int s, int e)
float level2[64];
float level[64];
-static void draw_spectrum(int yy, int hh)
+void draw_spectrum(int yy, int hh)
{
float logN2 = logf(N / 2);
@@ -176,7 +176,7 @@ static void draw_spectrum(int yy, int hh)
// };
for (uint32_t i = 0; i < (N / 2); i++)
- magnitudes[i] = 0;
+ magnitudes[i] = 0;
count = 0;
}
diff --git a/app/GND/Scope.bin b/app/GND/Scope.bin
index 00365fe..10c175b 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
new file mode 100644
index 0000000..1fed948
Binary files /dev/null and b/app/M-OSC/Waveforms.bin differ
diff --git a/app/M-OSC/Waveforms.cpp b/app/M-OSC/Waveforms.cpp
new file mode 100644
index 0000000..ba3fbb0
--- /dev/null
+++ b/app/M-OSC/Waveforms.cpp
@@ -0,0 +1,189 @@
+// 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 "stmlib/stmlib.h"
+#include "stmlib/dsp/dsp.h"
+
+#define private public
+#include "braids/macro_oscillator.h"
+#include "braids/envelope.h"
+#include "braids/settings.h"
+
+#include "braids/vco_jitter_source.h"
+
+#include "braids/analog_oscillator.cc"
+#define kHighestNote kHighestNote2
+#define kPitchTableStart kPitchTableStart2
+#define kOctave kOctave2
+#include "braids/digital_oscillator.cc"
+#include "braids/settings.cc"
+#include "braids/macro_oscillator.cc"
+#include "braids/resources.cc"
+#include "stmlib/utils/random.cc"
+
+using namespace braids;
+
+MacroOscillator osc1;
+MacroOscillator osc2;
+Envelope envelope;
+VcoJitterSource jitter_source;
+
+uint8_t sync_samples[FRAME_BUFFER_SIZE];
+
+float _pitch = 0;
+int32_t _shape = 0;
+int32_t _timbre = UINT16_MAX / 2;
+int32_t _color = UINT16_MAX / 2;
+int32_t _attack = 0;
+int32_t _decay = UINT16_MAX / 2;
+
+float buffer[FRAME_BUFFER_SIZE];
+float bufferR[FRAME_BUFFER_SIZE];
+
+void engine::setup()
+{
+ settings.Init();
+ osc1.Init();
+ osc2.Init();
+ jitter_source.Init();
+ envelope.Init();
+
+ std::fill(&sync_samples[0], &sync_samples[FRAME_BUFFER_SIZE], 0);
+
+ // settings.SetValue(SETTING_AD_VCA, true);
+ settings.SetValue(SETTING_SAMPLE_RATE, 5);
+ settings.SetValue(SETTING_PITCH_OCTAVE, 4);
+ settings.SetValue(SETTING_PITCH_RANGE, PITCH_RANGE_EXTERNAL);
+
+ engine::addParam(V_OCT, &_pitch);
+ engine::addParam("Shape", &_shape, braids::MACRO_OSC_SHAPE_CSAW, braids::MACRO_OSC_SHAPE_LAST - 1, (const char **)braids::settings.metadata(braids::Setting::SETTING_OSCILLATOR_SHAPE).strings);
+ engine::addParam("Timbre", &_timbre, 0, UINT16_MAX);
+ engine::addParam("Color", &_color, 0, UINT16_MAX);
+ engine::addParam("Decay", &_decay, 0, UINT16_MAX);
+ engine::addParam("Attack", &_attack, 0, UINT16_MAX);
+}
+
+void engine::process()
+{
+ envelope.Update(_attack / 512, _decay / 512);
+
+ if (engine::trig())
+ {
+ osc1.Strike();
+ osc2.Strike();
+ envelope.Trigger(braids::ENV_SEGMENT_ATTACK);
+ }
+
+ if (engine::gate())
+ {
+ // Not working witch Attack > 0
+ // envelope.Trigger(braids::ENV_SEGMENT_DECAY);
+ }
+
+ uint32_t ad_value = envelope.Render();
+
+ float pitchV = engine::cv();
+ int32_t pitch = (pitchV * 12.f + DEFAULT_NOTE + 12) * 128;
+
+ // if (!settings.meta_modulation())
+ // {
+ // pitch += settings.adc_to_fm(adc_3);
+ // }
+
+ pitch += jitter_source.Render(settings.vco_drift());
+ pitch += ad_value * settings.GetValue(SETTING_AD_FM) >> 7;
+
+ CONSTRAIN(pitch, 0, 16383);
+
+ if (settings.vco_flatten())
+ pitch = stmlib::Interpolate88(braids::lut_vco_detune, pitch << 2);
+
+ uint32_t gain = _decay < UINT16_MAX ? ad_value : UINT16_MAX;
+
+ if (!__io->tr)
+ gain = _decay; // No Trigger patched - use Decay as VCA...
+
+ if ((engine::t() % 12) != 0)
+ osc1.set_shape((braids::MacroOscillatorShape)_shape);
+ else if ((engine::t() % 12) != 6)
+ osc2.set_shape((braids::MacroOscillatorShape)_shape);
+
+ osc1.set_parameters(_timbre >> 1, _color >> 1);
+ osc1.set_pitch(pitch + settings.pitch_transposition());
+
+ auto audio_samples = engine::outputBuffer_i16<0>();
+ osc1.Render(sync_samples, audio_samples, FRAME_BUFFER_SIZE);
+
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
+ audio_samples[i] = (gain * audio_samples[i]) / UINT16_MAX;
+
+ if (engine::is_stereo() && __io->stereo > 0) // Stereo
+ {
+ const float f = (float)__io->stereo / 255.f;
+ uint8_t stereo = f * f * f * 255;
+
+ int32_t timbre = _timbre + stereo;
+ if (timbre > UINT16_MAX)
+ timbre = _timbre - stereo;
+
+ int32_t color = _color + stereo;
+ if (color > UINT16_MAX)
+ color = _color - stereo;
+
+ osc2.set_parameters((timbre >> 1), (color >> 1));
+ osc2.set_pitch(pitch + settings.pitch_transposition() + stereo);
+
+ auto audio_samples = engine::outputBuffer_i16<1>();
+ osc2.Render(sync_samples, audio_samples, FRAME_BUFFER_SIZE);
+
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
+ audio_samples[i] = (gain * audio_samples[i]) / UINT16_MAX;
+ }
+ else
+ {
+ memcpy(engine::outputBuffer_i16<1>(), engine::outputBuffer_i16<0>(), FRAME_BUFFER_SIZE * sizeof(int16_t));
+ }
+}
+
+void engine::draw()
+{
+ if (!__io->tr)
+ {
+ setParamName(&_decay, "Level");
+ setParamName(&_attack, nullptr);
+ }
+ else if (_decay < UINT16_MAX)
+ {
+ setParamName(&_decay, "Decay");
+ setParamName(&_attack, "Attack");
+ }
+ else
+ {
+ setParamName(&_decay, "VCA-off");
+ setParamName(&_attack, nullptr);
+ }
+}
\ No newline at end of file
diff --git a/app/MIDI/Clock.bin b/app/MIDI/Clock.bin
index 2b66bb1..c33cef8 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 5e5d70a..058073b 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 e179093..32ab387 100644
Binary files a/app/MIDI/VAx6.bin and b/app/MIDI/VAx6.bin differ
diff --git a/app/MIDI/VAx6.cpp b/app/MIDI/VAx6.cpp
index 55e298b..130bb20 100644
--- a/app/MIDI/VAx6.cpp
+++ b/app/MIDI/VAx6.cpp
@@ -24,7 +24,6 @@
//
#include "../squares-and-circles-api.h"
-#define FLASHMEM __attribute__((section(".text")))
// #include "../lib/plaits/dsp/engine/virtual_analog_engine.h"
// no virtual functions hack
diff --git a/app/NOISE/808_squares.bin b/app/NOISE/808_squares.bin
index 2f53522..398ce46 100644
Binary files a/app/NOISE/808_squares.bin and b/app/NOISE/808_squares.bin differ
diff --git a/app/NOISE/808_squares.cpp b/app/NOISE/808_squares.cpp
index 59dc012..77ce2ae 100644
--- a/app/NOISE/808_squares.cpp
+++ b/app/NOISE/808_squares.cpp
@@ -101,7 +101,7 @@ void engine::setup()
engine::addParam("F0", &f0, 254.3f, 627.2f);
engine::addParam("F1", &f1, 359.4f, 1149.9f);
update_oscillators();
-};
+}
void engine::process()
{
diff --git a/app/NOISE/NES.bin b/app/NOISE/NES.bin
index 5776856..bfd9961 100644
Binary files a/app/NOISE/NES.bin and b/app/NOISE/NES.bin differ
diff --git a/app/NOISE/NES.cpp b/app/NOISE/NES.cpp
index 1e456d4..416b2c6 100644
--- a/app/NOISE/NES.cpp
+++ b/app/NOISE/NES.cpp
@@ -42,7 +42,7 @@ void engine::setup()
_nes_noise.init(1);
_dc_blocker.Init(0.999f);
-};
+}
void engine::process()
{
diff --git a/app/NOISE/WhitePink.bin b/app/NOISE/WhitePink.bin
index 6da4663..32bad21 100644
Binary files a/app/NOISE/WhitePink.bin and b/app/NOISE/WhitePink.bin differ
diff --git a/app/NOISE/WhitePink.cpp b/app/NOISE/WhitePink.cpp
index 2b01077..6dcd4f3 100644
--- a/app/NOISE/WhitePink.cpp
+++ b/app/NOISE/WhitePink.cpp
@@ -38,8 +38,7 @@ void engine::setup()
{
engine::addParam("Level", &gain);
engine::addParam("@Mode", &mode, 0, LEN_OF(modes) - 1, modes);
-};
-
+}
void engine::process()
{
auto buffer = engine::outputBuffer<0>();
diff --git a/app/SEQ/EuclidArp.bin b/app/SEQ/EuclidArp.bin
new file mode 100644
index 0000000..2f142c8
Binary files /dev/null and b/app/SEQ/EuclidArp.bin differ
diff --git a/app/SEQ/EuclidArp.cpp b/app/SEQ/EuclidArp.cpp
new file mode 100644
index 0000000..b4a4ca0
--- /dev/null
+++ b/app/SEQ/EuclidArp.cpp
@@ -0,0 +1,385 @@
+
+// Copyright (C)2021 - Eduard 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.
+//
+
+#include "../squares-and-circles-api.h"
+#include "../lib/misc/euclidean.h"
+#include
+#include
+
+#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/stmlib/utils/dsp.h"
+#include "../DRUMS/resources/peaks_lut_env.hpp"
+
+// This app is copiled with soft-fpu - for running on teensy3.2 & teensy 4.x
+
+/*
+https://www.nullhardware.com/blog/fixed-point-sine-and-cosine-for-embedded-systems/
+
+Implements the 5-order polynomial approximation to sin(x).
+@param i angle (with 2^15 units/circle)
+@return 16 bit fixed point Sine value (4.12) (ie: +4096 = +1 & -4096 = -1)
+
+The result is accurate to within +- 1 count. ie: +/-2.44e-4.
+*/
+
+int16_t fpsin(int16_t i)
+{
+ /* Convert (signed) input to a value between 0 and 8192. (8192 is pi/2, which is the region of the curve fit). */
+ /* ------------------------------------------------------------------- */
+ i <<= 1;
+ uint8_t c = i < 0; // set carry for output pos/neg
+
+ if (i == (i | 0x4000)) // flip input value to corresponding value in range [0..8192)
+ i = (1 << 15) - i;
+ i = (i & 0x7FFF) >> 1;
+ /* ------------------------------------------------------------------- */
+
+ /* The following section implements the formula:
+ = y * 2^-n * ( A1 - 2^(q-p)* y * 2^-n * y * 2^-n * [B1 - 2^-r * y * 2^-n * C1 * y]) * 2^(a-q)
+ Where the constants are defined as follows:
+ */
+ uint32_t A1 = 3370945099UL, B1 = 2746362156UL, C1 = 292421UL;
+ uint32_t n = 13, p = 32, q = 31, r = 3, a = 12;
+
+ uint32_t y = (C1 * ((uint32_t)i)) >> n;
+ y = B1 - (((uint32_t)i * y) >> r);
+ y = (uint32_t)i * (y >> n);
+ y = (uint32_t)i * (y >> n);
+ y = A1 - (y >> (p - q));
+ y = (uint32_t)i * (y >> n);
+ y = (y + (1UL << (q - a - 1))) >> (q - a); // Rounding
+
+ return c ? -y : y;
+}
+
+// Cos(x) = sin(x + pi/2)
+inline int16_t fpcos(int16_t i) { return fpsin((int16_t)(((uint16_t)(i)) + 8192U)); }
+
+// https://xbm.jazzychad.net/
+const uint8_t xmb_note_6x8[8] = {0xc8, 0xd8, 0xe8, 0xd8, 0xe8, 0xce, 0xcf, 0xc6};
+const uint8_t xmb_rest_6x8[8] = {0xd6, 0xde, 0xd0, 0xd6, 0xde, 0xd0, 0xd0, 0xd0};
+
+const uint8_t xmb_arrow_up_5x6[6] = {0xe4, 0xee, 0xff, 0xe4, 0xe4, 0xe4};
+const uint8_t xmb_arrow_dn_5x6[6] = {0xe4, 0xe4, 0xe4, 0xf5, 0xee, 0xe4};
+const uint8_t xmb_circle_7x7[7] = {0x9c, 0xa2, 0xc1, 0xc1, 0xc1, 0xa2, 0x9c};
+const uint8_t xmb_filled_circle_7x7[7] = {0x9c, 0xa2, 0xdd, 0xdd, 0xdd, 0xa2, 0x9c};
+const uint8_t xbm_play_11x11[] = {0x03, 0xf8, 0x0d, 0xf8, 0x31, 0xf8, 0xc1, 0xf8, 0x01, 0xfb, 0x01, 0xfc, 0x01, 0xfb, 0xc1, 0xf8, 0x31, 0xf8, 0x0d, 0xf8, 0x03, 0xf8};
+const uint8_t xbm_stop_7x11[] = {0x80, 0xf7, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xf7, 0x80};
+
+int32_t len = 16;
+int32_t pulses = 4;
+int32_t rotate = 0;
+int32_t swing = 128;
+
+int32_t seq_pos = UINT8_MAX;
+bool playing = true;
+bool pre_start = false;
+
+void draw_eclid_cyrcle(int x, int y, uint8_t pattern[64], int _len, int rot)
+{
+ auto pattern2 = pattern;
+
+ int xx = x;
+ int yy = y;
+
+ if ((fpsin((INT16_MAX / (_len))) / 194) > 6)
+ {
+ gfx::drawCircle(xx + 3, 31 + 3, 21);
+
+ for (int i = 0; i < _len; i++)
+ {
+ int a = (INT16_MAX / (_len)) * i;
+
+ if (MOD(i, 2) == 1)
+ a += (-128 + swing) * (INT16_MAX / _len) / 6;
+
+ int x = fpsin(a) / 194;
+ int y = -fpcos(a) / 194;
+ x += xx;
+ y += yy;
+
+ gfx::clearCircle(x + 3, y + 3, 3);
+ }
+ }
+
+ for (int i = 0; i < _len; i++)
+ {
+ int a = (INT16_MAX / (_len)) * i;
+
+ if (MOD(i, 2) == 1)
+ a += (-128 + swing) * (INT16_MAX / _len) / 6;
+
+ int dx = fpsin(a);
+ int dy = -fpcos(a);
+
+ int x = xx + dx / 194;
+ int y = yy + dy / 194;
+
+ if (pattern[i] || pattern2[i])
+ gfx::fillRect(x + 2, y + 2, 3, 3); // gfx::drawXbm(x, y, 7, 7, xmb_filled_circle_7x7);
+
+ if (i == rot)
+ gfx::drawRect(x, y, 7, 7);
+ else
+ gfx::drawCircle(x + 3, y + 3, 3); //
+
+ bool cursor = i == MOD(seq_pos, _len);
+
+ if (cursor && !pre_start)
+ gfx::drawRect(x + 1, y + 1, 5, 5);
+ }
+
+ if (playing && pre_start && MOD(millis(), 300) > 150)
+ {
+ }
+ else
+ {
+ int x = xx - 2;
+ int y = 40 - 7;
+ if (pattern[seq_pos % _len] && (engine::clock() % 6) < 3)
+ {
+ if (x < 64)
+ gfx::fillRect(x - 3, y - 7, 17, 17);
+ else
+ gfx::fillCircle(x + 5, y + 1, 8);
+ }
+ else
+ {
+ if (x < 64)
+ gfx::drawRect(x - 2, y - 7, 16, 16);
+ else
+ gfx::drawCircle(x + 5, y + 1, 8);
+ }
+ }
+}
+
+float arp_root = 0;
+int32_t mode = 0;
+
+int32_t chord = 0;
+plaits::Arpeggiator arpeggiator_;
+plaits::ChordBank chords_;
+int32_t chords_mem[(plaits::kChordNumChords * plaits::kChordNumNotes) + plaits::kChordNumChords + plaits::kChordNumNotes];
+
+int32_t octaves = 1;
+int32_t _slide = 0;
+
+const char *smodes[] = {
+ "UP",
+ "DOWN",
+ "CYCLE",
+ "RAND",
+};
+
+const char *soctaves[] = {
+ "1-OCT",
+ "2-OCT",
+ "3-OCT",
+ "4-OCT",
+};
+
+void engine::setup()
+{
+ arpeggiator_.Init();
+ stmlib::BufferAllocator allocator;
+ allocator.Init(chords_mem, sizeof(chords_mem));
+ chords_.Init(&allocator);
+ chords_.chord_index_quantizer_.hysteresis_ = 0; // input => output
+ chords_.Reset();
+
+ engine::addParam("#LEN", &len, 1, 20);
+ engine::addParam(V_OCT, &arp_root); // arp_root ist automatically added to engine::cv()
+ engine::addParam("#HIT", &pulses, 0, 16);
+ engine::addParam("Mode", &mode, 0, LEN_OF(smodes) - 1, smodes);
+ engine::addParam("#ROT", &rotate, 0, 32);
+ engine::addParam("CHRD", &chord, 0, plaits::kChordNumChords - 1, (const char **)plaits::chord_names);
+ engine::addParam("RNGE", &octaves, 0, LEN_OF(soctaves) - 1, soctaves);
+ engine::addParam("SLIDE", &_slide, 0, 1);
+ engine::setMode(ENGINE_MODE_CV_OUT);
+}
+
+uint8_t pattern[64] = {};
+
+int32_t gate_until_t = 0;
+static int32_t key = 1;
+
+int32_t _len = len; // for mod vizualization
+int32_t _swing = swing; // for mod vizualization
+
+char debug[128] = {};
+
+static int32_t _last_len = -1;
+static auto _last_pulses = pulses;
+static auto _last_rotate = rotate;
+static auto _last_mode = mode;
+static uint32_t _slide_phase = UINT32_MAX;
+static uint32_t _slide_phase_inc = 0;
+
+uint32_t _t = 0;
+float _last_cv = 0;
+float _cv = 0;
+float _cv_out = 0;
+
+void update_seq_pattern()
+{
+ CONSTRAIN(pulses, pulses, len);
+ rotate %= len;
+ _swing = swing;
+
+ if (_last_len != len || _last_pulses != pulses || _last_rotate != rotate || _last_mode != mode)
+ {
+ if (_last_len != len && _last_len == _last_pulses)
+ pulses = len;
+
+ _last_len = len;
+ _last_pulses = pulses;
+ _last_rotate = rotate;
+ _last_mode = mode;
+ pre_start = false;
+ _len = len;
+
+ make_pattern(pattern, len, pulses, rotate);
+
+ for (int i = len; i < 64; i++)
+ pattern[i] = pattern[i - len];
+ }
+
+ if (engine::stepChanged())
+ {
+ seq_pos = engine::step() % len;
+ if (seq_pos == 0)
+ arpeggiator_.Reset();
+
+ bool trig = pattern[seq_pos];
+
+ if (trig)
+ {
+ uint32_t n = 1 + (engine::t() - _t) / 2;
+
+ if (_slide > 0)
+ {
+ int m = n * 2;
+ for (int i = seq_pos; !pattern[(i + 1) % _len]; i++)
+ m += n * 2;
+
+ _slide_phase = 0;
+ _slide_phase_inc = UINT32_MAX / n;
+ gate_until_t = 2 + m;
+ }
+ else
+ gate_until_t = 2 + n; // 10ms trigger
+
+ arpeggiator_.Clock(chords_.num_notes());
+ const float ratio = chords_.sorted_ratio(arpeggiator_.note());
+ _last_cv = _cv;
+ _cv = engine::cv() + arpeggiator_.octave() + log2f(ratio);
+
+ key++;
+ }
+
+ _t = engine::t();
+ }
+}
+
+void engine::process()
+{
+ if (!playing)
+ {
+ gate_until_t = 0;
+ seq_pos = len - 1;
+ pre_start = true;
+ return;
+ }
+
+ update_seq_pattern();
+
+ arpeggiator_.set_mode((plaits::ArpeggiatorMode)(mode % plaits::ARPEGGIATOR_MODE_LAST));
+ arpeggiator_.set_range(1 + octaves);
+
+ chords_.set_chord((float)chord / (plaits::kChordNumChords - 1));
+ chords_.Sort();
+
+ int32_t trig = 0;
+
+ if (gate_until_t > 0)
+ {
+ --gate_until_t;
+ trig = 5 * PITCH_PER_OCTAVE; // 5V
+ }
+
+ if (_slide_phase < (UINT32_MAX - _slide_phase_inc))
+ {
+ float e = stmlib::Interpolate824(peaks::lut_env_expo, _slide_phase);
+ _slide_phase += _slide_phase_inc;
+ _cv_out = _last_cv + ((_cv - _last_cv) * (e / UINT16_MAX));
+ }
+ else
+ {
+ _cv_out = _cv;
+ }
+
+ std::fill_n(engine::outputBuffer<1>(), FRAME_BUFFER_SIZE, _cv_out);
+
+ std::fill_n(engine::outputBuffer_i16<0>(), FRAME_BUFFER_SIZE, trig);
+}
+
+void engine::draw()
+{
+ // for (int i = 0; i < chords_.num_notes(); i++)
+ // {
+ // const float ratio = chords_.sorted_ratio(i);
+ // float notef = engine::cv() + arpeggiator_.octave() + log2f(ratio);
+
+ // float delta = 10.f;
+ // int note = 0;
+
+ // int n = 0;
+ // for (float i = -4.f; i < 4.f; i += 1.f / 12)
+ // {
+ // float d = std::fabs(i - notef);
+ // if (d < delta)
+ // {
+ // delta = d;
+ // note = n;
+ // }
+
+ // ++n;
+ // }
+ // bool now = fabsf(_cv - notef) < 0.001f;
+
+ // int key = note % 12;
+ // if (key == 1 || key == 3 || key == 6 || key == 8 || key == 10)
+ // gfx::invertRect((key < 5 ? 87 : 89) + (key * 2), (now ? 20 : 21) - 5, 1, now ? 3 : 1);
+ // else
+ // gfx::clearRect((key < 5 ? 87 : 89) + (key * 2), now ? 20 : 21, 1, now ? 3 : 1);
+ // }
+ draw_eclid_cyrcle(36, 31, pattern, _last_len, _last_rotate);
+}
\ No newline at end of file
diff --git a/app/SEQ/EuclidRythm.bin b/app/SEQ/EuclidRythm.bin
new file mode 100644
index 0000000..6be4a4d
Binary files /dev/null and b/app/SEQ/EuclidRythm.bin differ
diff --git a/app/SEQ/EuclidRythm.cpp b/app/SEQ/EuclidRythm.cpp
new file mode 100644
index 0000000..e4c901f
--- /dev/null
+++ b/app/SEQ/EuclidRythm.cpp
@@ -0,0 +1,302 @@
+
+// Copyright (C)2021 - Eduard 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.
+//
+
+#include "../squares-and-circles-api.h"
+#include "../lib/misc/euclidean.h"
+#include
+#include
+
+// build_flags: -fno-inline -mfloat-abi=soft -mfpu=fpv5-d16
+
+// This app is copiled with soft-fpu - for running on teensy3.2 & teensy 4.x
+
+/*
+https://www.nullhardware.com/blog/fixed-point-sine-and-cosine-for-embedded-systems/
+
+Implements the 5-order polynomial approximation to sin(x).
+@param i angle (with 2^15 units/circle)
+@return 16 bit fixed point Sine value (4.12) (ie: +4096 = +1 & -4096 = -1)
+
+The result is accurate to within +- 1 count. ie: +/-2.44e-4.
+*/
+
+int16_t fpsin(int16_t i)
+{
+ /* Convert (signed) input to a value between 0 and 8192. (8192 is pi/2, which is the region of the curve fit). */
+ /* ------------------------------------------------------------------- */
+ i <<= 1;
+ uint8_t c = i < 0; // set carry for output pos/neg
+
+ if (i == (i | 0x4000)) // flip input value to corresponding value in range [0..8192)
+ i = (1 << 15) - i;
+ i = (i & 0x7FFF) >> 1;
+ /* ------------------------------------------------------------------- */
+
+ /* The following section implements the formula:
+ = y * 2^-n * ( A1 - 2^(q-p)* y * 2^-n * y * 2^-n * [B1 - 2^-r * y * 2^-n * C1 * y]) * 2^(a-q)
+ Where the constants are defined as follows:
+ */
+ uint32_t A1 = 3370945099UL, B1 = 2746362156UL, C1 = 292421UL;
+ uint32_t n = 13, p = 32, q = 31, r = 3, a = 12;
+
+ uint32_t y = (C1 * ((uint32_t)i)) >> n;
+ y = B1 - (((uint32_t)i * y) >> r);
+ y = (uint32_t)i * (y >> n);
+ y = (uint32_t)i * (y >> n);
+ y = A1 - (y >> (p - q));
+ y = (uint32_t)i * (y >> n);
+ y = (y + (1UL << (q - a - 1))) >> (q - a); // Rounding
+
+ return c ? -y : y;
+}
+
+// Cos(x) = sin(x + pi/2)
+inline int16_t fpcos(int16_t i) { return fpsin((int16_t)(((uint16_t)(i)) + 8192U)); }
+
+// https://xbm.jazzychad.net/
+const uint8_t xmb_note_6x8[8] = {0xc8, 0xd8, 0xe8, 0xd8, 0xe8, 0xce, 0xcf, 0xc6};
+const uint8_t xmb_rest_6x8[8] = {0xd6, 0xde, 0xd0, 0xd6, 0xde, 0xd0, 0xd0, 0xd0};
+
+const uint8_t xmb_arrow_up_5x6[6] = {0xe4, 0xee, 0xff, 0xe4, 0xe4, 0xe4};
+const uint8_t xmb_arrow_dn_5x6[6] = {0xe4, 0xe4, 0xe4, 0xf5, 0xee, 0xe4};
+const uint8_t xmb_circle_7x7[7] = {0x9c, 0xa2, 0xc1, 0xc1, 0xc1, 0xa2, 0x9c};
+const uint8_t xmb_filled_circle_7x7[7] = {0x9c, 0xa2, 0xdd, 0xdd, 0xdd, 0xa2, 0x9c};
+const uint8_t xbm_play_11x11[] = {0x03, 0xf8, 0x0d, 0xf8, 0x31, 0xf8, 0xc1, 0xf8, 0x01, 0xfb, 0x01, 0xfc, 0x01, 0xfb, 0xc1, 0xf8, 0x31, 0xf8, 0x0d, 0xf8, 0x03, 0xf8};
+const uint8_t xbm_stop_7x11[] = {0x80, 0xf7, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xf7, 0x80};
+
+bool playing = true;
+bool pre_start = false;
+uint8_t seq_pos = UINT8_MAX;
+int32_t swing = 128;
+
+void draw_eclid_cyrcle(int x, int y, uint8_t pattern[64], int _len, int rot)
+{
+ auto pattern2 = pattern;
+
+ int xx = x;
+ int yy = y;
+
+ if ((fpsin((INT16_MAX / (_len))) / 194) > 6)
+ {
+ gfx::drawCircle(xx + 3, 31 + 3, 21);
+
+ for (int i = 0; i < _len; i++)
+ {
+ int a = (INT16_MAX / (_len)) * i;
+
+ if (MOD(i, 2) == 1)
+ a += (-128 + swing) * (INT16_MAX / _len) / 6;
+
+ int x = fpsin(a) / 194;
+ int y = -fpcos(a) / 194;
+ x += xx;
+ y += yy;
+
+ gfx::clearCircle(x + 3, y + 3, 3);
+ }
+ }
+
+ for (int i = 0; i < _len; i++)
+ {
+ int a = (INT16_MAX / (_len)) * i;
+
+ if (MOD(i, 2) == 1)
+ a += (-128 + swing) * (INT16_MAX / _len) / 6;
+
+ int dx = fpsin(a);
+ int dy = -fpcos(a);
+
+ int x = xx + dx / 194;
+ int y = yy + dy / 194;
+
+ if (pattern[i] || pattern2[i])
+ gfx::fillRect(x + 2, y + 2, 3, 3); // gfx::drawXbm(x, y, 7, 7, xmb_filled_circle_7x7);
+
+ if (i == rot)
+ gfx::drawRect(x, y, 7, 7);
+ else
+ gfx::drawCircle(x + 3, y + 3, 3); //
+
+ bool cursor = i == MOD(seq_pos, _len);
+
+ if (cursor && !pre_start)
+ gfx::drawRect(x + 1, y + 1, 5, 5);
+ }
+
+ if (playing && pre_start && MOD(millis(), 300) > 150)
+ {
+ }
+ else
+ {
+ int x = xx - 2;
+ int y = 40 - 7;
+ if (pattern[seq_pos % _len])
+ {
+ if (x < 64)
+ gfx::fillRect(x - 3, y - 7, 17, 17);
+ else
+ gfx::fillCircle(x + 5, y + 1, 8);
+ }
+ else
+ {
+ if (x < 64)
+ gfx::drawRect(x - 2, y - 7, 16, 16);
+ else
+ gfx::drawCircle(x + 5, y + 1, 8);
+ }
+ }
+}
+
+int32_t len = 16;
+int32_t pulses = 4;
+int32_t rotate = 0;
+
+int32_t lenB = 16;
+int32_t pulsesB = 4;
+int32_t rotateB = 0;
+
+void engine::setup()
+{
+ engine::addParam("#LEN", &len, 1, 20);
+ engine::addParam("#LEN", &lenB, 1, 20);
+ engine::addParam("#HIT", &pulses, 0, 16);
+ engine::addParam("#HIT", &pulsesB, 0, 16);
+ engine::addParam("#ROT", &rotate, 0, 32);
+ engine::addParam("#ROT", &rotateB, 0, 32);
+ engine::setMode(ENGINE_MODE_CV_OUT);
+}
+
+uint8_t pattern[64] = {};
+uint8_t pattern2[64] = {};
+
+uint8_t gate_until_t = 0;
+uint8_t gate_until2_t = 0;
+uint8_t next_clock = 1;
+
+int hit1 = 0;
+int hit2 = 0;
+
+char debug[128] = {};
+
+static int32_t _last_len = -1;
+static auto _last_pulses = pulses;
+static auto _last_rotate = rotate;
+
+static int32_t _last_lenB = -1;
+static auto _last_pulsesB = pulsesB;
+static auto _last_rotateB = rotateB;
+
+void update_seq_pattern()
+{
+ CONSTRAIN(pulses, pulses, len);
+ rotate %= len;
+
+ if (_last_len != len || _last_pulses != pulses || _last_rotate != rotate ||
+ _last_lenB != lenB || _last_pulsesB != pulsesB || _last_rotateB != rotateB)
+ {
+ _last_len = len;
+ _last_pulses = pulses;
+ _last_rotate = rotate;
+
+ _last_lenB = lenB;
+ _last_pulsesB = pulsesB;
+ _last_rotateB = rotateB;
+
+ pre_start = false;
+
+ make_pattern(pattern, len, pulses, rotate);
+ make_pattern(pattern2, lenB, pulsesB, rotateB);
+ }
+
+ if (engine::stepChanged())
+ {
+ seq_pos = engine::step();
+
+ bool trig = pattern[seq_pos % len];
+
+ if (trig)
+ {
+ hit1 = 64;
+ gate_until_t += 2; // 10ms trigger
+ }
+
+ bool trig2 = pattern2[seq_pos % lenB];
+ if (trig2)
+ {
+ hit2 = 64;
+ gate_until2_t += 2;
+ }
+ }
+}
+
+void engine::process()
+{
+ if (!playing)
+ {
+ gate_until_t = gate_until2_t = 0;
+ seq_pos = len - 1;
+ next_clock = 1;
+ pre_start = true;
+ return;
+ }
+
+ update_seq_pattern();
+
+ int32_t trig = 0;
+
+ if (gate_until_t > 0)
+ {
+ --gate_until_t;
+ trig = 5 * PITCH_PER_OCTAVE; // 5V
+ }
+
+ std::fill_n(engine::outputBuffer_i16<0>(), FRAME_BUFFER_SIZE, trig);
+
+ trig = 0;
+ if (gate_until2_t > 0)
+ {
+ --gate_until2_t;
+ trig = 5 * PITCH_PER_OCTAVE; // 5V
+ }
+
+ std::fill_n(engine::outputBuffer_i16<1>(), FRAME_BUFFER_SIZE, trig);
+}
+
+void engine::draw()
+{
+ char tmp[16];
+ sprintf(tmp, "%02d", engine::step());
+ gfx::drawStringCenter(64, 12, tmp, 0);
+ draw_eclid_cyrcle(36, 31, pattern, _last_len, _last_rotate);
+ draw_eclid_cyrcle(36 + 49, 31, pattern2, _last_lenB, _last_rotateB);
+}
+
+void engine::screensaver()
+{
+ gfx::clearRect(0, 0, 128, 64);
+ draw_eclid_cyrcle(36 - 4, 31, pattern, _last_len, _last_rotate);
+ draw_eclid_cyrcle(36 + 49 + 4, 31, pattern2, _last_lenB, _last_rotateB);
+}
\ No newline at end of file
diff --git a/app/SPEECH/LPC.bin b/app/SPEECH/LPC.bin
index 31ceb99..665ca4f 100644
Binary files a/app/SPEECH/LPC.bin and b/app/SPEECH/LPC.bin differ
diff --git a/app/SPEECH/LPC.cpp b/app/SPEECH/LPC.cpp
index 97ee2f9..e319f6b 100644
--- a/app/SPEECH/LPC.cpp
+++ b/app/SPEECH/LPC.cpp
@@ -8,8 +8,6 @@
#include "plaits/dsp/speech/lpc_speech_synth_controller.h"
#include "plaits/dsp/speech/lpc_speech_synth_words.h"
-#define FLASHMEM __attribute__((section(".text")))
-
#include "plaits/dsp/speech/lpc_speech_synth_controller.cc"
#include "plaits/dsp/speech/lpc_speech_synth_words.cc"
#include "plaits/dsp/speech/lpc_speech_synth_phonemes.cc"
diff --git a/app/SPEECH/SAM.bin b/app/SPEECH/SAM.bin
index 47025c7..c70e833 100644
Binary files a/app/SPEECH/SAM.bin and b/app/SPEECH/SAM.bin differ
diff --git a/app/SYNTH/Open303.bin b/app/SYNTH/Open303.bin
index fc2c19b..af086b5 100644
Binary files a/app/SYNTH/Open303.bin and b/app/SYNTH/Open303.bin differ
diff --git a/app/SYNTH/Open303.cpp b/app/SYNTH/Open303.cpp
index 584bb93..9678897 100644
--- a/app/SYNTH/Open303.cpp
+++ b/app/SYNTH/Open303.cpp
@@ -42,8 +42,6 @@
#include "open303/src/rosic_BlendOscillator.cpp"
#include "open303/src/rosic_BiquadFilter.cpp"
#include "open303/src/rosic_NumberManipulations.cpp"
-#include "open303/src/sequencer/rosic_AcidSequencer.cpp"
-#include "open303/src/sequencer/rosic_AcidPattern.cpp"
#include "open303/src/rosic_OnePoleFilter.cpp"
#include "open303/src/rosic_MidiNoteEvent.cpp"
#include "open303/src/rosic_TeeBeeFilter.cpp"
diff --git a/app/SYNTH/Resonator.bin b/app/SYNTH/Resonator.bin
index 622a756..c632548 100644
Binary files a/app/SYNTH/Resonator.bin and b/app/SYNTH/Resonator.bin differ
diff --git a/app/SYNTH/Resonator.cpp b/app/SYNTH/Resonator.cpp
index a8c910e..69e271a 100644
--- a/app/SYNTH/Resonator.cpp
+++ b/app/SYNTH/Resonator.cpp
@@ -1,6 +1,5 @@
#include "../squares-and-circles-api.h"
-#define FLASHMEM __attribute__((section(".text")))
-#undef ONE_POLE
+
#include "stmlib/stmlib.h"
#include "stmlib/dsp/units.cc"
#include "stmlib/utils/random.cc"
diff --git a/app/build.sh b/app/build.sh
index 6077ca5..e566bad 100644
--- a/app/build.sh
+++ b/app/build.sh
@@ -1,7 +1,7 @@
#!/usr/bin/bash
set -e #-eo pipefail
-cd $(dirname $0)
+cd $(dirname $0)/..
if ! which arm-none-eabi-gcc; then
export PATH=~/.platformio/packages/toolchain-gccarmnoneeabi/bin/:$PATH
@@ -11,7 +11,7 @@ fi
#pip install pyelftools
-for f in $(find . -mindepth 2 -maxdepth 2 -type f -name '*.cpp'); do
+for f in $(find $(dirname $0) -mindepth 2 -maxdepth 2 -type f -name '*.cpp'); do
X="${f%.*}"
@@ -21,29 +21,32 @@ fi
#-fno-rtti
NAME=$(grep "//ENGINE_NAME:" $f | cut -d':' -f2)
-NAME=${NAME:-"$(realpath --relative-to=. $X)"}
+NAME=${NAME:-"$(realpath --relative-to=$(dirname $0) $X)"}
echo ----- $NAME -----
-mkmodule=$(ls ../lib/udynlink/scripts/mkmodule | head -n1)
+mkmodule=$(ls lib/udynlink/scripts/mkmodule | head -n1)
BUILD_FLAGS=$(grep "build_flags:" $X.cpp | cut -d':' -f2-)
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-)
+
#--no-opt \
#-felide-constructors -fno-rtti -std=gnu++14 -Wno-error=narrowing -fno-threadsafe-statics
-$mkmodule $X.cpp \
+$mkmodule $X.cpp $CPP_FILES \
--no-opt \
- --build_flags="-fsingle-precision-constant -DNDEBUG -O3 $BUILD_FLAGS -I. -I../lib/ " \
+ --build_flags="-fsingle-precision-constant -DFLASHMEM='__attribute__((section(\".text.flashmem\")))' -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
touch -d "$(date -R -r $X.cpp)" $X.bin
-cat $X.log | arm-none-eabi-c++filt -t > ${X}2.log
+#cat $X.log | arm-none-eabi-c++filt -t > ${X}2.log
-arm-none-eabi-objdump -g -Dztr --source $X.elf | arm-none-eabi-c++filt -t > $X.elf.txt
+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- ./$X.elf -F -R --no-color >> $X.log
md5sum $X.bin | tee -a $X.log
@@ -52,9 +55,9 @@ echo "BIN_SIZE $(stat -c %s -- $X.bin)" | tee -a $X.log
grep "__aeabi_" $X.log && exit 1
-xxd -i $X.bin > ./$X.bin.h
-sed -i "s/unsigned char/const uint8_t/g" ./$X.bin.h
-sed -i "s/\[\]/\[\] FLASHMEM __attribute__((aligned(32)))/g" ./$X.bin.h
+#xxd -i $X.bin > ./$X.bin.h
+#sed -i "s/unsigned char/const uint8_t/g" ./$X.bin.h
+#sed -i "s/\[\]/\[\] FLASHMEM __attribute__((aligned(32)))/g" ./$X.bin.h
# arm-none-eabi-gcc -fPIE -msingle-pic-base -mcpu=cortex-m4 -mthumb -Wl,--unresolved-symbols=ignore-in-object-files -fdump-lang-class -I. -I../lib/ $X.cpp
# arm-none-eabi-objdump --disassemble-all --no-addresses ./$X.elf > $X.s
@@ -65,5 +68,8 @@ done
find . -type f -name '*.o' -delete
find . -type f -name '*.bin' -exec stat --printf="%-20n\t%6s\n" -- {} \;
-du -ch */*.bin | grep total
+du -ch $(dirname $0)/*/*.bin | grep total
#find . -type f -name '*.bin' -delete
+
+pio --version || alias pio=~/.platformio/penv/bin/pio
+pio run -v --environment squares-and-circles
\ No newline at end of file
diff --git a/app/index.json b/app/index.json
index c4174ce..aaebc5b 100644
--- a/app/index.json
+++ b/app/index.json
@@ -1,17 +1,21 @@
{
"apps": [
+ "CV/EnvGen_ADSR.bin",
"NOISE/WhitePink.bin",
"NOISE/NES.bin",
"NOISE/808_squares.bin",
"MIDI/Monitor.bin",
"MIDI/Clock.bin",
+ "DRUMS/FM-Drum.bin",
+ "DRUMS/808ish-BD.bin",
+ "DRUMS/808ish-SD.bin",
+ "DRUMS/808ish-HiHat.bin",
"DRUMS/TR909-HiHat.bin",
"DRUMS/TR909-Ride.bin",
"DRUMS/TR707.bin",
- "DRUMS/TR707-HiHat.bin",
-
- "DRUMS/Vint.Samples.bin",
+
+ "M-OSC/Waveforms.bin",
"FX/Reverb.bin",
"FX/ReverbSC.bin",
@@ -26,6 +30,9 @@
"FX/Delay.bin",
"FX/Gated-Reverb.bin",
"FX/Reverb-HP-LP.bin",
+
+ "SEQ/EuclidRythm.bin",
+ "SEQ/EuclidArp.bin",
"MIDI/VAx6.bin",
diff --git a/app/squares-and-circles-api.h b/app/squares-and-circles-api.h
index 00a615f..fceaffc 100644
--- a/app/squares-and-circles-api.h
+++ b/app/squares-and-circles-api.h
@@ -35,29 +35,20 @@
#include
#include
-#ifndef MACHINE_INTERNAL
+#define V_OCT "V_OCT"
+#define V_QTZ "V_QTZ"
+#define SEQ_SWING "$SWING"
+#define MULTI_TRIGS ">TRIGS"
-#if 0
-#define WASM_EXPORT extern "C" __attribute__((used)) __attribute__((visibility("default")))
-#define WASM_EXPORT_AS(NAME) WASM_EXPORT __attribute__((export_name(NAME)))
-#define WASM_IMPORT(MODULE, NAME) __attribute__((import_module(MODULE))) __attribute__((import_name(NAME)))
-#define WASM_CONSTRUCTOR __attribute__((constructor))
-#else
-#define WASM_EXPORT extern "C"
-#define WASM_EXPORT_AS(NAME) WASM_EXPORT
-#define WASM_IMPORT(MODULE, NAME)
-#define WASM_CONSTRUCTOR
+#ifndef EXTERN_C
+#define EXTERN_C extern "C"
#endif
-#ifndef FLASHMEM
-#define FLASHMEM __attribute__((section(".text")))
-#endif
+#ifndef MACHINE_INTERNAL
+
#define LEN_OF(x) (sizeof(x) / sizeof(x[0]))
#define MOD(x, y) ((x) % (y))
-#ifndef ONE_POLE
-#define ONE_POLE(out, in, coefficient) out += (coefficient) * ((in)-out);
-#endif
#ifndef CONSTRAIN
#define CONSTRAIN(var, min, max) \
if (var < (min)) \
@@ -71,7 +62,6 @@
#endif
-#define V_OCT "V_OCT"
#define IO_STEREOLIZE ".IO_STEREO"
#ifdef __cplusplus
@@ -83,13 +73,10 @@
// # pragma GCC poison virtual
#endif
-#ifndef EMSCRIPTEN
-
-extern "C" uint32_t micros();
-extern "C" uint32_t millis();
-extern "C" uint32_t crc32(uint32_t crc, const void *buf, size_t size);
+EXTERN_C uint32_t micros();
+EXTERN_C uint32_t millis();
+EXTERN_C uint32_t crc32(uint32_t crc, const void *buf, size_t size);
-#endif
#endif
#ifndef DEFAULT_NOTE
@@ -107,13 +94,15 @@ extern "C" uint32_t crc32(uint32_t crc, const void *buf, size_t size);
#ifndef engine
-extern "C"
+EXTERN_C
{
extern uint32_t *__t;
extern uint8_t *__clock;
- extern uint8_t *__trig;
- extern uint8_t *__gate;
- extern uint8_t *__accent;
+ extern uint8_t *__step;
+ extern bool *__step_changed;
+ extern uint32_t *__trig;
+ extern uint32_t *__gate;
+ extern uint32_t *__accent;
extern float *__cv;
extern float *__output_l_fp;
@@ -163,6 +152,23 @@ extern "C"
if (__midi_event_handler_ptr)
__midi_event_handler_ptr();
}
+
+ extern struct
+ {
+ uint8_t tr;
+ uint8_t ac;
+ uint8_t cv;
+ uint8_t qz;
+ int8_t transpose;
+ uint8_t aux;
+ uint8_t ext[4] = {0, 0, 0, 0};
+ uint8_t midi_channel;
+ uint8_t dac;
+ uint8_t level;
+ uint8_t pan; // 128 == center
+ uint8_t stereo;
+ uint8_t aux_dry;
+ } *__io;
}
namespace engine
@@ -171,11 +177,15 @@ namespace engine
inline uint32_t t() { return *__t; }
inline uint8_t clock() { return *__clock; }
- inline uint8_t trig() { return *__trig; }
- inline uint8_t gate() { return *__gate; }
- inline uint8_t accent() { return *__accent; }
+ inline uint8_t step() { return *__step; }
+ inline bool stepChanged() { return *__step_changed; }
+ inline uint32_t trig() { return *__trig; }
+ inline uint32_t gate() { return *__gate; }
+ inline uint32_t accent() { return *__accent; }
inline float cv() { return *__cv; }
+ inline bool is_stereo() { return (__io->dac == 2 || __io->dac == 5); }
+
template
inline float *outputBuffer();
@@ -203,10 +213,10 @@ namespace engine
template <>
inline float *inputBuffer<1>() { return *__audio_in_r_fpp; }
- extern "C" void setup();
- extern "C" void process();
- extern "C" void draw();
- extern "C" void screensaver();
+ EXTERN_C void setup();
+ EXTERN_C void process();
+ EXTERN_C void draw();
+ EXTERN_C void screensaver();
/////
typedef bool (*uiHandler)(uint16_t type, uint16_t control, int16_t value, uint16_t mask);
@@ -223,8 +233,8 @@ namespace engine
void __attribute__((weak)) onMidiCC(uint8_t ccc, uint8_t value);
void __attribute__((weak)) onMidiSysex(uint8_t byte);
- extern "C" void addParam_f32(const char *name, float *value, float min = 0.f, float max = 1.f); // min...max
- extern "C" void addParam_i32(const char *name, int32_t *value, int32_t min, int32_t max, const char **valueMap); // 0...max
+ EXTERN_C void addParam_f32(const char *name, float *value, float min = 0.f, float max = 1.f); // min...max
+ EXTERN_C void addParam_i32(const char *name, int32_t *value, int32_t min, int32_t max, const char **valueMap); // 0...max
void addParam(const char *name, int32_t *value, int32_t min, int32_t max, const char **valueMap = nullptr) // 0...max
{
@@ -270,19 +280,18 @@ namespace engine
constexpr uint32_t PARAM_SELECTED = 0x1;
constexpr uint32_t PARAM_MODULATION = 0x2;
- extern "C" uint32_t getParamFlags(const void *valuePtr);
+ EXTERN_C uint32_t getParamFlags(const void *valuePtr);
inline uint32_t isParamSelected(const void *valuePtr)
{
return getParamFlags(valuePtr) & PARAM_SELECTED;
}
- extern "C"
- {
- void *dsp_sample_u8(const uint8_t *data, int len, int sample_rate, int addr_shift);
- void *dsp_sample_Am6070(const uint8_t *data, int len, int sample_rate, int amp_mul);
- void dsp_process_sample(void *smpl, float start, float end, float pitch, float output[FRAME_BUFFER_SIZE]);
- void dsp_process_hihats(void *ch, void *oh, float ch_vol, float ch_dec, float oh_dec, float output[FRAME_BUFFER_SIZE]);
- }
+ EXTERN_C void setParamName(const void *valuePtr, const char *name);
+
+ EXTERN_C void *dsp_sample_u8(const uint8_t *data, int len, int sample_rate, int addr_shift);
+ EXTERN_C void *dsp_sample_Am6070(const uint8_t *data, int len, int sample_rate, int amp_mul);
+ EXTERN_C void dsp_set_sample_pos(void *smpl, float pos, float amplitude, float decay);
+ EXTERN_C void dsp_process_sample(void *smpl, float start, float end, float pitch, float output[FRAME_BUFFER_SIZE]);
}
enum EventType : uint16_t
@@ -300,7 +309,7 @@ constexpr uint16_t ENCODER_R = (1 << 9);
namespace machine
{
- extern "C" const uint8_t *fs_read(const char *blobName);
+ EXTERN_C const uint8_t *fs_read(const char *blobName);
inline uint32_t clk_bpm()
{
@@ -330,53 +339,53 @@ namespace machine
else
return nullptr;
}
-};
+}
#else
using namespace ui;
using namespace UI;
#endif
+#ifndef GFX_API
namespace gfx
{
- extern "C" void drawCircle(int x, int y, int r);
- extern "C" void fillCircle(int x, int y, int r);
- extern "C" void clearCircle(int x, int y, int r);
- extern "C" void drawRect(int x, int y, int w, int h);
- extern "C" void fillRect(int x, int y, int w, int h);
- extern "C" void clearRect(int x, int y, int w, int h);
- extern "C" void invertRect(int x, int y, int w, int h);
- extern "C" void drawString(int32_t x, int32_t y, const char *s, int32_t font = 1);
- extern "C" void drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2);
- extern "C" void setPixel(int x, int y)
- {
- drawLine(x, y, x, y);
- }
- extern "C" void drawXbm(int x, int y, int width, int height, const uint8_t *xbm);
- extern "C" void message(const char *msg);
+ EXTERN_C void drawCircle(int x, int y, int r);
+ EXTERN_C void fillCircle(int x, int y, int r);
+ EXTERN_C void clearCircle(int x, int y, int r);
+ EXTERN_C void drawRect(int x, int y, int w, int h);
+ EXTERN_C void fillRect(int x, int y, int w, int h);
+ EXTERN_C void clearRect(int x, int y, int w, int h);
+ EXTERN_C void invertRect(int x, int y, int w, int h);
+ EXTERN_C void drawString(int x, int y, const char *s, uint8_t font = 1);
+ EXTERN_C void drawStringCenter(int x, int y, const char *s, uint8_t font = 1);
+ EXTERN_C void drawLine(int x1, int y1, int x2, int y2);
+ EXTERN_C void setPixel(int x, int y);
+ EXTERN_C void drawXbm(int x, int y, int width, int height, const uint8_t *xbm);
+ EXTERN_C void drawSample(void *smpl);
+ EXTERN_C void message(const char *msg);
inline uint8_t *displayBuffer()
{
return __display_buffer_u8_p;
}
}
+#endif
+#ifndef SERIAL_API
namespace machine
{
- extern "C"
- {
- extern void serial_write(void const *buffer, uint32_t bufsiz);
- extern uint32_t serial_read(void *buffer, uint32_t length);
- extern uint32_t serial_available();
+ EXTERN_C void serial_write(void const *buffer, uint32_t bufsiz);
+ EXTERN_C uint32_t serial_read(void *buffer, uint32_t length);
+ EXTERN_C uint32_t serial_available();
- extern void get_device_id(uint8_t *mac);
+ EXTERN_C void get_device_id(uint8_t *mac);
- extern float cpu_load_percent();
+ EXTERN_C float cpu_load_percent();
- extern uint8_t *engine_malloc(uint32_t size);
- extern void engine_start(uint32_t args);
- extern void engine_stop(uint32_t result);
- }
+ EXTERN_C uint8_t *engine_malloc(uint32_t size);
+ EXTERN_C void engine_start(uint32_t args);
+ EXTERN_C void engine_stop(uint32_t result);
}
+#endif
#endif // MACHINE_INTERNAL
@@ -410,14 +419,11 @@ typedef DWORD FSIZE_t;
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
-extern "C"
-{
- FRESULT f_open(FIL *f, const char *name, uint32_t mode);
- FRESULT f_read(FIL *f, void *p, UINT size, UINT *bytes_read);
- FSIZE_t f_tell(FIL *fp);
- FSIZE_t f_size(FIL *fp);
- FRESULT f_truncate(FIL *fp);
- FRESULT f_lseek(FIL *fp, FSIZE_t ofs);
- FRESULT f_close(FIL *f);
- FRESULT f_write(FIL *fp, const void *buff, UINT btw, UINT *bw);
-}
\ No newline at end of file
+EXTERN_C FRESULT f_open(FIL *f, const char *name, uint32_t mode);
+EXTERN_C FRESULT f_read(FIL *f, void *p, UINT size, UINT *bytes_read);
+EXTERN_C FSIZE_t f_tell(FIL *fp);
+EXTERN_C FSIZE_t f_size(FIL *fp);
+EXTERN_C FRESULT f_truncate(FIL *fp);
+EXTERN_C FRESULT f_lseek(FIL *fp, FSIZE_t ofs);
+EXTERN_C FRESULT f_close(FIL *f);
+EXTERN_C FRESULT f_write(FIL *fp, const void *buff, UINT btw, UINT *bw);
\ No newline at end of file
diff --git a/app/upload.py b/app/upload.py
new file mode 100755
index 0000000..78caba1
--- /dev/null
+++ b/app/upload.py
@@ -0,0 +1,169 @@
+#!/bin/python3
+
+import rtmidi
+import json
+import os
+import zlib
+import time
+import intelhex # pip install intelhex - #https://python-intelhex.readthedocs.io/en/latest/part2-2.html
+import os, io
+
+midiout = rtmidi.MidiOut()
+
+for i in range(0, midiout.get_port_count()):
+ if midiout.get_port_name(i).startswith("S&C"):
+ midiout.open_port(i)
+
+midiin = rtmidi.MidiIn(queue_size_limit=1024 * 8)
+
+for i in range(0, midiin.get_port_count()):
+ if midiin.get_port_name(i).startswith("S&C"):
+ midiin.open_port(i)
+
+while True:
+ msg = midiin.get_message()
+ if not msg:
+ break
+
+
+def flush(midiin):
+ while True:
+ msg = midiin.get_message()
+ if not msg:
+ break
+
+
+def chunk_bytes(bytes_object, chunk_size):
+ chunks = (
+ bytes_object[i : i + chunk_size]
+ for i in range(0, len(bytes_object), chunk_size)
+ )
+ return chunks
+
+
+def sendFLASHDATA(name, data0):
+ flush(midiin)
+ data = bytes(name, "utf-8")[:8] + data0
+ crc32 = zlib.crc32(data)
+ print(" Flashing", name, crc32)
+ midiout.send_message(
+ [0xF3, 0x7E]
+ ) # midi_out.send(mido.Message('song_select', song=0x7e))
+ flush(midiin)
+ vlen = len(data)
+ ch = 0 + ((vlen & 0xF000) >> 12)
+ rawValue = [0b11100000 | ch, vlen & 0x7F, vlen >> 7 & 0x7F]
+
+ midiout.send_message(rawValue)
+
+ while True:
+ msg = midiin.get_message()
+ if msg:
+ ack, t = msg
+ print(" ACK:", ack)
+ break
+
+ print(" sending blob...", len(data))
+ i = 0
+ time.sleep(1 / 10000)
+ while i < len(data) - 1:
+ int16 = data[i] | data[i + 1] << 8
+ ch = 0 + ((data[i + 1] & 0xF0) >> 4)
+ rawValue = [0b11100000 | ch, int16 & 0x7F, int16 >> 7 & 0x7F]
+ midiout.send_message(rawValue)
+ time.sleep(1 / 10000)
+ i += 2
+
+ flush(midiin)
+ time.sleep(1 / 10000)
+
+ rawValue = [0b11100000, crc32 & 0x7F, crc32 >> 7 & 0x7F]
+ midiout.send_message(rawValue)
+
+ while True:
+ msg = midiin.get_message()
+ if msg:
+ data, t = msg
+ print(" CRC_CHECK:", data)
+ break
+
+
+midiout.send_message([0xF3, ord("E")])
+
+engines = ""
+
+try:
+ while True:
+ msg = midiin.get_message()
+ if msg:
+ data, t = msg
+ c = (data[2] << 7 | data[1]) - 8192
+ if c == 0:
+ break
+ engines += chr(c)
+except KeyboardInterrupt:
+ print("")
+finally:
+ print("OK")
+
+engines = json.loads(engines)
+
+apps_json = os.path.dirname(__file__) + "/index.json"
+with open(apps_json) as f:
+ apps = json.load(f)
+ j = 0
+ for file in apps["apps"]:
+ bin_file = os.path.dirname(apps_json) + "/" + str(file)
+ if not os.path.exists(bin_file):
+ continue
+ 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"] == os.path.splitext(file)[0]), None
+ )
+ if engine != None and engine["crc32"] == "%x" % crc32sum:
+ print(
+ os.path.splitext(file)[0],
+ "%x" % crc32sum,
+ "OK!",
+ bin_size - int(engine["size"]),
+ )
+ continue
+
+ print("->", file, engine)
+
+ if engine == None:
+ print("TODO - add new engine...")
+ continue
+
+ print(
+ os.path.splitext(file)[0], "%x" % crc32sum, bin_size - int(engine["size"])
+ )
+
+ offset = 0
+ ih = intelhex.IntelHex()
+ ih.loadbin(bin_file, offset=offset)
+ offset += bin_size
+ ih.puts(offset, crc32sum.to_bytes(4, "little"))
+ offset += 4
+
+ with io.BytesIO() as w:
+ ih.tofile(w, format="bin")
+ abx = w.getvalue()
+ offset = int(engine["addr"], 16) # (1024 * 1024)
+ for chunk in chunk_bytes(abx, 4096):
+ sendFLASHDATA(f"0x%6x" % offset, chunk)
+ offset += len(chunk)
+
+ j += 1
+
+ offset += 4 - (offset % 4)
+
+ if j > 0:
+ midiout.send_message([0xF3, 0x7F]) #reset
+
+midiin.close_port()
+midiout.close_port()
+del midiin
+del midiout
diff --git a/build.py b/build.py
index 25a9ff3..7079b7f 100644
--- a/build.py
+++ b/build.py
@@ -3,7 +3,6 @@
import json
import shutil
import io
-import mido #~/.platformio/penv/bin/pip install mido python-rtmidi
import zlib
import time
import intelhex #pip install intelhex - #https://python-intelhex.readthedocs.io/en/latest/part2-2.html
@@ -29,6 +28,7 @@ def make_engines_hex(apps_json, ih = intelhex.IntelHex(), offset= 0):
else:
with open(apps_json) as f:
apps = json.load(f)
+ i = 1
for file in apps["apps"]:
bin_file=os.path.dirname(apps_json)+'/'+str(file)
if not os.path.exists(bin_file):
@@ -43,16 +43,16 @@ def make_engines_hex(apps_json, ih = intelhex.IntelHex(), offset= 0):
ih.puts(offset, crc32sum.to_bytes(4, 'little') )
offset += 4
- print("0x%x" % bin_offset, bin_file, bin_size, udynlink_size(bin_file) % 4, "CRC32: %x" % crc32sum)
-
- offset += 4 - (offset % 4)
+ print(i, "0x%x" % bin_offset, bin_file, bin_size, udynlink_size(bin_file) % 4, "CRC32: %x" % crc32sum)
+ i+=1
+ offset += 4096 - (offset % 4096)
ih.puts(offset, 0xffff.to_bytes(4, 'little') )
return ih
env = DefaultEnvironment()
#print(env.Dump())
-env.Execute(f"bash $PROJECT_DIR/app/build.sh")
+#env.Execute(f"bash $PROJECT_DIR/app/build.sh")
env.Append(
LINKFLAGS=[
@@ -61,70 +61,6 @@ def make_engines_hex(apps_json, ih = intelhex.IntelHex(), offset= 0):
]
)
-midi_out = None
-midi_in = None
-
-def midi_init():
- global midi_in, midi_out
- try:
- for mo in mido.get_output_names():
- if "S&C" in mo or "Squares&Circles" in mo or "Teensy MIDI" in mo:
- midi_out = mido.open_output(mo)
- break
-
- for mi in mido.get_input_names():
- print(mi)
- if "S&C" in mi or "Squares&Circles" in mi or "Teensy MIDI" in mi:
- midi_in = mido.open_input(mi)
- break
- except:
- pass
-
-
-def chunk_bytes(bytes_object, chunk_size):
- chunks = (bytes_object[i:i+chunk_size] for i in range(0, len(bytes_object), chunk_size))
- return chunks
-
-def flush(input):
- for m in input.iter_pending():
- m #print("FLUSH", m)
-
-def sendFLASHDATA(name, data0):
- flush(midi_in)
- data = bytes(name, 'utf-8')[:8] + data0
- crc32=zlib.crc32(data)
- print("Flashing", name, crc32)
- midi_out.send(mido.Message('song_select', song=0x7e))
- flush(midi_in)
- vlen = len(data)
- ch = 0 + ((vlen & 0xF000) >> 12)
- rawValue = [0b11100000 | ch, vlen & 0x7f, vlen >> 7 & 0x7f]
- msg0 = mido.Message.from_bytes(rawValue)
- midi_out.send(msg0)
- msg1 = midi_in.receive(block=True)
- if msg1.pitch != 1:
- print("INIT FAILED", msg1.pitch, msg1)
- exit(-1) #no memory
- i=0
- time.sleep(1/10000)
- while i < len(data):
- int16 = data[i] | data[i + 1] << 8
- ch = 0 + ((data[i + 1] & 0xF0) >> 4)
- rawValue = [0b11100000 | ch, int16 & 0x7f, int16 >> 7 & 0x7f]
- midi_out.send(mido.Message.from_bytes(rawValue))
- time.sleep(2/10000)
- i += 2
-
- flush(midi_in)
- time.sleep(1/10000)
-
- rawValue = [0b11100000, crc32 & 0x7f, crc32 >> 7 & 0x7f]
- midi_out.send(mido.Message.from_bytes(rawValue))
- msg1 = midi_in.receive(block=True)
- if msg1.pitch != 1:
- print("CRC CHECK FAILED", msg1.pitch, msg1)
- exit(-1) #crc failed
-
def post_program_action(source, target, env):
os.remove(target[0].get_abspath())
apps_json=env.GetProjectOption("apps_json")
@@ -137,28 +73,7 @@ def post_program_action(source, target, env):
print(program_path, len(ahx))
def upload_hex(source, target, env):
-
- midi_init()
-
- print(midi_in)
- print(midi_out)
-
- if midi_out == None:
- exit(-1)
-
- program_path = env.GetBuildPath("$PROJECT_DIR/.pio/build/$PIOENV/engines.hex")
- ahx = intelhex.IntelHex(program_path)
-
- with io.BytesIO() as w:
- ahx.tofile(w, format='bin')
- abx=w.getvalue()
- offset = (1024 * 1024)
- for chunk in chunk_bytes(abx, 4096):
- sendFLASHDATA(f"0x%6x" % offset, chunk)
- offset += len(chunk)
- print(len(abx))
- midi_out.send(mido.Message('song_select', song=0x7f))
-
+ print("not implemented!")
exit(0)
env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex", post_program_action)
diff --git a/doc/.conv.sh b/doc/.conv.sh
index c06a7bb..eb2d679 100644
--- a/doc/.conv.sh
+++ b/doc/.conv.sh
@@ -1,5 +1,5 @@
-montage -background '#25282c' -tile 5x -geometry +10+10 gnd_*.png cv_*.png drums_*.png mosc_*.png synth_*.png noise_*.png fx_*.png midi_*.png engines.png
+montage -background '#25282c' -tile 5x -geometry +10+10 gnd_*.png cv_*.png drums_*.png mosc_*.png synth_*.png noise_*.png fx_*.png midi_*.png seq_*.png engines.png
for f in $1; do
convert $f -sample 256x128 ${f%.*}.png
diff --git a/doc/engines.png b/doc/engines.png
index 5f2c27b..fef02e1 100644
Binary files a/doc/engines.png and b/doc/engines.png differ
diff --git a/doc/mod_seq.png b/doc/mod_seq.png
new file mode 100644
index 0000000..702e8be
Binary files /dev/null and b/doc/mod_seq.png differ
diff --git a/lib/bbd/bbd_line.cc b/lib/bbd/bbd_line.cc
index 7afcb9b..7177353 100644
--- a/lib/bbd/bbd_line.cc
+++ b/lib/bbd/bbd_line.cc
@@ -4,6 +4,8 @@
void BBD_Line::setup(unsigned ns, const BBD_Filter_Coef &fin, const BBD_Filter_Coef &fout)
{
+ //[eh2k] mem_.reserve(8192);
+
fin_ = &fin;
fout_ = &fout;
@@ -15,6 +17,12 @@ void BBD_Line::setup(unsigned ns, const BBD_Filter_Coef &fin, const BBD_Filter_C
Gin_.reset(new cdouble[Min]);
Gout_.reset(new cdouble[Mout]);
+ set_delay_size(ns);
+ clear();
+}
+
+void BBD_Line::set_delay_size(unsigned ns)
+{
mem_.clear();
mem_.resize(ns);
imem_ = 0;
@@ -51,25 +59,21 @@ void BBD_Line::process(unsigned n, const float *input, float *output, const floa
cdouble *Gin = Gin_.get(), *Gout = Gout_.get();
const cdouble *Pin = fin.P.get(), *Pout = fout.P.get();
- for (unsigned i = 0; i < n; ++i)
- {
+ for (unsigned i = 0; i < n; ++i) {
double fclk = clock[i];
for (unsigned m = 0; m < Mout; ++m)
Xout[m] = 0;
- if (fclk > 0)
- {
+ if (fclk > 0) {
auto pclk_old = pclk;
pclk += fclk;
unsigned tick_count = (unsigned)pclk;
pclk -= tick_count;
- for (unsigned tick = 0; tick < tick_count; ++tick)
- {
+ for (unsigned tick = 0; tick < tick_count; ++tick) {
auto d = (1 - pclk_old + tick) * (1 / fclk);
d -= (unsigned)d;
- if ((ptick & 1) == 0)
- {
+ if ((ptick & 1) == 0) {
fin.interpolate_G(d, Gin);
cdouble s = 0;
for (unsigned m = 0; m < Min; ++m)
@@ -77,8 +81,7 @@ void BBD_Line::process(unsigned n, const float *input, float *output, const floa
mem[imem] = s.real();
imem = ((imem + 1) < ns) ? (imem + 1) : 0;
}
- else
- {
+ else {
fout.interpolate_G(d, Gout);
auto ybbd = mem[imem];
auto delta = ybbd - ybbd_old;
@@ -94,8 +97,7 @@ void BBD_Line::process(unsigned n, const float *input, float *output, const floa
Xin[m] = Pin[m] * Xin[m] + cdouble(input[i]);
cdouble y = fout.H * ybbd_old;
- for (unsigned m = 0; m < Mout; ++m)
- {
+ for (unsigned m = 0; m < Mout; ++m) {
cdouble xout = Pout[m] * Xout_mem[m] + Xout[m];
Xout_mem[m] = xout;
y += xout;
diff --git a/lib/bbd/bbd_line.h b/lib/bbd/bbd_line.h
index 8bd188d..c604155 100644
--- a/lib/bbd/bbd_line.h
+++ b/lib/bbd/bbd_line.h
@@ -7,10 +7,6 @@
class BBD_Line {
public:
-
- BBD_Line():mem_(0)
- {}
-
/**
* Initialize a delay line with the specified parameters. (non-RT)
* @param fs audio sampling rate
@@ -20,6 +16,13 @@ class BBD_Line {
*/
void setup(unsigned ns, const BBD_Filter_Coef &fin, const BBD_Filter_Coef &fout);
+ /**
+ * Change the number of stages. (RT?)
+ * @note It guarantees not to reallocate the buffer for \f$ns \leq 8192\f$.
+ * @param ns number of stages / length of the virtual capacitor array
+ */
+ void set_delay_size(unsigned ns);
+
/**
* Reinitialize all the internal state to zero. (RT)
*/
diff --git a/lib/braids/settings.cc b/lib/braids/settings.cc
index f61d795..df3b3ca 100644
--- a/lib/braids/settings.cc
+++ b/lib/braids/settings.cc
@@ -191,6 +191,7 @@ const char* const algo_values[] = {
"CLOU",
"PRTC",
"QPSK",
+ "****"
// "NAME" // For your algorithm
};
diff --git a/lib/misc/euclidean.h b/lib/misc/euclidean.h
new file mode 100644
index 0000000..2a8c155
--- /dev/null
+++ b/lib/misc/euclidean.h
@@ -0,0 +1,118 @@
+
+// Copyright (C)2023 - Eduard 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.
+//
+
+#include
+#include
+
+// found here:
+// https://louridas.github.io/rwa/assignments/musical-rhythms/#toussaint:2005
+// https://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf
+
+// https://github.com/grindcode/rhythms/blob/main/src/lib.rs#L129
+// https://github.com/computermusicdesign/euclidean-rhythm/blob/master/max-example/euclidSimple.js
+
+void simple_pattern(uint8_t *pattern, int len, int pulses, int rotate)
+{
+ pulses = std::min(pulses, len);
+ uint8_t bucket = 0;
+ uint8_t offset = 2 + rotate;
+
+ if (len > 0 && pulses > 0)
+ offset += len / pulses - 1;
+
+ for (uint8_t i = 0; i < len; i++)
+ {
+ uint8_t pos = (offset + i) % len;
+ bucket += pulses;
+ if (bucket >= len)
+ {
+ bucket -= len;
+ pattern[pos] = 1;
+ }
+ else
+ {
+ pattern[pos] = 0;
+ }
+ }
+}
+
+// based on https://bitbucket.org/sjcastroe/bjorklunds-algorithm/src/master/Bjorklund's%20Algorithm/bjorklund.cpp
+
+void bjorklund_pattern(uint8_t *pattern, int len, int pulses, int rotate)
+{
+ struct Pattern
+ {
+ uint32_t hits;
+ size_t len;
+ void append(const Pattern &second)
+ {
+ hits |= (second.hits << len);
+ len += second.len;
+ }
+ };
+
+ if (pulses > len)
+ pulses = len;
+
+ Pattern x = {0x1, 1};
+ int x_amount = pulses;
+ Pattern y = {0x0, 1};
+ int y_amount = len - pulses;
+
+ do
+ {
+ int x_temp = x_amount;
+ int y_temp = y_amount;
+ Pattern y_copy = y;
+
+ if (x_temp >= y_temp)
+ {
+ x_amount = y_temp;
+ y_amount = x_temp - y_temp;
+
+ y = x;
+ }
+ else
+ {
+ x_amount = x_temp;
+ y_amount = y_temp - x_temp;
+ }
+
+ x.append(y_copy);
+ } while (x_amount > 1 && y_amount > 1);
+
+ int k = 0;
+ for (int i = 1; i <= x_amount; i++)
+ for (auto j = 0; j < x.len; j++)
+ pattern[(k++ + rotate) % len] = (x.hits & (0x1 << j));
+ for (int i = 1; i <= y_amount; i++)
+ for (auto j = 0; j < y.len; j++)
+ pattern[(k++ + rotate) % len] = (y.hits & (0x1 << j));
+}
+
+#ifndef make_pattern
+#define make_pattern bjorklund_pattern
+#endif
\ No newline at end of file
diff --git a/lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.cpp b/lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.cpp
index fd12952..08898a8 100644
--- a/lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.cpp
+++ b/lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.cpp
@@ -16,22 +16,25 @@ FourierTransformerRadix2::FourierTransformerRadix2()
direction = FORWARD;
normalizationMode = NORMALIZE_ON_INVERSE_TRAFO;
normalizationFactor = 1.0;
+#ifndef STATIC_N
w = NULL;
ip = NULL;
tmpBuffer = NULL;
-
+#endif
setBlockSize(256);
}
FourierTransformerRadix2::~FourierTransformerRadix2()
{
// free dynamically allocated memory:
+#ifndef STATIC_N
if( w != NULL )
delete[] w;
if( ip != NULL )
delete[] ip;
if( tmpBuffer != NULL )
delete[] tmpBuffer;
+#endif
}
//-------------------------------------------------------------------------------------------------
@@ -50,6 +53,7 @@ void FourierTransformerRadix2::setBlockSize(int newBlockSize)
logN = (int) floor( log2((real_t) N + 0.5 ) );
updateNormalizationFactor();
+#ifndef STATIC_N
if( w != NULL )
delete[] w;
w = new real_t[2*N];
@@ -62,6 +66,9 @@ void FourierTransformerRadix2::setBlockSize(int newBlockSize)
if( tmpBuffer != NULL )
delete[] tmpBuffer;
tmpBuffer = new Complex[N];
+#else
+ ip[0] = 0;
+#endif
}
}
else if( !isPowerOfTwo(newBlockSize) || newBlockSize <= 1 )
diff --git a/lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.h b/lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.h
index f456ded..9ece96e 100644
--- a/lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.h
+++ b/lib/open303/src/wavetable_gen/rosic_FourierTransformerRadix2.h
@@ -8,6 +8,8 @@
#include "rosic_Complex.h"
#include "../rosic_RealFunctions.h"
+#define STATIC_N 256 //[eh2k] remove this, to use the original implementation (with new/delete)
+
namespace rosic
{
@@ -148,12 +150,18 @@ namespace rosic
int normalizationMode; /**< The normalization mode (@see: normalizationModes. */
real_t normalizationFactor; /**< The normalization factor (can be 1, 1/N or 1/sqrt(N)). */
+#ifndef STATIC_N
// work-area stuff for Ooura's fft-routines:
real_t *w; /**< Table of the twiddle-factors. */
int *ip; /**< Work area for bit-reversal (index pointer?). */
// our own temporary storage area:
Complex* tmpBuffer;
+#else
+ real_t w[2*STATIC_N];
+ int ip[4+16]; //ceil(4.0+sqrt(STATIC_N))];
+ Complex tmpBuffer[STATIC_N];
+#endif
};
diff --git a/lib/open303/src/wavetable_gen/rosic_MipMappedWaveTable.cpp b/lib/open303/src/wavetable_gen/rosic_MipMappedWaveTable.cpp
index c36f6f1..0ca7b41 100644
--- a/lib/open303/src/wavetable_gen/rosic_MipMappedWaveTable.cpp
+++ b/lib/open303/src/wavetable_gen/rosic_MipMappedWaveTable.cpp
@@ -1,4 +1,5 @@
#include "rosic_MipMappedWaveTable.h"
+#include
using namespace rosic;
MipMappedWaveTable::MipMappedWaveTable()
@@ -244,7 +245,8 @@ void MipMappedWaveTable::fillWithSquare303()
// do a circular shift to phase-align with the saw-wave, when both waveforms are mixed:
int nShift = roundToInt(N*squarePhaseShift/360.0);
- circularShift(prototypeTable, N, nShift);
+
+ std::rotate(&prototypeTable[0], &prototypeTable[0] + nShift, &prototypeTable[N]); //[eh2k] circularShift(prototypeTable, N, nShift);
}
void MipMappedWaveTable::fillWithSaw303()
diff --git a/lib/peaks/modulations/multistage_envelope.cc b/lib/peaks/modulations/multistage_envelope.cc
index d09dba0..34fc805 100644
--- a/lib/peaks/modulations/multistage_envelope.cc
+++ b/lib/peaks/modulations/multistage_envelope.cc
@@ -78,8 +78,12 @@ void MultistageEnvelope::Process(
int32_t a = start_value_;
int32_t b = level_[segment_ + 1];
- uint16_t t = Interpolate824(
- lookup_table_table[LUT_ENV_LINEAR + shape_[segment_]], phase_);
+
+ //eh2k >>>
+ const uint16_t * lutt[] = { lut_env_linear, lut_env_expo, lut_env_quartic };
+ //<<<
+
+ uint16_t t = Interpolate824(lutt[shape_[segment_]], phase_);
value_ = a + ((b - a) * (t >> 1) >> 15);
phase_ += phase_increment_;
*out++ = value_;
diff --git a/lib/plaits/dsp/chords/chord_bank.cc b/lib/plaits/dsp/chords/chord_bank.cc
index 96f1efe..53628b4 100644
--- a/lib/plaits/dsp/chords/chord_bank.cc
+++ b/lib/plaits/dsp/chords/chord_bank.cc
@@ -41,7 +41,7 @@ using namespace stmlib;
#ifdef JON_CHORDS
//[eh2k]
-const char* const chord_names[kChordNumChords] FLASHMEM = {
+const char* const chord_names[kChordNumChords] = {
"OCT",
"Fifth",
"m",
@@ -63,7 +63,7 @@ const char* const chord_names[kChordNumChords] FLASHMEM = {
// Alternative chord table by Jon Butler jonbutler88@gmail.com
/* static */
-const float ChordBank::chords_[kChordNumChords][kChordNumNotes] FLASHMEM = {
+const float ChordBank::chords_[kChordNumChords][kChordNumNotes] = {
// Fixed Intervals
{ 0.00f, 0.01f, 11.99f, 12.00f }, // Octave
{ 0.00f, 7.00f, 7.01f, 12.00f }, // Fifth
diff --git a/lib/rings/resources.cc b/lib/rings/resources.cc
index 193445f..47e9fbb 100644
--- a/lib/rings/resources.cc
+++ b/lib/rings/resources.cc
@@ -38,16 +38,6 @@
namespace rings {
-
-
-const int16_t* lookup_table_int16_table[] = {
-};
-
-
-
-const uint32_t* lookup_table_uint32_table[] = {
-};
-
const float FLASHMEM lut_sine[] = {
0.000000000e+00, 1.533980186e-03, 3.067956763e-03, 4.601926120e-03,
6.135884649e-03, 7.669828740e-03, 9.203754782e-03, 1.073765917e-02,
diff --git a/lib/stmlib/dsp/units.h b/lib/stmlib/dsp/units.h
index 41ddbaf..bd3f28d 100644
--- a/lib/stmlib/dsp/units.h
+++ b/lib/stmlib/dsp/units.h
@@ -34,6 +34,50 @@
namespace stmlib {
+// https://pichenettes.github.io/mutable-instruments-documentation/tech_notes/exponential_conversion_in_digital_oscillators/
+
+// Computes 2^x by using a polynomial approximation of 2^frac(x) and directly
+// incrementing the exponent of the IEEE 754 representation of the result
+// by int(x). Depending on the use case, the order of the polynomial
+// approximation can be chosen.
+template
+inline float Pow2Fast(float x) {
+ union {
+ float f;
+ int32_t w;
+ } r;
+
+
+ if (order == 1) {
+ r.w = float(1 << 23) * (127.0f + x);
+ return r.f;
+ }
+
+ int32_t x_integral = static_cast(x);
+ if (x < 0.0f) {
+ --x_integral;
+ }
+ x -= static_cast(x_integral);
+
+ if (order == 1) {
+ r.f = 1.0f + x;
+ } else if (order == 2) {
+ r.f = 1.0f + x * (0.6565f + x * 0.3435f);
+ } else if (order == 3) {
+ r.f = 1.0f + x * (0.6958f + x * (0.2251f + x * 0.0791f));
+ }
+ r.w += x_integral << 23;
+ return r.f;
+}
+
+#ifdef SemitonesToRatioFast
+
+inline float SemitonesToRatio(float semitones){
+ return Pow2Fast<1>(semitones / 12.f);
+}
+
+#else
+
extern const float lut_pitch_ratio_high[257];
extern const float lut_pitch_ratio_low[257];
@@ -45,6 +89,8 @@ inline float SemitonesToRatio(float semitones) {
lut_pitch_ratio_low[static_cast(pitch_fractional * 256.0f)];
}
+#endif
+
inline float SemitonesToRatioSafe(float semitones) {
float scale = 1.0f;
while (semitones > 120.0f) {
diff --git a/lib/udynlink b/lib/udynlink
index 7ad890c..7337f22 160000
--- a/lib/udynlink
+++ b/lib/udynlink
@@ -1 +1 @@
-Subproject commit 7ad890c70ba8ac0a9500c9b6c1aaec5380ff717a
+Subproject commit 7337f22fd7995540b102cbe44fe6b4ffccd58200
diff --git a/platformio.ini b/platformio.ini
index abd09b5..947bbd2 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -10,7 +10,6 @@
[env:squares-and-circles]
apps_json = ./app/index.json
extra_scripts = build.py
-squares_and_circles_loader = a751cf7 ; minimum loader version
-platform = teensy@5.0.0 ; https://github.com/platformio/platform-teensy/releases
-board = teensy41 ; fake setting - the engines are compatibe with all targets
-
+squares_and_circles_loader = 2cd9d0a ; minimum loader version
+platform = teensy@5.0.0 ; https://github.com/platformio/platform-teensy/releases
+board = teensy41 ; fake setting - the engines are compatibe with all targets
diff --git a/test/test_midi.sh b/test/test_midi.sh
index ba38544..eb9132c 100644
--- a/test/test_midi.sh
+++ b/test/test_midi.sh
@@ -6,15 +6,20 @@ amidi -p $int -S "F34D" # set CH 1,2,3,4
RANDOM=1
I=0
-N=44
+N=52
while true; do
for i in $(seq 0 100); do
- C=$(($RANDOM % 4))
- PROG=$((1 + $RANDOM % $N))
+ PROG1=$((1 + $RANDOM % $N))
+ PROG2=$((1 + $RANDOM % $N))
+ PROG3=$((1 + $RANDOM % $N))
+ PROG4=$((1 + $RANDOM % $N))
#if [[ $PROG == "x35" || $PROG == "33" || $PROG == "39" || $PROG == "40" || $PROG == "x41" ]]; then continue; fi
- echo "$I: $C -> $PROG"
- amidi -p $int -S "$(printf "C%x%02x" $C $PROG)"
+ echo "$I: $C -> $PROG1, $PROG2, $PROG3, $PROG4"
+ amidi -p $int -S "$(printf "C%x%02x" 0 $PROG1)"
+ amidi -p $int -S "$(printf "C%x%02x" 1 $PROG2)"
+ amidi -p $int -S "$(printf "C%x%02x" 2 $PROG3)"
+ amidi -p $int -S "$(printf "C%x%02x" 3 $PROG4)"
I=$(($I + 1))
#sleep 0.001