// Hecks perkons extension #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" using namespace daisy; using namespace daisysp; static DaisySeed hw{}; static MidiUartHandler midi{}; static FIFO event_log{}; static float samplerate{}; static Heck::Instrument::Kick instr_kick{}; static Heck::Instrument::Noise instr_noise{}; void AudioCallback( AudioHandle::InterleavingInputBuffer in, AudioHandle::InterleavingOutputBuffer out, size_t size) { float sig{}; for (size_t i = 0; i < size; i += 2) { float kick_sig = instr_kick.nextsample(); float noise_sig = instr_noise.nextsample(); sig = .5 * noise_sig + .5 * kick_sig; sig *= 0.4; out[i] = sig; out[i + 1] = sig; } } int init_dsp_chain() { instr_kick.init(samplerate); instr_noise.init(samplerate); return 0; } int main(void) { hw.Configure(); hw.Init(); hw.StartLog(); uint32_t now = System::GetNow(); uint32_t log_time{}; bool heartbeat_led_state{ false }; uint32_t heartbeat_time{}; init_dsp_chain(); // Start Audio hw.SetAudioBlockSize(4); samplerate = hw.AudioSampleRate(); hw.StartAudio(AudioCallback); // MIDI RX 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); }; midi.StartReceive(); midi.Listen(); 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) { instr_kick.trigger(); } if (msg.channel == 1) { instr_noise.trigger(); } std::array bytes = { 0x90, 0x00, 0x00 }; bytes[1] = msg.data[0]; bytes[2] = msg.data[1]; midi.SendMessage(bytes.data(), 3); } else if (msg.type == MidiMessageType::ControlChange) { } 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; } } }