Skip to content

Commit

Permalink
Switch to template-based applet decl; simplify audio pipelines for ap…
Browse files Browse the repository at this point in the history
…plets; unbreak T3.2
  • Loading branch information
qiemem committed Jul 16, 2024
1 parent 5827ffb commit 0990bad
Show file tree
Hide file tree
Showing 11 changed files with 331 additions and 266 deletions.
3 changes: 3 additions & 0 deletions software/res/progname.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@
extras += "_flipped"

env.Replace(PROGNAME=f"o_C-phazerville-{version}{extras}-{git_rev}")

# include toolchain paths in compiledb for clangd lsp
env.Replace(COMPILATIONDB_INCLUDE_TOOLCHAIN=True)
128 changes: 102 additions & 26 deletions software/src/APP_HEMISPHERE.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@
#include "HSClockManager.h"

#include "hemisphere_config.h"
#include <optional>
#ifdef ARDUINO_TEENSY41
#include "AudioSetup.h"
#include "AudioPassthrough.h"
#endif

// The settings specify the selected applets, and 64 bits of data for each applet,
// plus 64 bits of data for the ClockSetup applet (which includes some misc config).
Expand Down Expand Up @@ -82,9 +86,9 @@ class HemispherePreset : public SystemExclusiveHandler,
return (h == LEFT_HEMISPHERE) ? values_[HEMISPHERE_SELECTED_LEFT_ID]
: values_[HEMISPHERE_SELECTED_RIGHT_ID];
}
HemisphereApplet* GetApplet(int h) {
HemisphereApplet& GetApplet(int h) {
int idx = HS::get_applet_index_by_id( GetAppletId(h) );
return HS::available_applets[idx].instance[h];
return HS::available_applets[idx]->GetInstance(h);
}
void SetAppletId(int h, int id) {
apply_value(h, id);
Expand Down Expand Up @@ -263,11 +267,11 @@ class HemisphereManager : public HSApplication {
for (int h = 0; h < 2; h++)
{
int index = my_applet[h];
if (hem_active_preset->GetAppletId(HEM_SIDE(h)) != HS::available_applets[index].id)
if (hem_active_preset->GetAppletId(HEM_SIDE(h)) != HS::available_applets[index]->id)
doSave = 1;
hem_active_preset->SetAppletId(HEM_SIDE(h), HS::available_applets[index].id);
hem_active_preset->SetAppletId(HEM_SIDE(h), HS::available_applets[index]->id);

uint64_t data = HS::available_applets[index].instance[h]->OnDataRequest();
uint64_t data = HS::available_applets[index]->GetInstance(h).OnDataRequest();
if (data != applet_data[h]) doSave = 1;
applet_data[h] = data;
hem_active_preset->SetData(HEM_SIDE(h), data);
Expand Down Expand Up @@ -315,7 +319,7 @@ class HemisphereManager : public HSApplication {
int index = HS::get_applet_index_by_id( hem_active_preset->GetAppletId(h) );
applet_data[h] = hem_active_preset->GetData(HEM_SIDE(h));
SetApplet(HEM_SIDE(h), index);
HS::available_applets[index].instance[h]->OnDataReceive(applet_data[h]);
HS::available_applets[index]->GetInstance(h).OnDataReceive(applet_data[h]);
}


Expand All @@ -324,18 +328,83 @@ class HemisphereManager : public HSApplication {
PokePopup(PRESET_POPUP);
}

HemisphereApplet& GetApplet(HEM_SIDE hemisphere) {
return HS::available_applets[my_applet[hemisphere]]->GetInstance(hemisphere);
}

#ifdef ARDUINO_TEENSY41
void UpdateAudioPipeline() {
AudioNoInterrupts();
HemisphereApplet& left_applet = GetApplet(HEM_SIDE::LEFT_HEMISPHERE);
HemisphereApplet& right_applet = GetApplet(HEM_SIDE::RIGHT_HEMISPHERE);

for (int i=0; i < 3; i++) for (int j=0; j < 2; j++) conns[i][j].disconnect();

AudioStream& in = OC::AudioDSP::input_stream();
AudioStream& out = OC::AudioDSP::output_stream();

auto lin = left_applet.InputStream();
auto lout = left_applet.OutputStream();

auto rin = right_applet.InputStream();
auto rout = right_applet.OutputStream();

// Rules:
// - If both sides are mono, left applet controls left pipeline, right controls right
// - If one side is mono and the other stereo, the stereo effectively becomes mono
// - If one side is stereo and the other none, the stereo applet controls both channels
// - If both are stereo, left pipeline feeds into right

// Wire up left channel
if (left_applet.NumAudioChannels() > 0) {
conns[0][0].connect(in, 0, lin.value(), 0);
if (right_applet.NumAudioChannels() == 2 && left_applet.NumAudioChannels() == 2) {
conns[1][0].connect(lout.value(), 0, rin.value(), 0);
conns[2][0].connect(rout.value(), 0, out, 0);
} else {
conns[1][0].connect(lout.value(), 0, out, 0);
}
} else if (right_applet.NumAudioChannels() == 2) {
conns[0][0].connect(in, 0, rin.value(), 0);
conns[1][0].connect(rout.value(), 0, out, 0);
} else {
conns[0][0]. connect(in, 0, out, 0);
}

// Wire up right channel
if (right_applet.NumAudioChannels() == 1) {
conns[0][1].connect(in, 1, rin.value(), 0);
conns[1][1].connect(rout.value(), 0, out, 1);
} else if (left_applet.NumAudioChannels() == 2) {
conns[0][1].connect(in, 1, lin.value(), 1);
if (right_applet.NumAudioChannels() == 2) {
conns[1][1].connect(lout.value(), 1, rin.value(), 1);
conns[2][1].connect(rout.value(), 1, out, 1);
} else {
conns[1][1].connect(lout.value(), 1, out, 1);
}
} else if (right_applet.NumAudioChannels() == 2) {
conns[0][1].connect(in, 1, rin.value(), 1);
conns[1][1].connect(rout.value(), 1, out, 1);
} else {
conns[0][1].connect(in, 1, out, 1);
}
AudioInterrupts();
}
#endif

// does not modify the preset, only the manager
void SetApplet(HEM_SIDE hemisphere, int index) {
serial_printf("SetApplet(%d, %d)\n", hemisphere, index);
#ifdef ARDUINO_TEENSY41
AudioNoInterrupts();
HS::available_applets[my_applet[hemisphere]].instance[hemisphere]->DisconnectAudio();
const uint8_t last_channels = GetApplet(hemisphere).NumAudioChannels();
#endif
next_applet[hemisphere] = my_applet[hemisphere] = index;
HS::available_applets[index].instance[hemisphere]->BaseStart(hemisphere);
HemisphereApplet& selected_applet = HS::available_applets[index]->GetInstance(hemisphere);
selected_applet.BaseStart(hemisphere);

#ifdef ARDUINO_TEENSY41
HS::available_applets[index].instance[hemisphere]->ConnectAudio(OC::AudioDSP::input_stream(), OC::AudioDSP::output_stream());
AudioInterrupts();
if (selected_applet.NumAudioChannels() > 0 || selected_applet.NumAudioChannels() != last_channels)
UpdateAudioPipeline();
#endif
}

Expand Down Expand Up @@ -417,7 +486,7 @@ class HemisphereManager : public HSApplication {
int index = my_applet[h];

// MIDI signals mixed with inputs to applets
if (HS::available_applets[index].id != 150) // not MIDI In
if (HS::available_applets[index]->id != 150) // not MIDI In
{
ForEachChannel(ch) {
int chan = h*2 + ch;
Expand All @@ -442,7 +511,7 @@ class HemisphereManager : public HSApplication {
}
}
}
HS::available_applets[index].instance[h]->BaseController();
HS::available_applets[index]->GetInstance(h).BaseController();
}

#ifdef ARDUINO_TEENSY41
Expand Down Expand Up @@ -502,7 +571,7 @@ class HemisphereManager : public HSApplication {
}
else if (help_hemisphere > -1) {
int index = my_applet[help_hemisphere];
HS::available_applets[index].instance[help_hemisphere]->BaseView();
HS::available_applets[index]->GetInstance(help_hemisphere).BaseView();
draw_applets = false;
}
}
Expand All @@ -511,7 +580,7 @@ class HemisphereManager : public HSApplication {
for (int h = 0; h < 2; h++)
{
int index = my_applet[h];
HS::available_applets[index].instance[h]->BaseView();
HS::available_applets[index]->GetInstance(h).BaseView();
}

if (HS::clock_m.IsRunning()) {
Expand Down Expand Up @@ -558,7 +627,7 @@ class HemisphereManager : public HSApplication {
} else if (!clock_setup) {
// regular applets get button release
int index = my_applet[h];
HS::available_applets[index].instance[h]->OnButtonPress();
HS::available_applets[index]->GetInstance(h).OnButtonPress();
}
}

Expand Down Expand Up @@ -651,11 +720,11 @@ class HemisphereManager : public HSApplication {
// -- button release
if (!clock_setup) {
const int index = my_applet[hemisphere];
HemisphereApplet* applet = HS::available_applets[index].instance[hemisphere];
HemisphereApplet& applet = HS::available_applets[index]->GetInstance(hemisphere);

if (applet->EditMode()) {
if (applet.EditMode()) {
// select button becomes aux button while editing a param
applet->AuxButton();
applet.AuxButton();
} else {
// Select Mode
if (hemisphere == select_mode) select_mode = -1; // Exit Select Mode if same button is pressed
Expand Down Expand Up @@ -691,7 +760,7 @@ class HemisphereManager : public HSApplication {
ChangeApplet(HEM_SIDE(h), event.value);
} else {
int index = my_applet[h];
HS::available_applets[index].instance[h]->OnEncoderMove(event.value);
HS::available_applets[index]->GetInstance(h).OnEncoderMove(event.value);
}
}

Expand Down Expand Up @@ -721,12 +790,12 @@ class HemisphereManager : public HSApplication {
void SetHelpScreen(int hemisphere) {
if (help_hemisphere > -1) { // Turn off the previous help screen
int index = my_applet[help_hemisphere];
HS::available_applets[index].instance[help_hemisphere]->ToggleHelpScreen();
HS::available_applets[index]->GetInstance(help_hemisphere).ToggleHelpScreen();
}

if (hemisphere > -1) { // Turn on the next hemisphere's screen
int index = my_applet[hemisphere];
HS::available_applets[index].instance[hemisphere]->ToggleHelpScreen();
HS::available_applets[index]->GetInstance(hemisphere).ToggleHelpScreen();
}

help_hemisphere = hemisphere;
Expand Down Expand Up @@ -789,6 +858,13 @@ class HemisphereManager : public HSApplication {
int config_page = 0;
int dummy_count = 0;

#ifdef ARDUINO_TEENSY41
// default audio streams for applets so non-audio applets don't need their
// own.
AudioPassthrough<2> passthroughs[2];
AudioConnection conns[3][2]; // input_to_left, left_to_right, right_to_output
#endif

OC::menu::ScreenCursor<5> showhide_cursor;

int help_hemisphere; // Which of the hemispheres (if any) is in help mode, or -1 if none
Expand Down Expand Up @@ -1067,7 +1143,7 @@ class HemisphereManager : public HSApplication {
++current, y += LineH) {

gfxIcon(1, y + 1, HS::applet_is_hidden(current) ? CHECK_OFF_ICON : CHECK_ON_ICON);
gfxPrint( 11, y + 2, HS::available_applets[current].instance[0]->applet_name());
gfxPrint( 11, y + 2, HS::available_applets[current]->GetInstance(0).applet_name());

if (current == showhide_cursor.cursor_pos())
gfxInvert(0, y, 127, LineH - 1);
Expand Down Expand Up @@ -1146,9 +1222,9 @@ class HemisphereManager : public HSApplication {
if (!hem_presets[i].is_valid())
gfxPrint(18, y, "(empty)");
else {
gfxPrint(18, y, hem_presets[i].GetApplet(0)->applet_name());
gfxPrint(18, y, hem_presets[i].GetApplet(0).applet_name());
gfxPrint(", ");
gfxPrint(hem_presets[i].GetApplet(1)->applet_name());
gfxPrint(hem_presets[i].GetApplet(1).applet_name());
}

y += 10;
Expand Down
Loading

0 comments on commit 0990bad

Please sign in to comment.