Browse Source

YUP. added the SEQUENCER finally :)

main
heck 7 months ago
parent
commit
3268389805
  1. 328
      src/main_perkons.cc

328
src/main_perkons.cc

@ -31,27 +31,18 @@ namespace Heck {
std::array<Track, Constants::TRACK_COUNT> tracks; std::array<Track, Constants::TRACK_COUNT> tracks;
// function prototypes struct MidiClock {
int create_tracks(); public:
void tick_advance()
void AudioCallback(
ld::AudioHandle::InterleavingInputBuffer in,
ld::AudioHandle::InterleavingOutputBuffer out,
size_t size);
void midi_realtime_handler(ld::MidiEvent& msg);
struct Clock {
void advance()
{ {
if (enabled) { if (enabled) {
time++; time_inf++;
} }
}; };
void reset() void reset()
{ {
time = 0; time_inf = 0;
}; };
void enable(bool enabled) void enable(bool enabled)
@ -59,17 +50,148 @@ namespace Heck {
this->enabled = enabled; this->enabled = enabled;
}; };
int gettime() // get time
int tick_infinite()
{
return time_inf;
}
int tick_4n()
{
return time_inf % PPQ;
}
int tick_1n()
{
return time_inf % (PPQ * 4);
}
int count_8n()
{ {
return time; return std::floor(tick_1n() / 12);
}
int count_16n()
{
return std::floor(tick_1n() / 6);
}
int count_bar()
{
return std::floor(time_inf / 96.);
} }
private: private:
static constexpr int PPQ = 24;
bool enabled{ true }; bool enabled{ true };
int time{ 0 }; int time_inf{ 0 };
};
struct Sequencer {
Sequencer()
{
clear_sequence();
}
// its a MIDI CC step sequencer
constexpr static int MIDI_MAX = 127;
constexpr static int STEP_COUNT = 16;
constexpr static int TRACK_COUNT = 16;
using Step = std::array<int, MIDI_MAX>;
using Track = std::array<Step, STEP_COUNT>;
using Sequence = std::array<Track, TRACK_COUNT>;
void reset()
{
step_current = 0;
}
void next_step()
{
step_current++;
if(step_current >= STEP_COUNT) {
step_current = 0;
}
}
void clear_track(int track_nr)
{
for (int step = 0; step < STEP_COUNT; step++) {
for (int cc_nr = 0; cc_nr < MIDI_MAX; cc_nr++) {
sequence[track_nr][step][cc_nr] = -1;
}
}
}
void clear_track_cc(int track_nr, int cc_nr)
{
for (int step = 0; step < STEP_COUNT; step++) {
sequence[track_nr][step][cc_nr] = -1;
}
}
void clear_sequence()
{
for (int track = 0; track < TRACK_COUNT; track++) {
clear_track(track);
}
}
void midi_in(ld::MidiEvent& msg)
{
if (recording) {
ld::ControlChangeEvent cc = msg.AsControlChange();
sequence[cc.channel][step_current][cc.control_number] = cc.value;
}
}
std::vector<ld::MidiEvent> midi_out()
{
std::vector<ld::MidiEvent> ret{};
for (int track = 0; track < TRACK_COUNT; track++) {
for (int cc_nr = 0; cc_nr < MIDI_MAX; cc_nr++) {
int cc_val = sequence[track][step_current][cc_nr];
if (cc_val != -1) {
ld::MidiEvent ev{};
ev.channel = track;
ev.type = ld::ControlChange;
ev.data[0] = cc_nr;
ev.data[1] = cc_val;
ret.push_back(ev);
}
}
}
return ret;
}
int step_current{ 0 };
bool recording{ false };
Sequence sequence{};
}; };
Clock clock{}; MidiClock clock{};
Sequencer sequencer{};
// function prototypes
void AudioCallback(
ld::AudioHandle::InterleavingInputBuffer in,
ld::AudioHandle::InterleavingOutputBuffer out,
size_t size);
void midi_realtime_handler(ld::MidiEvent& msg);
void init_tracks()
{
tracks[0].init(instrument0);
tracks[1].init(instrument1);
tracks[2].init(instrument2);
tracks[3].init(instrument3);
}
void init() void init()
{ {
@ -105,38 +227,21 @@ namespace Heck {
break; break;
} }
hw.PrintLine("Creating Tracks"); hw.PrintLine("Initializing MIDI");
create_tracks();
hw.PrintLine("Setting up MIDI");
ld::MidiUartHandler::Config midi_config{}; ld::MidiUartHandler::Config midi_config{};
midi.Init(midi_config); midi.Init(midi_config);
midi.realtime_callback = &midi_realtime_handler; midi.realtime_callback = &midi_realtime_handler;
init_tracks();
hw.PrintLine("Starting MIDI Receive"); hw.PrintLine("Starting MIDI Receive");
midi.StartReceive(); midi.StartReceive();
midi.Listen(); midi.Listen();
hw.PrintLine("Starting Audio"); hw.PrintLine("Starting Audio");
hw.StartAudio(AudioCallback); hw.StartAudio(AudioCallback);
hw.PrintLine("Entering MainLoop");
} }
int create_tracks()
{
instrument0.init();
tracks[0].init(instrument0);
instrument1.init();
tracks[1].init(instrument1);
instrument2.init();
tracks[2].init(instrument2);
instrument3.init();
tracks[3].init(instrument3);
return 0;
}
// ============================================================================================= // =============================================================================================
// RUN // RUN
@ -163,15 +268,17 @@ namespace Heck {
event_log.PushBack(msg); event_log.PushBack(msg);
switch (msg.srt_type) { switch (msg.srt_type) {
case daisy::TimingClock: case daisy::TimingClock:
clock.advance(); clock.tick_advance();
break; break;
case daisy::Start: { case daisy::Start: {
sequencer.reset();
clock.reset(); clock.reset();
clock.enable(true); clock.enable(true);
} break; } break;
case daisy::Stop: { case daisy::Stop: {
clock.enable(false); clock.enable(false);
clock.reset(); clock.reset();
sequencer.reset();
} break; } break;
case daisy::Reset: case daisy::Reset:
break; break;
@ -180,67 +287,82 @@ namespace Heck {
} }
} }
void tracks_midi_in(ld::MidiEvent msg)
{
switch (msg.type) {
case ld::MidiMessageType::NoteOn: {
if (msg.channel >= 0 && msg.channel < Constants::TRACK_COUNT) {
tracks[msg.channel].instrument->trigger();
}
} break;
case ld::MidiMessageType::ControlChange: {
sequencer.midi_in(msg);
ld::ControlChangeEvent cc = msg.AsControlChange();
float val_normalized = cc.value / 127.;
switch (cc.control_number) {
// 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].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;
}
} break;
default: {
// Other MIDI message
} break;
}
}
void midi_async_handler() void midi_async_handler()
{ {
while (midi.HasEvents()) { while (midi.HasEvents()) {
ld::MidiEvent msg = midi.PopEvent(); ld::MidiEvent msg = midi.PopEvent();
event_log.PushBack(msg); event_log.PushBack(msg);
switch (msg.type) { tracks_midi_in(msg);
case ld::MidiMessageType::NoteOn: { }
if (msg.channel >= 0 && msg.channel < Constants::TRACK_COUNT) { }
tracks[msg.channel].instrument->trigger();
} void sequencer_midi_handler()
} break; {
case ld::MidiMessageType::ControlChange: { std::vector<ld::MidiEvent> queue = sequencer.midi_out();
ld::ControlChangeEvent cc = msg.AsControlChange(); for (ld::MidiEvent msg : queue) {
float val_normalized = cc.value / 127.; tracks_midi_in(msg);
switch (cc.control_number) {
// 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].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;
}
} break;
default: {
// Other MIDI message
} break;
}
} }
} }
void mainloop() void mainloop()
{ {
u32 systick_now = ld::System::GetNow(); hw.PrintLine("Entering MainLoop");
u32 systick_now{};
u32 midi_log_systick_last{}; u32 midi_log_systick_last{};
bool heartbeat_led_state{ false }; bool heartbeat_led_state{ false };
@ -252,16 +374,21 @@ namespace Heck {
int clock_time_new{}; int clock_time_new{};
int clock_time_current{}; int clock_time_current{};
int clock_bar_new{};
int clock_bar_current{};
int clock_16n_new{};
int clock_16n_current{};
while (1) { while (1) {
// Get current values for state // Get current values for state
// if update is different // if update is different
// Update state // Update state
// handle change // handle change
systick_now = ld::System::GetNow(); systick_now = ld::System::GetNow();
clock_time_new = clock.gettime(); clock_time_new = clock.tick_infinite();
if (clock_time_current != clock_time_new) { if (clock_time_current != clock_time_new) {
clock_time_current = clock_time_new; clock_time_current = clock_time_new;
if (0) { if (0) {
@ -269,6 +396,20 @@ namespace Heck {
} }
} }
clock_bar_new = clock.count_bar();
if (clock_bar_new != clock_bar_current) {
clock_bar_current = clock_bar_new;
hw.PrintLine("Bar: %i", clock_bar_current);
}
clock_16n_new = clock.count_16n();
if (clock_16n_new != clock_16n_current) {
clock_16n_current = clock_16n_new;
hw.PrintLine("16n: %i", clock_16n_current);
sequencer.next_step();
}
sequencer_midi_handler();
midi_async_handler(); midi_async_handler();
// REC // REC
@ -281,6 +422,7 @@ namespace Heck {
} else { } else {
hw.PrintLine("RECORDING OFF"); hw.PrintLine("RECORDING OFF");
} }
sequencer.recording = seq_recording_current;
} }
if (systick_now - midi_log_systick_last > 5) { if (systick_now - midi_log_systick_last > 5) {
@ -303,7 +445,7 @@ namespace Heck {
case ld::NoteOn: case ld::NoteOn:
case ld::NoteOff: case ld::NoteOff:
case ld::MidiMessageType::ControlChange: { case ld::MidiMessageType::ControlChange: {
if (1) { if (0) {
char outstr[256]; char outstr[256];
char type_str[32]; char type_str[32];
GetMidiTypeAsString(msg, type_str); GetMidiTypeAsString(msg, type_str);

Loading…
Cancel
Save