// Hecks perkons extension #include #include #include #include "daisy_seed.h" #include "daisysp.h" #include "types.hh" #include "utils.hh" #include "perkons_instrument_interface.hh" #include "instr_kick.hh" #include "instr_noise.hh" #include "instr_fm.hh" #define TRACK_COUNT 4 using namespace daisy; using namespace daisysp; static DaisySeed hw{}; static MidiUartHandler midi{}; static FIFO event_log{}; Heck::Instrument::Noise instrument0{}; Heck::Instrument::FM instrument1{}; Heck::Instrument::FM instrument2{}; Heck::Instrument::Kick instrument3{}; std::array, TRACK_COUNT> tracks{}; void AudioCallback( AudioHandle::InterleavingInputBuffer in, AudioHandle::InterleavingOutputBuffer out, size_t size) { float sig_out{}; for (size_t i = 0; i < size; i += 2) { for (int i = 0; i < TRACK_COUNT; i++) { sig_out += tracks[i]->nextsample(); } sig_out *= 0.1; out[i] = sig_out; out[i + 1] = sig_out; } } int create_tracks(float samplerate) { instrument0.init(samplerate); tracks[0] = std::shared_ptr(&instrument0); instrument1.init(samplerate); tracks[1] = std::shared_ptr(&instrument1); instrument2.init(samplerate); tracks[2] = std::shared_ptr(&instrument2); instrument3.init(samplerate); tracks[3] = std::shared_ptr(&instrument3); return 0; } int main(void) { int* npt = nullptr; int i = *npt; hw.Configure(); hw.Init(); hw.StartLog(true); uint32_t now = System::GetNow(); uint32_t log_time{}; bool heartbeat_led_state{ false }; uint32_t heartbeat_time{}; // Start Audio hw.SetAudioBlockSize(4); float samplerate = hw.AudioSampleRate(); hw.PrintLine("Creating Tracks"); create_tracks(samplerate); hw.PrintLine("Starting Audio"); hw.StartAudio(AudioCallback); // MIDI RX hw.PrintLine("Setting up MIDI"); MidiUartHandler::Config midi_config; midi.Init(midi_config); uint32_t systick_last_rt_msg{}; midi.realtime_callback = [&systick_last_rt_msg](MidiEvent& msg) { uint32_t systick_now = System::GetNow(); uint32_t systick_since_last = systick_now - systick_last_rt_msg; systick_last_rt_msg = systick_now; char outstr[128]; char rttype_str[32]; GetMidiRTTypeAsString(msg, rttype_str); // sprintf( // outstr, // "RT: systick: %i\ttimedelta: %i\ttype: %s\n", // (unsigned int)systick_now, // (unsigned int)systick_since_last, // rttype_str); // hw.PrintLine("%s", outstr); }; hw.PrintLine("Starting MIDI Receive"); midi.StartReceive(); midi.Listen(); hw.PrintLine("Entering MainLoop"); while (1) { now = System::GetNow(); while (midi.HasEvents()) { MidiEvent msg = midi.PopEvent(); event_log.PushBack(msg); if (msg.type == MidiMessageType::NoteOn) { if (msg.channel >= 0 && msg.channel < TRACK_COUNT) { tracks[msg.channel]->trigger(); } } else if (msg.type == MidiMessageType::ControlChange) { // ControlChangeEvent cc = msg.AsControlChange(); event_log.PushBack(msg); } else { } } if (now - log_time > 5) { log_time = now; if (!event_log.IsEmpty()) { auto msg = event_log.PopFront(); char outstr[128]; char type_str[32]; GetMidiTypeAsString(msg, type_str); sprintf( outstr, "time-last:\t%ld\ttype: %s\tChannel: %d\tData MSB: " "%d\tData LSB: %d\n", now, type_str, msg.channel, msg.data[0], msg.data[1]); hw.PrintLine(outstr); } } if (now - heartbeat_time > 500) { heartbeat_time = now; hw.SetLed(heartbeat_led_state); heartbeat_led_state = !heartbeat_led_state; } } }