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