Streamlined audio device (now activating once).
h3rald h3rald@h3rald.com
Fri, 13 Feb 2026 08:00:21 +0100
2 files changed,
34 insertions(+),
26 deletions(-)
M
devices/beeper.c
→
devices/beeper.c
@@ -27,6 +27,11 @@ float amplitude;
ma_uint64 samples_remaining; } beeper_state; +// Persistent audio device +static ma_device beeper_device; +static beeper_state beeper_st = {0}; +static int beeper_device_initialized = 0; + // Audio callback to generate the square wave tone static void beeper_callback(ma_device *device, void *output, const void *input, ma_uint32 frame_count) {@@ -53,44 +58,47 @@ }
} } -// Helper function to play a tone with given frequency, duration, and level -static void beeper_play_tone(xyw_word freq, unsigned long duration_ms, xyw_byte level) +// Ensure the persistent audio device is initialized +static int beeper_ensure_device(void) { - ma_device_config config; - ma_device device; - beeper_state state = {0}; - - // Initialize state for the tone - state.phase = 0.0; - state.phase_increment = MA_TAU * (double)freq / BEEPER_SAMPLE_RATE; - state.amplitude = (float)level / (float)BEEPER_MAX_LEVEL; - state.samples_remaining = (ma_uint64)(BEEPER_SAMPLE_RATE * duration_ms / 1000); + if (beeper_device_initialized) + return 1; - // Initialize and start the audio device - config = ma_device_config_init(ma_device_type_playback); + ma_device_config config = ma_device_config_init(ma_device_type_playback); config.playback.format = ma_format_f32; config.playback.channels = 1; config.sampleRate = BEEPER_SAMPLE_RATE; config.dataCallback = beeper_callback; - config.pUserData = &state; + config.pUserData = &beeper_st; - if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) - return; + if (ma_device_init(NULL, &config, &beeper_device) != MA_SUCCESS) + return 0; - if (ma_device_start(&device) != MA_SUCCESS) + if (ma_device_start(&beeper_device) != MA_SUCCESS) { - ma_device_uninit(&device); + ma_device_uninit(&beeper_device); + return 0; + } + + beeper_device_initialized = 1; + return 1; +} + +// Helper function to play a tone with given frequency, duration, and level +static void beeper_play_tone(xyw_word freq, unsigned long duration_ms, xyw_byte level) +{ + if (!beeper_ensure_device()) return; - } + + // Update tone parameters (callback will pick them up) + beeper_st.phase = 0.0; + beeper_st.phase_increment = MA_TAU * (double)freq / BEEPER_SAMPLE_RATE; + beeper_st.amplitude = (float)level / (float)BEEPER_MAX_LEVEL; + beeper_st.samples_remaining = (ma_uint64)(BEEPER_SAMPLE_RATE * duration_ms / 1000); // Wait for playback to complete - while (state.samples_remaining > 0) + while (beeper_st.samples_remaining > 0) ma_sleep(1); - - // Brief drain delay for audio buffers to ensure the tone finishes playing - ma_sleep(10); - - ma_device_uninit(&device); } void beeper_output(xyw_byte *data, xyw_byte addr, xyw_byte *error)
M
xyw-vscode/syntaxes/xyw.tmLanguage.json
→
xyw-vscode/syntaxes/xyw.tmLanguage.json
@@ -157,7 +157,7 @@ "patterns": [
{ "comment": "Device identifiers: system.*, terminal.*, file.*, clock.*, beeper.*", "name": "support.type.device.xyw", - "match": "\\b(system|terminal|file|clock|beeper|)\\.[a-zA-Z0-9_.\\-]*\\b" + "match": "\\b(system|terminal|file|clock|beeper)\\.[a-zA-Z0-9_.\\-]*\\b" }, { "comment": "Label/macro references: starts with letter/underscore, can contain letters, numbers, underscores, dashes, or dots",