Add base audio + asio implementation

This commit is contained in:
2026-03-03 02:55:38 -05:00
parent b523e233cb
commit 7e298faadd
4 changed files with 680 additions and 1 deletions

View File

@@ -5,6 +5,7 @@
#include "platform/platform.h"
#include "renderer/renderer.h"
#include "midi/midi.h"
#include "audio/audio.h"
#include "ui/ui_core.h"
#include "ui/ui_theme.h"
#include "ui/ui_widgets.h"
@@ -16,6 +17,7 @@
#include "platform/platform_win32.cpp"
#include "renderer/renderer_dx12.cpp"
#include "midi/midi_win32.cpp"
#include "audio/audio_asio.cpp"
#include "menus.cpp"
////////////////////////////////
@@ -49,6 +51,7 @@ struct AppState {
PlatformWindow *window;
Renderer *renderer;
MidiEngine *midi;
AudioEngine *audio;
UI_Context *ui;
S32 last_w, last_h;
B32 show_browser;
@@ -77,6 +80,10 @@ struct AppState {
S32 settings_theme_sel;
B32 settings_vsync;
B32 settings_autosave;
// Audio device selection
S32 audio_device_sel; // dropdown index: 0 = None, 1+ = device
S32 audio_device_prev; // previous selection for change detection
};
////////////////////////////////
@@ -490,6 +497,80 @@ static void settings_window_content(void *user_data) {
ui_checkbox("SettingsVsync", "V-Sync", &app->settings_vsync);
ui_checkbox("SettingsAutosave", "Autosave", &app->settings_autosave);
// Separator
CLAY(CLAY_ID("SettingsSep1"),
.layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(1) },
.padding = { 0, 0, 6, 6 } },
.backgroundColor = g_theme.border
) {}
// Audio device dropdown
ui_label("SettingsLblAudio", "Audio Device");
static const char *audio_options[AUDIO_MAX_DEVICES + 1];
int32_t audio_count = audio_get_device_count(app->audio);
audio_options[0] = "None";
for (int32_t i = 0; i < audio_count && i < AUDIO_MAX_DEVICES; i++) {
AudioDeviceInfo *dev = audio_get_device(app->audio, i);
audio_options[i + 1] = dev ? dev->name : "???";
}
CLAY(CLAY_ID("SettingsAudioWrap"),
.layout = { .sizing = { .width = CLAY_SIZING_FIXED(220), .height = CLAY_SIZING_FIT() } }
) {
ui_dropdown("SettingsAudio", audio_options, audio_count + 1, &app->audio_device_sel);
}
// Handle device selection change
if (app->audio_device_sel != app->audio_device_prev) {
audio_close_device(app->audio);
if (app->audio_device_sel > 0) {
audio_open_device(app->audio, app->audio_device_sel - 1);
}
app->audio_device_prev = app->audio_device_sel;
}
// Test tone button + status
CLAY(CLAY_ID("SettingsAudioBtnRow"),
.layout = {
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
.childGap = 8,
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}
) {
bool device_open = (app->audio_device_sel > 0);
bool tone_playing = audio_is_test_tone_playing(app->audio);
if (device_open && !tone_playing) {
if (ui_button("BtnTestTone", "Play Test Tone")) {
audio_play_test_tone(app->audio);
}
} else {
// Disabled button appearance
Clay_ElementId btn_eid = CLAY_ID("BtnTestToneDisabled");
CLAY(btn_eid,
.layout = {
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIXED(28) },
.padding = { 12, 12, 0, 0 },
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = Clay_Color{50, 50, 50, 255},
.cornerRadius = CLAY_CORNER_RADIUS(3)
) {
static Clay_TextElementConfig disabled_text = {};
disabled_text.textColor = Clay_Color{100, 100, 100, 255};
disabled_text.fontSize = 15;
disabled_text.wrapMode = CLAY_TEXT_WRAP_NONE;
CLAY_TEXT(CLAY_STRING("Play Test Tone"), &disabled_text);
}
}
if (tone_playing) {
ui_label("SettingsLblPlaying", "Playing...");
}
}
}
static void about_window_content(void *user_data) {
@@ -580,8 +661,9 @@ static void do_frame(AppState *app) {
if (!renderer_begin_frame(app->renderer))
return;
// Update MIDI activity timers
// Update subsystems
midi_update(app->midi, dt);
audio_update(app->audio, dt);
// Gather input
PlatformInput input = platform_get_input(app->window);
@@ -630,6 +712,7 @@ int main(int argc, char **argv) {
}
MidiEngine *midi = midi_create();
AudioEngine *audio = audio_create(platform_get_native_handle(window));
// Initialize UI (Clay)
ui_init_theme();
@@ -644,6 +727,7 @@ int main(int argc, char **argv) {
app.window = window;
app.renderer = renderer;
app.midi = midi;
app.audio = audio;
app.ui = ui;
app.last_w = w;
app.last_h = h;
@@ -675,6 +759,7 @@ int main(int argc, char **argv) {
}
exit_app:
audio_destroy(audio);
midi_destroy(midi);
ui_destroy(ui);
renderer_destroy(renderer);