MIDI Note Input

This commit is contained in:
chriskiefer 2025-06-20 09:01:03 +01:00
parent 9308af9b84
commit f697d71aac
3 changed files with 70 additions and 12 deletions

View file

@ -1,4 +1,5 @@
// #include "src/memllib/interface/InterfaceBase.hpp" // #include "src/memllib/interface/InterfaceBase.hpp"
#include "src/memllib/interface/MIDIInOut.hpp"
#include "display.hpp" #include "display.hpp"
#include "src/memllib/audio/AudioAppBase.hpp" #include "src/memllib/audio/AudioAppBase.hpp"
#include "src/memllib/audio/AudioDriver.hpp" #include "src/memllib/audio/AudioDriver.hpp"
@ -32,6 +33,9 @@ uint32_t get_rosc_entropy_seed(int bits) {
// Global objects // Global objects
std::shared_ptr<InterfaceRL> APP_SRAM RLInterface; std::shared_ptr<InterfaceRL> APP_SRAM RLInterface;
std::shared_ptr<MIDIInOut> APP_SRAM midi_interf;
std::shared_ptr<PAFSynthAudioApp> __scratch_y("audio") audio_app; std::shared_ptr<PAFSynthAudioApp> __scratch_y("audio") audio_app;
// Inter-core communication // Inter-core communication
@ -41,6 +45,7 @@ volatile bool APP_SRAM serial_ready = false;
volatile bool APP_SRAM interface_ready = false; volatile bool APP_SRAM interface_ready = false;
// We're only bound to the joystick inputs (x, y, rotate) // We're only bound to the joystick inputs (x, y, rotate)
constexpr size_t kN_InputParams = 3; constexpr size_t kN_InputParams = 3;
@ -87,6 +92,22 @@ void setup()
RLInterface->bind_RL_interface(scr); RLInterface->bind_RL_interface(scr);
Serial.println("Bound RL interface to MEMLNaut."); Serial.println("Bound RL interface to MEMLNaut.");
midi_interf = std::make_shared<MIDIInOut>();
midi_interf->Setup(0);
midi_interf->SetMIDISendChannel(1);
Serial.println("MIDI setup complete.");
if (midi_interf) {
midi_interf->SetNoteCallback([RLInterface] (bool noteon, uint8_t note_number, uint8_t vel_value) {
if (noteon) {
uint8_t midimsg[2] = {note_number, vel_value };
queue_try_add(&audio_app->qMIDINoteOn, &midimsg);
}
Serial.printf("MIDI Note %d: %d\n", note_number, vel_value);
});
Serial.println("MIDI note callback set.");
}
WRITE_VOLATILE(core_0_ready, true); WRITE_VOLATILE(core_0_ready, true);
while (!READ_VOLATILE(core_1_ready)) { while (!READ_VOLATILE(core_1_ready)) {
@ -115,6 +136,7 @@ void loop()
// Un-blink LED // Un-blink LED
digitalWrite(33, LOW); digitalWrite(33, LOW);
} }
midi_interf->Poll();
delay(10); // Add a small delay to avoid flooding the serial output delay(10); // Add a small delay to avoid flooding the serial output
} }

View file

@ -23,10 +23,10 @@ stereosample_t PAFSynthAudioApp::Process(const stereosample_t x)
// const float trig = pulse.square(1); // const float trig = pulse.square(1);
paf0.play(x1, 1, arpFreq, arpFreq + (paf0_cf * arpFreq), paf0_bw * arpFreq, paf0_vib, paf0_vfr, paf0_shift, 0); paf0.play(x1, 1, baseFreq, baseFreq + (paf0_cf * baseFreq), paf0_bw * baseFreq, paf0_vib, paf0_vfr, paf0_shift, 0);
float y = x1[0]; float y = x1[0];
const float freq1 = arpFreq * detune; const float freq1 = baseFreq * detune;
paf1.play(x1, 1, freq1, freq1 + (paf1_cf * freq1), paf1_bw * freq1, paf1_vib, paf1_vfr, paf1_shift, 1); paf1.play(x1, 1, freq1, freq1 + (paf1_cf * freq1), paf1_bw * freq1, paf1_vib, paf1_vfr, paf1_shift, 1);
y += x1[0]; y += x1[0];
@ -36,18 +36,20 @@ stereosample_t PAFSynthAudioApp::Process(const stereosample_t x)
paf2.play(x1, 1, freq2, freq2 + (paf2_cf * freq2), paf2_bw * freq2, paf2_vib, paf2_vfr, paf2_shift, 1); paf2.play(x1, 1, freq2, freq2 + (paf2_cf * freq2), paf2_bw * freq2, paf2_vib, paf2_vfr, paf2_shift, 1);
y += x1[0]; y += x1[0];
const float ph = phasorOsc.phasor(1); // const float ph = phasorOsc.phasor(1);
const bool euclidNewNote = euclidean(ph, 12, euclidN, 0, 0.1f); // const bool euclidNewNote = euclidean(ph, 12, euclidN, 0, 0.1f);
// y = y * 0.3f; // y = y * 0.3f;
// const float envamp = env.play(counter==0); // const float envamp = env.play(counter==0);
// const float envamp = line.play(counter==0); // const float envamp = line.play(counter==0);
if(zxdetect.onZX(euclidNewNote)) { if(newNote) {
envamp=0.2f; // if(zxdetect.onZX(euclidNewNote)) {
freqIndex++; newNote = false;
if(freqIndex >= 4) { envamp=0.8f;
freqIndex = 0; // freqIndex++;
} // if(freqIndex >= 4) {
arpFreq = frequencies[freqIndex]; // freqIndex = 0;
// }
// arpFreq = frequencies[freqIndex];
}else{ }else{
constexpr float envdec = 0.2f/9000.f; constexpr float envdec = 0.2f/9000.f;
envamp -= envdec; envamp -= envdec;
@ -71,6 +73,8 @@ stereosample_t PAFSynthAudioApp::Process(const stereosample_t x)
// Serial.println(envamp); // Serial.println(envamp);
// }) // })
y *= noteVel;
float d1 = (dl1.play(y, 3500, 0.8f) * dl1mix); float d1 = (dl1.play(y, 3500, 0.8f) * dl1mix);
// float d2 = (dl2.play(y, 15000, 0.8f) * dl2mix); // float d2 = (dl2.play(y, 15000, 0.8f) * dl2mix);
y = y + d1;// + d2; y = y + d1;// + d2;
@ -83,6 +87,8 @@ void PAFSynthAudioApp::Setup(float sample_rate, std::shared_ptr<InterfaceBase> i
{ {
AudioAppBase::Setup(sample_rate, interface); AudioAppBase::Setup(sample_rate, interface);
maxiSettings::sampleRate = sample_rate; maxiSettings::sampleRate = sample_rate;
paf0.init(); paf0.init();
paf0.setsr(maxiSettings::getSampleRate(), 1); paf0.setsr(maxiSettings::getSampleRate(), 1);
// paf0.freq(100, 0); // paf0.freq(100, 0);
@ -118,10 +124,32 @@ void PAFSynthAudioApp::Setup(float sample_rate, std::shared_ptr<InterfaceBase> i
// line.prepare(1.f,0.f,100.f,false); // line.prepare(1.f,0.f,100.f,false);
// line.triggerEnable(true); // line.triggerEnable(true);
envamp=1.f; envamp=1.f;
queue_init(&qMIDINoteOn, sizeof(uint8_t)*2, 1);
} }
float mtof(uint8_t note) {
// Convert MIDI note to frequency
return 440.0f * powf(2.0f, (note - 69) / 12.0f);
}
void PAFSynthAudioApp::loop(){
AudioAppBase::loop();
uint8_t midimsg[2];
if (firstParamsReceived && queue_try_remove(&qMIDINoteOn, &midimsg)) {
// Serial.printf("PAFSynthAudioApp::ProcessParams - Received MIDI Note On: %d, Velocity: %d\n", midimsg[0], midimsg[1]);
baseFreq = mtof(midimsg[0]);
noteVel = midimsg[1] / 127.0f; // Normalize velocity to [0, 1]
noteVel = noteVel * noteVel; // Square the velocity for more pronounced effect
newNote = true;
}
}
void PAFSynthAudioApp::ProcessParams(const std::vector<float>& params) void PAFSynthAudioApp::ProcessParams(const std::vector<float>& params)
{ {
firstParamsReceived = true;
// // Map parameters to the synth // // Map parameters to the synth
// synth_.mapParameters(params); // synth_.mapParameters(params);
// //Serial.print("Params processed."); // //Serial.print("Params processed.");

View file

@ -31,6 +31,9 @@ public:
void ProcessParams(const std::vector<float>& params) override; void ProcessParams(const std::vector<float>& params) override;
queue_t qMIDINoteOn, qMIDINoteOff;
void loop() override;
protected: protected:
maxiPAFOperator paf0; maxiPAFOperator paf0;
@ -79,7 +82,7 @@ protected:
float arpFreq=50; float arpFreq=50;
maxiLine line; maxiLine line;
float envamp; float envamp=0.f;
float detune = 1.0; float detune = 1.0;
@ -88,6 +91,11 @@ protected:
size_t euclidN=4; size_t euclidN=4;
float baseFreq = 50.0f; // Base frequency for the synth
bool newNote=false;
float noteVel = 0.f;
bool firstParamsReceived = false;
}; };
#endif // __PAF_SYNTH_AUDIO_APP_HPP__ #endif // __PAF_SYNTH_AUDIO_APP_HPP__