You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.3 KiB
159 lines
4.3 KiB
// Hecks perkons extension
|
|
#include <map>
|
|
#include <array>
|
|
#include <memory>
|
|
#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<MidiEvent, 128> event_log{};
|
|
|
|
Heck::Instrument::Noise instrument0{};
|
|
Heck::Instrument::FM instrument1{};
|
|
Heck::Instrument::FM instrument2{};
|
|
Heck::Instrument::Kick instrument3{};
|
|
|
|
std::array<std::shared_ptr<PerkonsInstrumentInterface>, 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<PerkonsInstrumentInterface>(&instrument0);
|
|
instrument1.init(samplerate);
|
|
tracks[1] = std::shared_ptr<PerkonsInstrumentInterface>(&instrument1);
|
|
instrument2.init(samplerate);
|
|
tracks[2] = std::shared_ptr<PerkonsInstrumentInterface>(&instrument2);
|
|
instrument3.init(samplerate);
|
|
tracks[3] = std::shared_ptr<PerkonsInstrumentInterface>(&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;
|
|
}
|
|
}
|
|
}
|