break|| midi clock and seq control
This commit is contained in:
parent
1656e7a4a4
commit
3ddbcdfed9
5 changed files with 376 additions and 32 deletions
|
|
@ -24,11 +24,13 @@
|
||||||
#include "modes/MEMLNautModeSoundAnalysisMIDI.hpp"
|
#include "modes/MEMLNautModeSoundAnalysisMIDI.hpp"
|
||||||
#include "modes/MEMLNautModeXIASRI.hpp"
|
#include "modes/MEMLNautModeXIASRI.hpp"
|
||||||
#include "modes/MEMLNautModeBreakOr.hpp"
|
#include "modes/MEMLNautModeBreakOr.hpp"
|
||||||
|
#include "modes/MEMLNautModeVerbFX.hpp"
|
||||||
|
|
||||||
//hook up the memlnaut mode
|
//hook up the memlnaut mode
|
||||||
|
|
||||||
// #define MEMLNAUT_MODE_TYPE MEMLNautModeSoundAnalysisMIDI
|
// #define MEMLNAUT_MODE_TYPE MEMLNautModeSoundAnalysisMIDI
|
||||||
// #define MEMLNAUT_MODE_TYPE MEMLNautModeXIASRI
|
// #define MEMLNAUT_MODE_TYPE MEMLNautModeXIASRI
|
||||||
|
// #define MEMLNAUT_MODE_TYPE MEMLNautModeVerbFX
|
||||||
#define MEMLNAUT_MODE_TYPE MEMLNautModeBreakOr
|
#define MEMLNAUT_MODE_TYPE MEMLNautModeBreakOr
|
||||||
// #define MEMLNAUT_MODE_TYPE MEMLNautModeChannelStrip
|
// #define MEMLNAUT_MODE_TYPE MEMLNautModeChannelStrip
|
||||||
// #define MEMLNAUT_MODE_TYPE MEMLNautModePAFSynth
|
// #define MEMLNAUT_MODE_TYPE MEMLNautModePAFSynth
|
||||||
|
|
|
||||||
|
|
@ -26,19 +26,23 @@ struct ratioSeqState {
|
||||||
float ratioSum=1.f;
|
float ratioSum=1.f;
|
||||||
int midiNote = 36;
|
int midiNote = 36;
|
||||||
float pulseWidth = 0.5f;
|
float pulseWidth = 0.5f;
|
||||||
|
|
||||||
|
std::array<float, 2> ampRatios{1.f};
|
||||||
|
float ampRatioSum=1.f;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t seqLength>
|
template<size_t seqLength>
|
||||||
inline bool __not_in_flash_func(ratioSeq)(ratioSeqState &seq) {
|
inline bool __not_in_flash_func(ratioSeq)(float phasor, float phaseOffset, float ratioSum, const std::array<float, seqLength> &ratios, float pulseWidth) {
|
||||||
bool trig = 0;
|
bool trig = 0;
|
||||||
float offsetPhase = seq.phaseOffset + seq.phasor;
|
float offsetPhase = phaseOffset + phasor;
|
||||||
if (offsetPhase >= 1.f) {
|
if (offsetPhase >= 1.f) {
|
||||||
offsetPhase -= 1.f;
|
offsetPhase -= 1.f;
|
||||||
}
|
}
|
||||||
float phaseAdj = seq.ratioSum * offsetPhase;
|
float phaseAdj = ratioSum * offsetPhase;
|
||||||
float accumulatedSum = 0;
|
float accumulatedSum = 0;
|
||||||
float lastAccumulatedSum = 0;
|
float lastAccumulatedSum = 0;
|
||||||
for (size_t v : seq.ratios)
|
for (size_t v : ratios)
|
||||||
{
|
{
|
||||||
accumulatedSum += v;
|
accumulatedSum += v;
|
||||||
if (phaseAdj <= accumulatedSum)
|
if (phaseAdj <= accumulatedSum)
|
||||||
|
|
@ -46,7 +50,7 @@ inline bool __not_in_flash_func(ratioSeq)(ratioSeqState &seq) {
|
||||||
// check pulse width
|
// check pulse width
|
||||||
float beatPhase = (phaseAdj - lastAccumulatedSum) /
|
float beatPhase = (phaseAdj - lastAccumulatedSum) /
|
||||||
(accumulatedSum - lastAccumulatedSum);
|
(accumulatedSum - lastAccumulatedSum);
|
||||||
trig = beatPhase <= seq.pulseWidth;
|
trig = beatPhase <= pulseWidth;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lastAccumulatedSum = accumulatedSum;
|
lastAccumulatedSum = accumulatedSum;
|
||||||
|
|
@ -55,13 +59,18 @@ inline bool __not_in_flash_func(ratioSeq)(ratioSeqState &seq) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<size_t NPARAMS=50, size_t NSEQUENCES=10>
|
template<size_t NPARAMS=70, size_t NSEQUENCES=10>
|
||||||
class BreakOrAudioApp : public AudioAppBase<NPARAMS>
|
class BreakOrAudioApp : public AudioAppBase<NPARAMS>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr size_t kN_Params = NPARAMS;
|
static constexpr size_t kN_Params = NPARAMS;
|
||||||
static constexpr size_t nVoiceSpaces=0;
|
static constexpr size_t nVoiceSpaces=0;
|
||||||
|
|
||||||
|
queue_t bpmQueue;
|
||||||
|
queue_t sequencerControlQueue;
|
||||||
|
|
||||||
|
bool sequencerPlaying = false;
|
||||||
|
|
||||||
std::shared_ptr<MIDIInOut> midiIO;
|
std::shared_ptr<MIDIInOut> midiIO;
|
||||||
|
|
||||||
std::array<VoiceSpace<NPARAMS>, nVoiceSpaces> voiceSpaces;
|
std::array<VoiceSpace<NPARAMS>, nVoiceSpaces> voiceSpaces;
|
||||||
|
|
@ -84,6 +93,8 @@ public:
|
||||||
|
|
||||||
BreakOrAudioApp() : AudioAppBase<NPARAMS>() {
|
BreakOrAudioApp() : AudioAppBase<NPARAMS>() {
|
||||||
// currentVoiceSpace = voiceSpaces[0].mappingFunction;
|
// currentVoiceSpace = voiceSpaces[0].mappingFunction;
|
||||||
|
queue_init(&bpmQueue, sizeof(float), 1);
|
||||||
|
queue_init(&sequencerControlQueue, sizeof(int), 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool __force_inline euclidean(float phase, const size_t n, const size_t k, const size_t offset, const float pulseWidth)
|
bool __force_inline euclidean(float phase, const size_t n, const size_t k, const size_t offset, const float pulseWidth)
|
||||||
|
|
@ -102,31 +113,41 @@ public:
|
||||||
|
|
||||||
stereosample_t __force_inline Process(const stereosample_t x) override
|
stereosample_t __force_inline Process(const stereosample_t x) override
|
||||||
{
|
{
|
||||||
if (sequencingSampleCounter==0) {
|
if (sequencerPlaying) {
|
||||||
for(auto &seq: ratioSeqStates) {
|
midiClockPhasor += midiClockPhasorInc;
|
||||||
//update phasor
|
if (midiClockPhasor >= 1.f) {
|
||||||
seq.phasor += (seq.phasorInc * seq.phasorMul);
|
midiClockPhasor -= 1.f;
|
||||||
if (seq.phasor >= 1.f) {
|
midiIO->queueClock();
|
||||||
seq.phasor -= 1.f;
|
midiIO->flushQueue();
|
||||||
}
|
}
|
||||||
bool trig = ratioSeq<3>(seq);
|
if (sequencingSampleCounter==0) {
|
||||||
if (trig && !seq.lastTrig) {
|
for(auto &seq: ratioSeqStates) {
|
||||||
if (trig) {
|
//update phasor
|
||||||
midiIO->queueNoteOn(seq.midiNote, 127);
|
seq.phasor += (seq.phasorInc * seq.phasorMul);
|
||||||
}else{
|
if (seq.phasor >= 1.f) {
|
||||||
midiIO->queueNoteOff(seq.midiNote, 0);
|
seq.phasor -= 1.f;
|
||||||
}
|
}
|
||||||
}
|
bool trig = ratioSeq<3>(seq.phasor, seq.phaseOffset, seq.ratioSum, seq.ratios, seq.pulseWidth);
|
||||||
seq.lastTrig = trig;
|
bool highAmp = ratioSeq<2>(seq.phasor, seq.phaseOffset, seq.ampRatioSum, seq.ampRatios, 0.5f);
|
||||||
|
if (trig && !seq.lastTrig) {
|
||||||
|
if (trig) {
|
||||||
|
midiIO->queueNoteOn(seq.midiNote, highAmp ? 127 : 64);
|
||||||
|
}else{
|
||||||
|
midiIO->queueNoteOff(seq.midiNote, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seq.lastTrig = trig;
|
||||||
|
}
|
||||||
|
midiIO->flushQueue();
|
||||||
}
|
}
|
||||||
midiIO->flushQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
sequencingSampleCounter ++;
|
sequencingSampleCounter ++;
|
||||||
if (sequencingSampleCounter >= sequencingSampleDiv) {
|
if (sequencingSampleCounter >= sequencingSampleDiv) {
|
||||||
sequencingSampleCounter = 0;
|
sequencingSampleCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
stereosample_t ret { 0.f,0.f };
|
stereosample_t ret { 0.f,0.f };
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -155,18 +176,50 @@ public:
|
||||||
void ProcessParams(const std::array<float, NPARAMS>& params)
|
void ProcessParams(const std::array<float, NPARAMS>& params)
|
||||||
{
|
{
|
||||||
firstParamsReceived = true;
|
firstParamsReceived = true;
|
||||||
|
if (queue_try_remove(&bpmQueue, &bpm)) {
|
||||||
|
bpm = 30.f + (bpm * 200.f); // Scale BPM from [0,1] to [30,230]
|
||||||
|
updateBPM(bpm);
|
||||||
|
}
|
||||||
|
int sequencerControl;
|
||||||
|
if (queue_try_remove(&sequencerControlQueue, &sequencerControl)) {
|
||||||
|
sequencerPlaying = sequencerControl == 1;
|
||||||
|
if (!sequencerPlaying) {
|
||||||
|
midiIO->queueClockStop();
|
||||||
|
// Send note offs for all sequences when stopping
|
||||||
|
for(auto &seq: ratioSeqStates) {
|
||||||
|
midiIO->queueNoteOff(seq.midiNote, 0);
|
||||||
|
seq.phasor = 0.f; // Reset phasor to start when stopping
|
||||||
|
}
|
||||||
|
midiIO->flushQueue();
|
||||||
|
midiClockPhasor = 0.f; // Reset MIDI clock phasor when stopping
|
||||||
|
sequencingSampleCounter = 0; // Reset sequencing sample counter
|
||||||
|
|
||||||
|
}else{
|
||||||
|
midiIO->queueClockStart();
|
||||||
|
midiIO->flushQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
// currentVoiceSpace(params);
|
// currentVoiceSpace(params);
|
||||||
size_t paramIdx = 0;
|
size_t paramIdx = 0;
|
||||||
for(auto &v: ratioSeqStates) {
|
for(auto &v: ratioSeqStates) {
|
||||||
float sum=0.f;
|
float sum=0.f;
|
||||||
for(size_t i=0; i < v.ratios.size(); i++) {
|
for(size_t i=0; i < v.ratios.size(); i++) {
|
||||||
v.ratios[i] = (float)(int)(params[paramIdx++] * 7.f) + 1.f;
|
v.ratios[i] = (float)(int)(params[paramIdx++] * 3.f) + 1.f;
|
||||||
sum += v.ratios[i];
|
sum += v.ratios[i];
|
||||||
}
|
}
|
||||||
v.ratioSum = sum;
|
v.ratioSum = sum;
|
||||||
static float muls[7] = {0.25f, 0.33f, 0.5f, 1.f, 1.5f, 2.f, 3.f};
|
// static float muls[7] = {0.25f, 0.33f, 0.5f, 1.f, 1.5f, 2.f, 3.f};
|
||||||
v.phasorMul = muls[(int)(params[paramIdx++] * 6.999999f)];
|
// v.phasorMul = muls[(int)(params[paramIdx++] * 6.999999f)];
|
||||||
|
static float muls[4] = {0.5f, 1.f, 2.f, 4.f};
|
||||||
|
v.phasorMul = muls[(int)(params[paramIdx++] * 3.999999f)];
|
||||||
v.phaseOffset = ((int)(params[paramIdx++] * timeSigBeats)) * timeSigBeatsInv;
|
v.phaseOffset = ((int)(params[paramIdx++] * timeSigBeats)) * timeSigBeatsInv;
|
||||||
|
|
||||||
|
sum=0.f;
|
||||||
|
for(size_t i=0; i < v.ampRatios.size(); i++) {
|
||||||
|
v.ampRatios[i] = (float)(int)(params[paramIdx++] * 3.f) + 1.f;
|
||||||
|
sum += v.ampRatios[i];
|
||||||
|
}
|
||||||
|
v.ampRatioSum = sum;
|
||||||
}
|
}
|
||||||
// Serial.printf("pm: %f", ratioSeqStates[0].phasorMul);
|
// Serial.printf("pm: %f", ratioSeqStates[0].phasorMul);
|
||||||
|
|
||||||
|
|
@ -181,6 +234,9 @@ public:
|
||||||
for(auto &v: ratioSeqStates) {
|
for(auto &v: ratioSeqStates) {
|
||||||
v.phasorInc = barPhasorInc;
|
v.phasorInc = barPhasorInc;
|
||||||
}
|
}
|
||||||
|
float midiClockLengthInSeconds = beatLengthInSeconds / 24.f;
|
||||||
|
float midiClockLengthInSamples = midiClockLengthInSeconds * sampleRatef;
|
||||||
|
midiClockPhasorInc = 1.f / midiClockLengthInSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTimeSignature(float beats, float division) {
|
void setTimeSignature(float beats, float division) {
|
||||||
|
|
@ -206,6 +262,9 @@ protected:
|
||||||
|
|
||||||
std::array<ratioSeqState, NSEQUENCES> ratioSeqStates;
|
std::array<ratioSeqState, NSEQUENCES> ratioSeqStates;
|
||||||
|
|
||||||
|
float midiClockPhasor=0;
|
||||||
|
float midiClockPhasorInc=0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __BREAKOR_AUDIO_APP_HPP__
|
#endif // __BREAKOR_AUDIO_APP_HPP__
|
||||||
|
|
|
||||||
169
modes/AudioApps/VerbFXAudioApp.hpp
Normal file
169
modes/AudioApps/VerbFXAudioApp.hpp
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
#ifndef __VERBFX_AUDIO_APP_HPP__
|
||||||
|
#define __VERBFX_AUDIO_APP_HPP__
|
||||||
|
|
||||||
|
#include "../../src/memllib/audio/AudioAppBase.hpp" // Added missing include
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
//#include "src/memllib/interface/InterfaceBase.hpp" // Added missing include
|
||||||
|
|
||||||
|
#include <span>
|
||||||
|
#include "../../voicespaces/VoiceSpaces.hpp"
|
||||||
|
#include "../../src/memllib/synth/OnePoleSmoother.hpp"
|
||||||
|
#include "../../src/memllib/synth/maximilian.h"
|
||||||
|
#include "../../src/daisysp/Effects/pitchshifter.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t NPARAMS=24>
|
||||||
|
class VerbFXAudioApp : public AudioAppBase<NPARAMS>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr size_t kN_Params = NPARAMS;
|
||||||
|
static constexpr size_t nVoiceSpaces=1;
|
||||||
|
|
||||||
|
|
||||||
|
std::array<VoiceSpace<NPARAMS>, nVoiceSpaces> voiceSpaces;
|
||||||
|
|
||||||
|
VoiceSpaceFn<NPARAMS> currentVoiceSpace;
|
||||||
|
|
||||||
|
std::array<String, nVoiceSpaces> getVoiceSpaceNames() {
|
||||||
|
std::array<String, nVoiceSpaces> names;
|
||||||
|
for(size_t i=0; i < voiceSpaces.size(); i++) {
|
||||||
|
names[i] = voiceSpaces[i].name;
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVoiceSpace(size_t i) {
|
||||||
|
if (i < voiceSpaces.size()) {
|
||||||
|
currentVoiceSpace = voiceSpaces[i].mappingFunction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VerbFXAudioApp() : AudioAppBase<NPARAMS>() {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((hot)) stereosample_t __force_inline Process(const stereosample_t x) override
|
||||||
|
{
|
||||||
|
float mix = x.L + x.R;
|
||||||
|
mix *= 2.0f;
|
||||||
|
|
||||||
|
smoother.Process(neuralNetOutputs.data(), smoothParams.data());
|
||||||
|
|
||||||
|
float dl1mix = smoothParams[0] * 0.4f;
|
||||||
|
float dl2mix = smoothParams[1] * 0.4f;
|
||||||
|
float dl3mix = smoothParams[2] * 0.8f;
|
||||||
|
float dl4mix = smoothParams[22] * smoothParams[22] * 0.41f;
|
||||||
|
|
||||||
|
float allp1fb = smoothParams[4] * 0.99f;
|
||||||
|
float allp2fb = smoothParams[5] * 0.99f;
|
||||||
|
float comb1fb = (smoothParams[6] * 0.95f);
|
||||||
|
float comb2fb = (smoothParams[7] * 0.95f);
|
||||||
|
|
||||||
|
float dl1fb = (smoothParams[8] * 0.95f);
|
||||||
|
float dl2fb = (smoothParams[9] * 0.95f);
|
||||||
|
float dl3fb = (smoothParams[10] * 0.95f);
|
||||||
|
float dl4fb = (smoothParams[23] * 0.95f);
|
||||||
|
// Wet-dry mix between 0.2 and 1
|
||||||
|
wetdry_mix_ = (smoothParams[11] * 0.7f) + 0.3f;
|
||||||
|
// Pitch shift transposition between -12 and +12 semitones
|
||||||
|
// float pitchshift_transpose = (smoothParams[12] * 24.f) - 12.f; // Scale to -12 to +12 semitones
|
||||||
|
pitchshifter_.SetTransposition(12.f + smoothParams[12]);
|
||||||
|
//pitchshifter_.SetTransposition(-5.f);
|
||||||
|
// Set pitch shifter mix
|
||||||
|
pitchshifter_mix_ = smoothParams[13] * 0.99f;
|
||||||
|
|
||||||
|
float allp3fb = smoothParams[14] * 0.99f;
|
||||||
|
float allp4fb = smoothParams[15] * 0.99f;
|
||||||
|
float allp5fb = smoothParams[16] * 0.99f;
|
||||||
|
float allp6fb = smoothParams[17] * 0.99f;
|
||||||
|
float allp3fbmix = smoothParams[18];
|
||||||
|
float allp4fbmix = smoothParams[19];
|
||||||
|
float allp5fbmix = smoothParams[20];
|
||||||
|
float allp6fbmix = smoothParams[21];
|
||||||
|
|
||||||
|
// // PROCESS
|
||||||
|
float pitchshifted = pitchshifter_.Process(mix);
|
||||||
|
// // Mix the original signal with the pitch-shifted signal
|
||||||
|
pitchshifted = (mix * (1.f - pitchshifter_mix_)) + (pitchshifted * pitchshifter_mix_);
|
||||||
|
|
||||||
|
float y = dcb.play(pitchshifted, 0.99f) * 2.f;
|
||||||
|
// float y = dcb.play(pitchshifted, 0.99f) * 3.f;
|
||||||
|
float y1 = allp1.allpass(y, 30, allp1fb);
|
||||||
|
y1 = comb1.combfb(y1, 127, comb1fb);
|
||||||
|
|
||||||
|
float y2 = allp2.allpass(y, 482, allp2fb);
|
||||||
|
y2 = comb2.combfb(y2, 808, comb2fb);
|
||||||
|
|
||||||
|
float y3 = allp3.allpass(y, 19, allp3fb) * allp3fbmix;
|
||||||
|
float y4 = allp4.allpass(y, 69, allp4fb) * allp4fbmix;
|
||||||
|
float y5 = allp5.allpass(y, 131, allp5fb) * allp5fbmix;
|
||||||
|
float y6 = allp6.allpass(y, 287, allp6fb) * allp6fbmix;
|
||||||
|
y = y1 + y2 + y3 + y4 +y5 +y6;
|
||||||
|
float d1 = (dl1.play(y, 3500, dl1fb) * dl1mix);
|
||||||
|
float d2 = (dl2.play(y, 7886, dl2fb) * dl2mix);
|
||||||
|
float d3 = (dl3.play(y, 299, dl3fb) * dl3mix);
|
||||||
|
float d4 = (dl4.play(y, 15873, dl4fb) * dl4mix);
|
||||||
|
|
||||||
|
|
||||||
|
y = y + d1 + d2 + d3;
|
||||||
|
|
||||||
|
// Mix dry
|
||||||
|
y = (y * wetdry_mix_) + (mix * (1.f - wetdry_mix_));
|
||||||
|
|
||||||
|
y = tanhf(y*1.2f);
|
||||||
|
|
||||||
|
stereosample_t ret { y, y };
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Setup(float sample_rate, std::shared_ptr<InterfaceBase> interface) override
|
||||||
|
{
|
||||||
|
AudioAppBase<NPARAMS>::Setup(sample_rate, interface);
|
||||||
|
maxiSettings::sampleRate = sample_rate;
|
||||||
|
pitchshifter_.Init(sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline)) void ProcessParams(const std::array<float, NPARAMS>& params)
|
||||||
|
{
|
||||||
|
// currentVoiceSpace(params);
|
||||||
|
neuralNetOutputs = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::array<float,NPARAMS> neuralNetOutputs{0}, smoothParams{0};
|
||||||
|
|
||||||
|
|
||||||
|
maxiDelayline<5000> dl1;
|
||||||
|
maxiDelayline<8000> dl2;
|
||||||
|
maxiDelayline<1201> dl3;
|
||||||
|
maxiDelayline<16000> dl4;
|
||||||
|
|
||||||
|
maxiReverbFilters<300> allp1;
|
||||||
|
maxiReverbFilters<500> allp2;
|
||||||
|
maxiReverbFilters<500> allp3;
|
||||||
|
maxiReverbFilters<500> allp4;
|
||||||
|
maxiReverbFilters<500> allp5;
|
||||||
|
maxiReverbFilters<500> allp6;
|
||||||
|
maxiReverbFilters<200> comb1;
|
||||||
|
maxiReverbFilters<900> comb2;
|
||||||
|
|
||||||
|
maxiDCBlocker dcb;
|
||||||
|
|
||||||
|
daisysp::PitchShifter pitchshifter_;
|
||||||
|
float pitchshifter_mix_{0.5f};
|
||||||
|
float wetdry_mix_{0.5f};
|
||||||
|
|
||||||
|
OnePoleSmoother<kN_Params> smoother{150.f, kSampleRate};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -22,10 +22,36 @@ public:
|
||||||
InterfaceRL interface;
|
InterfaceRL interface;
|
||||||
std::shared_ptr<InterfaceRL> interfacePtr;
|
std::shared_ptr<InterfaceRL> interfacePtr;
|
||||||
|
|
||||||
|
bool sequencerPlaying = false;
|
||||||
|
|
||||||
void setupInterface() {
|
void setupInterface() {
|
||||||
interface.setup(kN_InputParams, BreakOrAudioApp<>::kN_Params);
|
interface.setup(kN_InputParams, BreakOrAudioApp<>::kN_Params);
|
||||||
interface.bindInterface(InterfaceRL::INPUT_MODES::JOYSTICK, true);
|
interface.bindInterface(InterfaceRL::INPUT_MODES::JOYSTICK, true);
|
||||||
interfacePtr = make_non_owning(interface);
|
interfacePtr = make_non_owning(interface);
|
||||||
|
|
||||||
|
MEMLNaut::Instance()->setTogA2Callback([this](bool state) { // scr_ref no longer captured directly
|
||||||
|
Serial.println(state ? "TogA2 ON" : "TogA2 OFF");
|
||||||
|
if (state) {
|
||||||
|
sequencerPlaying = !sequencerPlaying;
|
||||||
|
queue_try_add(&audioAppBreakOr.sequencerControlQueue, &sequencerPlaying);
|
||||||
|
}
|
||||||
|
|
||||||
|
// //tiggle up
|
||||||
|
// if (state) {
|
||||||
|
// //store output
|
||||||
|
// savedAction = action;
|
||||||
|
// actionBeingDragged=true;
|
||||||
|
// msgView->post("Where do you want it?");
|
||||||
|
// }else{
|
||||||
|
// //button up
|
||||||
|
// if (actionBeingDragged) {
|
||||||
|
// this->storeExperience(1.f, controlInput, savedAction);
|
||||||
|
// actionBeingDragged=false;
|
||||||
|
// msgView->post("Here!");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String getHelpTitle() {
|
String getHelpTitle() {
|
||||||
|
|
@ -40,6 +66,11 @@ public:
|
||||||
audioAppBreakOr.Setup(sample_rate, interfacePtr);
|
audioAppBreakOr.Setup(sample_rate, interfacePtr);
|
||||||
voiceSpaceList = audioAppBreakOr.getVoiceSpaceNames();
|
voiceSpaceList = audioAppBreakOr.getVoiceSpaceNames();
|
||||||
audioAppBreakOr.setupMIDI(midi_interf);
|
audioAppBreakOr.setupMIDI(midi_interf);
|
||||||
|
MEMLNaut::Instance()->setRVGain1Callback([this](float value) {
|
||||||
|
// Serial.printf("Volume control: %f\n", value);
|
||||||
|
queue_try_add(&audioAppBreakOr.bpmQueue, &value);
|
||||||
|
}, 0); // Set threshold to 0 to trigger on any change
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__force_inline void loop() {
|
__force_inline void loop() {
|
||||||
|
|
|
||||||
83
modes/MEMLNautModeVerbFX.hpp
Normal file
83
modes/MEMLNautModeVerbFX.hpp
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../src/memllib/interface/MIDIInOut.hpp"
|
||||||
|
#include "./AudioApps/VerbFXAudioApp.hpp"
|
||||||
|
#include "MEMLNautMode.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include <array>
|
||||||
|
#include "../XiasriAnalysis.hpp"
|
||||||
|
#include "../src/memllib/utils/sharedMem.hpp"
|
||||||
|
#include "../src/memllib/audio/AudioDriver.hpp"
|
||||||
|
#include "../src/memllib/examples/InterfaceRL.hpp"
|
||||||
|
#include "../src/memllib/PicoDefs.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MEMLNautModeVerbFX {
|
||||||
|
public:
|
||||||
|
constexpr static size_t kN_InputParams = XiasriAnalysis::kN_Params; //ML
|
||||||
|
InterfaceRL interface;
|
||||||
|
std::shared_ptr<InterfaceRL> interfacePtr;
|
||||||
|
XiasriAnalysis mlAnalysis{kSampleRate};
|
||||||
|
SharedBuffer<float, XiasriAnalysis::kN_Params> machine_list_buffer;
|
||||||
|
|
||||||
|
VerbFXAudioApp<> audioAppVerbFX;
|
||||||
|
std::shared_ptr<MIDIInOut> midi_interf;
|
||||||
|
|
||||||
|
void setupInterface() {
|
||||||
|
interface.setup(kN_InputParams, VerbFXAudioApp<>::kN_Params);
|
||||||
|
interface.bindInterface(InterfaceRL::INPUT_MODES::MACHINE_LISTENING);
|
||||||
|
interfacePtr = make_non_owning(interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getHelpTitle() {
|
||||||
|
return "VerbFX Mode";
|
||||||
|
}
|
||||||
|
|
||||||
|
__force_inline stereosample_t process(stereosample_t x) {
|
||||||
|
return audioAppVerbFX.Process(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupMIDI(std::shared_ptr<MIDIInOut> new_midi_interf) {
|
||||||
|
midi_interf = new_midi_interf;
|
||||||
|
midi_interf->Setup(0);
|
||||||
|
midi_interf->SetMIDISendChannel(1);
|
||||||
|
interface.bindMIDI(midi_interf, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addViews() {
|
||||||
|
};
|
||||||
|
|
||||||
|
void setupAudio(float sample_rate) {
|
||||||
|
audioAppVerbFX.Setup(sample_rate, interfacePtr);
|
||||||
|
// Reinitialize XiasriAnalysis filters after maxiSettings is properly configured
|
||||||
|
mlAnalysis.ReinitFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
__force_inline void loop() {
|
||||||
|
audioAppVerbFX.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
__force_inline void analyse(stereosample_t x) {
|
||||||
|
union {
|
||||||
|
XiasriAnalysis::parameters_t p;
|
||||||
|
float v[XiasriAnalysis::kN_Params];
|
||||||
|
} param_u;
|
||||||
|
param_u.p = mlAnalysis.Process(x.L + x.R);
|
||||||
|
// Write params into shared_buffer
|
||||||
|
machine_list_buffer.writeNonBlocking(param_u.v, XiasriAnalysis::kN_Params);
|
||||||
|
}
|
||||||
|
|
||||||
|
__force_inline void processAnalysisParams() {
|
||||||
|
// Read SharedBuffer
|
||||||
|
std::vector<float> mlist_params(XiasriAnalysis::kN_Params, 0);
|
||||||
|
machine_list_buffer.readNonBlocking(mlist_params);
|
||||||
|
// Send parameters to RL interface
|
||||||
|
interface.readAnalysisParameters(mlist_params);
|
||||||
|
// PERIODIC_RUN(
|
||||||
|
// Serial.printf("%f %f %f\n", mlist_params[0], mlist_params[1], mlist_params[2]);
|
||||||
|
// , 100);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue