diff --git a/README.md b/README.md
index 6d54c22..6a072b2 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,11 @@
ChangeLog
````
+== 2024-12-14
+ * Bugfix/Enchancement
+ * SEQ triggered & trig-input triggered engines were not in sync
+ * V_OCT/Scale parameter, semitones from active quantizer (#117)
+ * Claps less RAM usage
== 2024-12-07
* Bugfix:
* EnvFollower - IO-page AUX input
diff --git a/app/DRUMS/Claps.bin b/app/DRUMS/Claps.bin
index 60d8492..57604aa 100644
Binary files a/app/DRUMS/Claps.bin and b/app/DRUMS/Claps.bin differ
diff --git a/app/DRUMS/Claps.cpp b/app/DRUMS/Claps.cpp
index 9921c47..28d81ef 100644
--- a/app/DRUMS/Claps.cpp
+++ b/app/DRUMS/Claps.cpp
@@ -28,8 +28,6 @@
#include "lib/drumsynth/drumsynth_claps.h"
#include "lib/misc/noise.hxx"
-float tmp[FRAME_BUFFER_SIZE];
-float tmp2[FRAME_BUFFER_SIZE];
static constexpr size_t n = 8;
DrumSynth _instA = nullptr;
@@ -80,25 +78,66 @@ void engine::setup()
// unpack
const uint8_t *p = packed_drumKit;
p += 4;
- for (size_t i = 0; i < inst_count; i++)
+ for (size_t i = 0; i < packed_drumKit[0]; i++)
{
inst[i].name = reinterpret_cast(p);
p += 12;
- inst[i].n = p[0];
- p += 4;
- inst[i].part = reinterpret_cast(p);
- p += inst[i].n * sizeof(PartArgs);
+
+ inst[i].n = *reinterpret_cast(p);
+ p += sizeof(inst[i].n);
+
+ PartArgs *part = new PartArgs[inst[i].n]{};
+ inst[i].part = part;
+
+ for (int j = 0; j < inst[i].n; j++)
+ {
+ part->flags = *reinterpret_cast(p);
+ p += sizeof(part->flags);
+
+ part->osc = *reinterpret_cast(p);
+ p += sizeof(part->osc);
+
+ part->osc_pitch.n = *reinterpret_cast(p);
+ p += sizeof(part->osc_pitch.n);
+ part->osc_pitch.xy = reinterpret_cast(p);
+ p += sizeof(EnvXY) * 16;
+
+ part->osc_amp.n = *reinterpret_cast(p);
+ p += sizeof(part->osc_amp.n);
+ part->osc_amp.xy = reinterpret_cast(p);
+ p += sizeof(EnvXY) * 16;
+
+ part->vca.n = *reinterpret_cast(p);
+ p += sizeof(part->vca.n);
+ part->vca.xy = reinterpret_cast(p);
+ p += sizeof(EnvXY) * 16;
+
+ part->bq1 = *reinterpret_cast(p);
+ p += sizeof(BiquadArgs);
+
+ part->bq2 = *reinterpret_cast(p);
+ p += sizeof(BiquadArgs);
+
+ part->ws.n = *reinterpret_cast(p);
+ p += sizeof(part->ws.n);
+ part->ws.xy = reinterpret_cast(p);
+ p += sizeof(WS_XY) * 8;
+
+ part->level = *reinterpret_cast(p);
+ p += sizeof(part->level);
+ part++;
+ }
}
engine::addParam("Color", &pitch, 0.5f, 1.5f);
char *tmp = inst_name_buff;
- for (int i = 0; i < LEN_OF(inst_names); i++)
+ for (int i = 0; i < (inst_count + LEN_OF(seeds)); i++)
{
inst_names[i] = tmp;
tmp += sprint_inst_name(tmp, i) + 1;
}
- engine::addParam("Clap", &inst_selection, 0, LEN_OF(inst_names) - 1, inst_names);
+ engine::addParam("Clap", &inst_selection, 0, (inst_count + LEN_OF(seeds)) - 1, inst_names);
engine::addParam("Decay", &stretch, 0.1f, 2.0f);
engine::addParam("Stereo", &stereo);
// param[0].init("Crispy", &crispy, crispy, -1.1f, 1.1f);
@@ -191,6 +230,8 @@ void engine::process()
auto bufferAux = engine::outputBuffer<1>();
memset(buffer, 0, sizeof(float) * FRAME_BUFFER_SIZE);
memset(bufferAux, 0, sizeof(float) * FRAME_BUFFER_SIZE);
+ float tmpL[FRAME_BUFFER_SIZE];
+ float tmpR[FRAME_BUFFER_SIZE];
if (engine::trig())
{
@@ -218,30 +259,30 @@ void engine::process()
{
if (stereo > 0.01f && _cur_inst.part[k].osc.type >= OSC_METALLIC)
{
- drum_synth_process_frame(_instA, k, (f - (f * 0.01f * stereo)), ¶ms, tmp, FRAME_BUFFER_SIZE);
- drum_synth_process_frame(_instB, k, (f + (f * 0.01f * stereo)), ¶ms, tmp2, FRAME_BUFFER_SIZE);
+ drum_synth_process_frame(_instA, k, (f - (f * 0.01f * stereo)), ¶ms, tmpL, tmpL, FRAME_BUFFER_SIZE);
+ drum_synth_process_frame(_instB, k, (f + (f * 0.01f * stereo)), ¶ms, tmpR, tmpR, FRAME_BUFFER_SIZE);
if (_cur_inst.part[k].osc.type == OSC_METALLIC)
{
for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
{
- buffer[i] += tmp[i];
- bufferAux[i] += tmp2[i];
+ buffer[i] += tmpL[i];
+ bufferAux[i] += tmpR[i];
}
}
else
for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
{
- buffer[i] += tmp[i];
- bufferAux[i] += tmp[i] * b + tmp2[i] * a;
+ buffer[i] += tmpL[i];
+ bufferAux[i] += tmpL[i] * b + tmpR[i] * a;
}
}
else
{
- drum_synth_process_frame(_instA, k, f, ¶ms, tmp, FRAME_BUFFER_SIZE);
+ drum_synth_process_frame(_instA, k, f, ¶ms, tmpL, tmpR, FRAME_BUFFER_SIZE);
for (int i = 0; i < FRAME_BUFFER_SIZE; i++)
{
- buffer[i] += tmp[i];
- bufferAux[i] += tmp[i];
+ buffer[i] += tmpL[i];
+ bufferAux[i] += tmpR[i];
}
}
// bufferAux[i] += p._vca.value() * p._amp.value() * 0.99f;
diff --git a/app/squares-and-circles-api.h b/app/squares-and-circles-api.h
index de5dc07..671ee16 100644
--- a/app/squares-and-circles-api.h
+++ b/app/squares-and-circles-api.h
@@ -127,6 +127,7 @@ EXTERN_C
extern uint8_t *__mixer_level;
extern uint8_t *__mixer_pan;
+ extern uint32_t *__multi_trigs_mask;
extern float **__audio_in_l_fpp;
extern float **__audio_in_r_fpp;
diff --git a/app/upload.py b/app/upload.py
index 0f996b8..4cdb779 100755
--- a/app/upload.py
+++ b/app/upload.py
@@ -172,7 +172,7 @@ def get_appid(binfile):
engine["crc32"] = "%x" % crc32sum
engines.append(engine)
print("NEW ->", file, engine)
- continue
+ #continue
#exit(0)
elif engine["crc32"] == "%x" % crc32sum:
onext = int(engine["addr"], 16) + int(engine["size"])
diff --git a/lib/braids/quantizer.cc b/lib/braids/quantizer.cc
index 84083a9..7477132 100644
--- a/lib/braids/quantizer.cc
+++ b/lib/braids/quantizer.cc
@@ -38,6 +38,8 @@ void Quantizer::Init() {
codeword_ = 0;
previous_boundary_ = 0;
next_boundary_ = 0;
+ last_note = 64;
+ num_notes_ = 12;
for (int16_t i = 0; i < 128; ++i) {
codebook_[i] = (i - 64) << 7;
}
@@ -56,7 +58,12 @@ void Quantizer::Configure(
int16_t span,
size_t num_notes) {
enabled_ = notes != NULL && num_notes != 0 && span != 0;
+ num_notes_ = num_notes;
if (enabled_) {
+ codeword_ = 0;
+ previous_boundary_ = 0;
+ next_boundary_ = 0;
+ last_note = 64;
int32_t octave = 0;
size_t note = 0;
int16_t root = 0;
diff --git a/lib/braids/quantizer.h b/lib/braids/quantizer.h
index bb78720..3367ed1 100644
--- a/lib/braids/quantizer.h
+++ b/lib/braids/quantizer.h
@@ -62,6 +62,10 @@ class Quantizer {
bool enabled();
+ size_t NumNotes() {
+ return num_notes_;
+ }
+
private:
int8_t last_note;
bool enabled_;
@@ -69,6 +73,7 @@ class Quantizer {
int32_t codeword_;
int32_t previous_boundary_;
int32_t next_boundary_;
+ size_t num_notes_;
DISALLOW_COPY_AND_ASSIGN(Quantizer);
};
diff --git a/lib/drumsynth/drumsynth.cpp b/lib/drumsynth/drumsynth.cpp
index b45654a..ef3f98b 100644
--- a/lib/drumsynth/drumsynth.cpp
+++ b/lib/drumsynth/drumsynth.cpp
@@ -106,6 +106,11 @@ class Envelope
}
}
+ inline bool finished()
+ {
+ return pos_ != 0 && pos_ == len_;
+ }
+
inline float value()
{
return value_;
@@ -183,7 +188,10 @@ class Oscillator
inline void Sine(float &out)
{
- out = stmlib::Interpolate(plaits::lut_sine + 256, osc.phase_, 1024.0f);
+ // #define PI_F 3.1415927410125732421875f
+ // out = sinf((0.25f + osc.phase_) * PI_F * 2.f);
+
+ out = stmlib::Interpolate(plaits::lut_sine + 128, osc.phase_, 512.0f);
osc.phase_ += phase_inc_;
if (osc.phase_ > 1.0f)
@@ -207,6 +215,9 @@ struct drum_synth_Part
Biquad biquad1 = {};
Biquad biquad2 = {};
+ std::pair biquad1b;
+ std::pair biquad2b;
+
const PartArgs *part;
float amp = 0.4380016479995117f;
@@ -284,16 +295,23 @@ struct drum_synth_Part
uint32_t last_f = 0;
- inline void process_frame(float f, uint32_t t, float stretch, float *out, size_t size)
+ inline void process_frame(float f, const DrumParams *params, float *outL, float *outR, size_t size)
{
+ uint32_t t = params->t;
float osc = 0;
+ float osc2 = 0;
uint32_t ff = f * SAMPLE_RATE;
+ // if (t > 0 && this->_amp.finished() && this->_vca.finished())
+ // {
+ // return;
+ // }
+
while (size--)
{
- this->_amp.process(t, stretch);
- this->_vca.process(t, stretch);
- this->_pitch.process(t, stretch);
+ this->_amp.process(t, params->decay);
+ this->_vca.process(t, params->decay);
+ this->_pitch.process(t, params->decay);
++t;
@@ -307,8 +325,14 @@ struct drum_synth_Part
{
case OSC_NOISE1:
case OSC_NOISE2:
- osc = this->noise.nextf(-1, 1);
- break;
+ {
+ float a = this->noise.nextf(-1, 1);
+ float b = this->noise.nextf(-1, 1);
+ float st = 0.5f - (params->stereo / 2);
+ osc = (a * (1 - st) + b * st);
+ osc2 = (b * (1 - st) + a * st);
+ }
+ break;
case OSC_METALLIC:
osc = 0;
@@ -374,6 +398,33 @@ struct drum_synth_Part
if (part->bq2.mode < BIQUAD_NOTCH)
osc *= part->bq2.g;
}
+
+ if (params->stereo > 0 && (part->osc.type == OSC_NOISE1 || part->osc.type == OSC_NOISE2))
+ {
+ osc2 *= amp;
+ osc2 *= this->_amp.value();
+
+ if (part->bq1.mode)
+ {
+ osc2 = this->biquad1.process(osc2, this->biquad1b.first, this->biquad1b.second);
+ if (part->bq1.mode < BIQUAD_NOTCH)
+ osc2 *= part->bq1.g;
+ }
+
+ if (part->ws.n)
+ osc = waveshaper_transform(osc);
+
+ if (part->bq2.mode)
+ {
+ osc2 = this->biquad2.process(osc2, this->biquad2b.first, this->biquad2b.second);
+ if (part->bq2.mode < BIQUAD_NOTCH)
+ osc2 *= part->bq2.g;
+ }
+ }
+ else
+ {
+ osc2 = osc;
+ }
}
else if (part->flags & BIQUAD_PARALLEL)
{
@@ -383,7 +434,8 @@ struct drum_synth_Part
osc = this->biquad2.process(osc) * part->bq2.g;
}
- *out++ = osc * this->_vca.value() * part->level;
+ *outL++ = osc * this->_vca.value() * part->level;
+ *outR++ = osc2 * this->_vca.value() * part->level;
}
last_f = ff;
@@ -423,11 +475,11 @@ extern "C" void drum_synth_reset(DrumSynth inst)
}
}
}
-extern "C" void drum_synth_process_frame(DrumSynth inst, int part, float freq, const DrumParams *params, float *out, size_t size)
+extern "C" void drum_synth_process_frame(DrumSynth inst, int part, float freq, const DrumParams *params, float *outL, float *outR, size_t size)
{
if (inst)
{
auto _part = (drum_synth_Part *)&inst[1];
- _part[part].process_frame(freq, params->t, params->decay, out, size);
+ _part[part].process_frame(freq, params, outL, outR, size);
}
}
\ No newline at end of file
diff --git a/lib/drumsynth/drumsynth.h b/lib/drumsynth/drumsynth.h
index 7708079..da35c7b 100644
--- a/lib/drumsynth/drumsynth.h
+++ b/lib/drumsynth/drumsynth.h
@@ -38,10 +38,22 @@ struct EnvXY
struct EnvArgs
{
int32_t n;
- EnvXY xy[16];
+ const EnvXY *xy; //[16];
};
-enum BiquadMode
+struct WS_XY
+{
+ float x;
+ float y;
+};
+
+struct WSArgs
+{
+ uint32_t n;
+ const WS_XY *xy; //[8];
+};
+
+enum BiquadMode : uint32_t
{
BIQUAD_THRU = 0,
BIQUAD_LP,
@@ -61,7 +73,7 @@ struct BiquadArgs
float g;
};
-enum OscType
+enum OscType : uint32_t
{
OSC_NONE = 0,
OSC_SINE = 1,
@@ -85,7 +97,7 @@ struct OscArgs
uint32_t n;
};
-enum PartFlags
+enum PartFlags : uint32_t
{
BIQUAD_SERIAL = 1 << 1,
BIQUAD_PARALLEL = 1 << 2,
@@ -93,30 +105,22 @@ enum PartFlags
struct PartArgs
{
- uint32_t flags;
+ PartFlags flags;
OscArgs osc;
EnvArgs osc_pitch;
EnvArgs osc_amp;
EnvArgs vca;
BiquadArgs bq1;
BiquadArgs bq2;
- struct
- {
- uint32_t n;
- struct _
- {
- float x;
- float y;
- } xy[8];
- } ws;
+ WSArgs ws;
float level;
};
struct DrumModel
{
- const char* name;
+ const char *name;
size_t n;
- const PartArgs* part;
+ const PartArgs *part;
};
struct DrumParams
@@ -124,6 +128,7 @@ struct DrumParams
uint32_t t;
float attack;
float decay;
+ float stereo;
};
struct DrumKit
@@ -137,6 +142,6 @@ typedef uint32_t *DrumSynth;
extern "C"
{
DrumSynth drum_synth_init(const DrumModel *inst, void *(*malloc)(size_t size));
- void drum_synth_process_frame(DrumSynth inst, int part, float freq, const DrumParams *params, float *out, size_t size);
+ void drum_synth_process_frame(DrumSynth inst, int part, float freq, const DrumParams *params, float *outL, float *outR, size_t size);
void drum_synth_reset(DrumSynth inst);
}
\ No newline at end of file
diff --git a/lib/misc/Biquad.h b/lib/misc/Biquad.h
index 7e12ed2..765910a 100644
--- a/lib/misc/Biquad.h
+++ b/lib/misc/Biquad.h
@@ -42,7 +42,7 @@ class Biquad
void setPeakGain(float peakGainDB);
void setBiquad(int type, float Fc, float Q, float peakGainDB);
float process(float in);
-
+ float process(float in, float& z1, float& z2);
protected:
void calcBiquad(void);
@@ -74,4 +74,22 @@ inline float Biquad::process(float in)
// return y;
}
+inline float Biquad::process(float in, float& _z1, float& _z2)
+{
+ float out = in * a0 + _z1;
+ _z1 = in * a1 + _z2 - b1 * out;
+ _z2 = in * a2 - b2 * out;
+ return out;
+
+ // float x = in;
+ // float y = a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2;
+
+ // x2 = x1;
+ // x1 = x;
+ // y2 = y1;
+ // y1 = y;
+
+ // return y;
+}
+
#endif // Biquad_h
diff --git a/platformio.ini b/platformio.ini
index 03f42d8..8adc2e0 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -9,5 +9,5 @@
[env:squares-and-circles]
apps_json = ./app/index.json
-squares_and_circles_loader = 5e1e08e ; minimum loader version
+squares_and_circles_loader = 18c0102 ; minimum loader version
platform = .pio/
\ No newline at end of file