From 25a2729e4ab7aacf6f425b52aab31c57635b283f Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 12 Sep 2024 05:28:21 +0200 Subject: [PATCH] MIDI controls for tracks complete Move `struct Track` into own module --- src/main_perkons.cc | 113 +++++++++++++++++--------------------------- src/track.hh | 81 +++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 69 deletions(-) create mode 100644 src/track.hh diff --git a/src/main_perkons.cc b/src/main_perkons.cc index e01f1b9..a92c73d 100644 --- a/src/main_perkons.cc +++ b/src/main_perkons.cc @@ -1,10 +1,9 @@ // Hecks perkons extension #include #include -#include "daisy_seed.h" -#include "daisysp.h" #include "globals.hh" +#include "track.hh" #include "utils.hh" #include "instr_abstract.hh" #include "instr_kick.hh" @@ -14,13 +13,13 @@ namespace ld = daisy; namespace dsp = daisysp; -namespace Heck { +namespace Heck { // ============================================================================================= // INIT // ============================================================================================= + ld::DaisySeed hw{}; - static ld::DaisySeed hw{}; static ld::MidiUartHandler midi{}; static ld::FIFO event_log{}; @@ -29,55 +28,11 @@ namespace Heck { Instrument::FM instrument2{}; Instrument::Kick instrument3{}; - struct Track { - public: - void init(Instrument::AbstractInstrument& instrument) - { - instrument_.reset(&instrument); - ctl_volume_ = 1.; - // filter_.Init(); - } - - float nextsample() - { - float sig = instrument_->nextsample(); - sig = vca_(sig, ctl_volume_); - // sig = filter_.Low(); - return sig; - } - - void trigger() - { - instrument_->trigger(); - } - - void volume(float vol) - { - ctl_volume_ = vol; - } - - void filter(float freq) - { - filter_.SetFreq(freq); - } - - void drive(float amt) - { - filter_.SetDrive(amt); - } - - private: - std::shared_ptr instrument_{}; - dsp::LinearVCA vca_{}; - dsp::Svf filter_{}; - - float ctl_volume_{}; - }; - std::array tracks; // function prototypes int create_tracks(); + void AudioCallback( ld::AudioHandle::InterleavingInputBuffer in, ld::AudioHandle::InterleavingOutputBuffer out, @@ -86,14 +41,10 @@ namespace Heck { void init() { - int* npt = nullptr; - int i = *npt; - hw.Configure(); hw.Init(); - hw.StartLog(true); + hw.StartLog(); - // Start Audio hw.PrintLine("Setting Blocksize: %i", Constants::BUFFERSIZE); hw.SetAudioBlockSize(Constants::BUFFERSIZE); @@ -120,17 +71,12 @@ namespace Heck { break; } - hw.PrintLine("Creating Tracks"); create_tracks(); - hw.PrintLine("Starting Audio"); - hw.StartAudio(AudioCallback); - - // MIDI RX hw.PrintLine("Setting up MIDI"); - ld::MidiUartHandler::Config midi_config; + ld::MidiUartHandler::Config midi_config{}; midi.Init(midi_config); u32 systick_last_rt_msg{}; midi.realtime_callback = [&systick_last_rt_msg](ld::MidiEvent& msg) { @@ -155,6 +101,9 @@ namespace Heck { midi.StartReceive(); midi.Listen(); + hw.PrintLine("Starting Audio"); + hw.StartAudio(AudioCallback); + hw.PrintLine("Entering MainLoop"); } @@ -171,12 +120,10 @@ namespace Heck { return 0; } - // ============================================================================================= // RUN // ============================================================================================= - void AudioCallback( ld::AudioHandle::InterleavingInputBuffer in, ld::AudioHandle::InterleavingOutputBuffer out, @@ -187,7 +134,6 @@ namespace Heck { for (int i = 0; i < Constants::TRACK_COUNT; i++) { sig_out += tracks[i].nextsample(); } - sig_out *= 0.1; out[i] = sig_out; out[i + 1] = sig_out; @@ -205,22 +151,51 @@ namespace Heck { now = ld::System::GetNow(); while (midi.HasEvents()) { ld::MidiEvent msg = midi.PopEvent(); - event_log.PushBack(msg); if (msg.type == ld::MidiMessageType::NoteOn) { if (msg.channel >= 0 && msg.channel < Constants::TRACK_COUNT) { - tracks[msg.channel].trigger(); + tracks[msg.channel].instrument->trigger(); } } else if (msg.type == ld::MidiMessageType::ControlChange) { + event_log.PushBack(msg); ld::ControlChangeEvent cc = msg.AsControlChange(); + float val_normalized = cc.value / 127.; switch (cc.control_number) { - case Constants::MIDI_Mapping::TRACK_VOLUME: - tracks[cc.channel].volume(cc.value); + // Pots + case Constants::MIDI_Mapping::TRACK_PITCH: + tracks[cc.channel].instrument->ctl(0, val_normalized); + break; + case Constants::MIDI_Mapping::TRACK_DECAY: + tracks[cc.channel].instrument->ctl(1, val_normalized); + break; + case Constants::MIDI_Mapping::TRACK_PARAM1: + tracks[cc.channel].instrument->ctl(2, val_normalized); + break; + case Constants::MIDI_Mapping::TRACK_PARAM2: + tracks[cc.channel].instrument->ctl(3, val_normalized); break; case Constants::MIDI_Mapping::TRACK_FILTER: - tracks[cc.channel].volume(cc.value); + tracks[cc.channel].filter(val_normalized); + break; + case Constants::MIDI_Mapping::TRACK_DRIVE: + tracks[cc.channel].drive(val_normalized); + break; + case Constants::MIDI_Mapping::TRACK_VOLUME: + tracks[cc.channel].volume(val_normalized); + break; + // Switches + case Constants::MIDI_Mapping::TRACK_MODE1: + tracks[cc.channel].instrument->switch_mode1(int(val_normalized * 2.)); + break; + case Constants::MIDI_Mapping::TRACK_MODE2: + tracks[cc.channel].instrument->switch_mode2(int(val_normalized * 2.)); + break; + case Constants::MIDI_Mapping::TRACK_FILTERMODE: + tracks[cc.channel].filtermode(val_normalized); + break; + default: break; } - event_log.PushBack(msg); + } else { } } diff --git a/src/track.hh b/src/track.hh new file mode 100644 index 0000000..50b090e --- /dev/null +++ b/src/track.hh @@ -0,0 +1,81 @@ +#ifndef HECK_PERKONS_TRACK_HH +#define HECK_PERKONS_TRACK_HH + +#include "daisysp.h" +#include "instr_abstract.hh" + +namespace dsp = daisysp; + +namespace Heck { + struct Track { + public: + void init(Instrument::AbstractInstrument& instr) + { + instrument.reset(&instr); + ctl_volume_ = 0.; + + ladder_.Init(Constants::SAMPLERATE); + ladder_.SetFilterMode(daisysp::LadderFilter::FilterMode::LP24); + ladder_.SetRes(0.7); + ladder_.SetInputDrive(1.3); + + od_.Init(); + } + + float nextsample() + { + float sig = instrument->nextsample(); + sig = ladder_.Process(sig); + sig = od_.Process(sig); + sig = vca_(sig, ctl_volume_); + return sig; + } + + void volume(float vol) + { + ctl_volume_ = vol; + } + + void filter(float val) + { + float ladder_freq = 80 + (val * 9000); + ladder_.SetFreq(val * ladder_freq); + } + + void drive(float amt) + { + od_.SetDrive(0.35 + amt * 0.15); + } + + // range: 0-1 + void filtermode(float val) + { + ctl_filtermode_ = val; + + // MID + if (ctl_filtermode_ < 0.33) { + ladder_.SetFilterMode(daisysp::LadderFilter::FilterMode::BP24); + } + // HIGH + if (ctl_filtermode_ >= 0.33 && ctl_filtermode_ < 0.66) { + ladder_.SetFilterMode(daisysp::LadderFilter::FilterMode::HP24); + } + // LOW + if (ctl_filtermode_ >= 0.66) { + ladder_.SetFilterMode(daisysp::LadderFilter::FilterMode::LP24); + } + } + + std::shared_ptr instrument{}; + + private: + dsp::LinearVCA vca_{}; + dsp::LadderFilter ladder_{}; + dsp::Overdrive od_{}; + + float ctl_volume_{}; + float ctl_filtermode_{}; + }; + +} // namespace Heck +#endif \ No newline at end of file