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;
// function prototypes
int create_tracks();
void AudioCallback(
ld::AudioHandle::InterleavingInputBuffer in,
ld::AudioHandle::InterleavingOutputBuffer out,
size_t size);
void midi_realtime_handler(ld::MidiEvent& msg);
struct Clock {
void advance()
struct MidiClock {
public:
void tick_advance()
{
if (enabled) {
time++;
time_inf++;
}
};
void reset()
{
time = 0;
time_inf = 0;
};
void enable(bool enabled)
@ -59,17 +50,148 @@ namespace Heck {
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:
static constexpr int PPQ = 24;
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()
{
@ -105,38 +227,21 @@ namespace Heck {
break;
}
hw.PrintLine("Creating Tracks");
create_tracks();
hw.PrintLine("Setting up MIDI");
hw.PrintLine("Initializing MIDI");
ld::MidiUartHandler::Config midi_config{};
midi.Init(midi_config);
midi.realtime_callback = &midi_realtime_handler;
init_tracks();
hw.PrintLine("Starting MIDI Receive");
midi.StartReceive();
midi.Listen();
hw.PrintLine("Starting Audio");
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
@ -163,15 +268,17 @@ namespace Heck {
event_log.PushBack(msg);
switch (msg.srt_type) {
case daisy::TimingClock:
clock.advance();
clock.tick_advance();
break;
case daisy::Start: {
sequencer.reset();
clock.reset();
clock.enable(true);
} break;
case daisy::Stop: {
clock.enable(false);
clock.reset();
sequencer.reset();
} break;
case daisy::Reset:
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()
{
while (midi.HasEvents()) {
ld::MidiEvent msg = midi.PopEvent();
event_log.PushBack(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: {
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;
}
tracks_midi_in(msg);
}
}
void sequencer_midi_handler()
{
std::vector<ld::MidiEvent> queue = sequencer.midi_out();
for (ld::MidiEvent msg : queue) {
tracks_midi_in(msg);
}
}
void mainloop()
{
u32 systick_now = ld::System::GetNow();
hw.PrintLine("Entering MainLoop");
u32 systick_now{};
u32 midi_log_systick_last{};
bool heartbeat_led_state{ false };
@ -252,16 +374,21 @@ namespace Heck {
int clock_time_new{};
int clock_time_current{};
int clock_bar_new{};
int clock_bar_current{};
int clock_16n_new{};
int clock_16n_current{};
while (1) {
// Get current values for state
// if update is different
// Update state
// handle change
systick_now = ld::System::GetNow();
clock_time_new = clock.gettime();
clock_time_new = clock.tick_infinite();
if (clock_time_current != clock_time_new) {
clock_time_current = clock_time_new;
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();
// REC
@ -281,6 +422,7 @@ namespace Heck {
} else {
hw.PrintLine("RECORDING OFF");
}
sequencer.recording = seq_recording_current;
}
if (systick_now - midi_log_systick_last > 5) {
@ -303,7 +445,7 @@ namespace Heck {
case ld::NoteOn:
case ld::NoteOff:
case ld::MidiMessageType::ControlChange: {
if (1) {
if (0) {
char outstr[256];
char type_str[32];
GetMidiTypeAsString(msg, type_str);

Loading…
Cancel
Save