memlnaut-nisps/modes/MEMLNautModePAFSynth.hpp
chriskiefer d623adfe42 modes
2025-11-23 15:48:14 +00:00

101 lines
3.5 KiB
C++

#pragma once
#include "../src/memllib/interface/MIDIInOut.hpp"
#include "../src/memllib/hardware/memlnaut/display/XYPadView.hpp"
#include "../src/memllib/hardware/memlnaut/MEMLNaut.hpp"
#include "../PAFSynthAudioApp.hpp"
#include "MEMLNautMode.hpp"
#include <memory>
#include <array>
class MEMLNautModePAFSynth {
public:
constexpr static size_t kN_InputParams = 3; // joystick x, y, rotate
inline static PAFSynthAudioApp<> audioAppPAFSynth;
std::array<String, PAFSynthAudioApp<>::nVoiceSpaces> voiceSpaceList;
String getHelpTitle() {
return "PAF Synth Mode";
}
size_t getNParams() {
return PAFSynthAudioApp<>::kN_Params;
}
void setVoiceSpace(size_t i) {
audioAppPAFSynth.setVoiceSpace(i);
}
std::span<String> getVoiceSpaceList() {
return voiceSpaceList;
}
__force_inline stereosample_t process(stereosample_t x) {
return audioAppPAFSynth.Process(x);
}
void Setup(float sample_rate, std::shared_ptr<InterfaceBase> interface) {
audioAppPAFSynth.Setup(sample_rate, interface);
voiceSpaceList = audioAppPAFSynth.getVoiceSpaceNames();
}
__force_inline void loop() {
audioAppPAFSynth.loop();
}
std::shared_ptr<MIDIInOut> midi_interf;
void setupMIDI(std::shared_ptr<MIDIInOut> new_midi_interf) {
midi_interf = new_midi_interf;
midi_interf->SetNoteCallback([this](bool noteon, uint8_t note_number, uint8_t vel_value) {
if (noteon) {
uint8_t midimsg[2] = { note_number, vel_value };
queue_try_add(&audioAppPAFSynth.qMIDINoteOn, &midimsg);
}else{
uint8_t midimsg[2] = { note_number, vel_value };
queue_try_add(&audioAppPAFSynth.qMIDINoteOff, &midimsg);
}
// Serial.printf("MIDI Note %d: %d %d\n", note_number, vel_value, noteon);
});
// Serial.println("MIDI note callback set.");
}
void addViews() {
std::shared_ptr<XYPadView> noteTrigView = std::make_shared<XYPadView>("Play", TFT_SILVER);
// Cache MIDI notes being echoed
static bool is_playing_note = false;
static uint8_t last_note_number = 0;
noteTrigView->SetOnTouchCallback([this](float x, float y) {
// Serial.printf("Note trigger at: %.2f, %.2f\n", x, y);
// If a note is already playing, stop it
if (is_playing_note) {
midi_interf->sendNoteOff(last_note_number, 0);
is_playing_note = false;
}
uint8_t noteVel = static_cast<uint8_t>(powf(y, 0.5f) * 127.f);
uint8_t midimsg[2] = {static_cast<uint8_t>(x * 127.f), noteVel};
queue_try_add(&audioAppPAFSynth.qMIDINoteOn, &midimsg);
midi_interf->sendNoteOn(midimsg[0], midimsg[1]);
last_note_number = midimsg[0];
is_playing_note = true; // Set flag to indicate a note is playing
// Serial.printf("sending %d %d\n",midimsg[0], midimsg[1]);
});
noteTrigView->SetOnTouchReleaseCallback([this](float x, float y) {
// Serial.printf("Note release at: %.2f, %.2f\n", x, y);
uint8_t midimsg[2] = {last_note_number,0};
queue_try_add(&audioAppPAFSynth.qMIDINoteOff, &midimsg);
midi_interf->sendNoteOff(last_note_number, 0);
is_playing_note = false; // Reset flag when note is released
});
MEMLNaut::Instance()->disp->AddView(noteTrigView);
};
size_t getNMIDICtrlOutputs() {
return 16;
}
inline void processAnalysisParams(std::shared_ptr<InterfaceBase> interface) {}
};