summaryrefslogtreecommitdiff
path: root/src/audio/miniaudio_backend.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-07 11:37:03 +0100
committerskal <pascal.massimino@gmail.com>2026-02-07 11:37:03 +0100
commit5b51a8571e127515b01f1d14b45abc8077de5f34 (patch)
treeab2d3f5cb525872dd5a91619a392929ff089db79 /src/audio/miniaudio_backend.cc
parentab95bf75d1f2fc500f71c57dfe7ffc52e838dff0 (diff)
refactor(audio): Convert miniaudio_backend.cc to use FATAL_* macros (Phase 3)
Converted all 3 abort() calls in miniaudio_backend.cc to FATAL_* macros, completing the audio subsystem migration to strippable error checking. ## Changes ### miniaudio_backend.cc - Replaced `#include <stdlib.h> // for abort()` with `#include "util/fatal_error.h"` - Removed `#include <stdio.h>` (included by fatal_error.h) - Converted 3 abort() patterns to FATAL_* macros: 1. **Callback re-entry check** (line 66) - Complex case using FATAL_CODE_BEGIN/END - Static variable tracking (callback_reentry counter) - Increment at entry, decrement at exit (line 150) - Entire re-entry detection logic stripped in FINAL_STRIP 2. **Invalid device check** (line 80) - Simple FATAL_CHECK - Validates pDevice pointer and sample rate - Critical for audio callback safety 3. **Unreasonable frameCount check** (line 100) - Simple FATAL_CHECK - Bounds check: frameCount must be in range (1, 8192] - Prevents buffer overflow from malformed callback requests ## Size Impact **Incremental savings** (Phase 3 only): - Additional bytes saved: 472 bytes (3 checks) **Cumulative savings** (Phase 2 + Phase 3): - Normal build: 1,416,616 bytes - FINAL_STRIP build: 1,380,936 bytes - **Total savings: 35,680 bytes (~34.8 KB)** Breakdown: - Phase 2 (ring_buffer.cc): ~35,208 bytes (8 checks) - Phase 3 (miniaudio_backend.cc): ~472 bytes (3 checks) ## Code Transformation Examples **Example 1: Simple FATAL_CHECK** ```cpp // Before: if (frameCount > 8192 || frameCount == 0) { fprintf(stderr, "AUDIO CALLBACK ERROR: frameCount=%u (unreasonable!)\n", frameCount); abort(); } // After: FATAL_CHECK(frameCount > 8192 || frameCount == 0, "AUDIO CALLBACK ERROR: frameCount=%u (unreasonable!)\n", frameCount); ``` **Example 2: Complex validation with FATAL_CODE_BEGIN/END** ```cpp // Before: #if defined(DEBUG_LOG_AUDIO) if (callback_reentry > 0) { DEBUG_AUDIO("FATAL: Callback re-entered! depth=%d\n", callback_reentry); abort(); } callback_reentry++; // ... rest of function ... callback_reentry--; #endif // After: #if defined(DEBUG_LOG_AUDIO) FATAL_CODE_BEGIN if (callback_reentry > 0) { FATAL_ERROR("Callback re-entered! depth=%d", callback_reentry); } callback_reentry++; FATAL_CODE_END // ... rest of function ... FATAL_CODE_BEGIN callback_reentry--; FATAL_CODE_END #endif ``` In FINAL_STRIP mode, FATAL_CODE_BEGIN/END expands to `if (0) { }`, causing the compiler to eliminate the entire block (dead code elimination). ## Testing All 27 tests pass in both modes: - Normal build (checks enabled): ✅ 27/27 pass - FINAL_STRIP build (checks stripped): Compiles successfully Audio subsystem now fully migrated to strippable error checking: - ✅ ring_buffer.cc (8 checks) - ✅ miniaudio_backend.cc (3 checks) - Total: 11 checks converted ## Design Notes **Why FATAL_CODE_BEGIN/END for callback re-entry?** The callback re-entry detection uses a static counter that must be incremented at function entry and decremented at exit. This creates a dependency between two locations in the code. Using FATAL_CODE_BEGIN/END ensures both the increment and decrement are stripped together in FINAL_STRIP builds, maintaining correctness: - Debug/STRIP_ALL: Full re-entry tracking enabled - FINAL_STRIP: Entire tracking mechanism removed (zero cost) Alternative approaches (conditional per-statement) would require careful manual synchronization and are more error-prone. ## Next Steps Phase 4: Systematic scan for remaining abort() calls - Search entire codebase for any missed abort() calls - Convert any fprintf(stderr, ...) + abort() patterns - Verify all production code uses FATAL_* macros Phase 5: Size verification and documentation - Build full demo64k in both modes - Measure actual binary size savings - Update documentation with final measurements Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/audio/miniaudio_backend.cc')
-rw-r--r--src/audio/miniaudio_backend.cc32
1 files changed, 15 insertions, 17 deletions
diff --git a/src/audio/miniaudio_backend.cc b/src/audio/miniaudio_backend.cc
index baaf9bb..0e6fce5 100644
--- a/src/audio/miniaudio_backend.cc
+++ b/src/audio/miniaudio_backend.cc
@@ -6,8 +6,7 @@
#include "audio.h"
#include "ring_buffer.h"
#include "util/debug.h"
-#include <stdio.h>
-#include <stdlib.h> // for abort()
+#include "util/fatal_error.h"
// Static callback for miniaudio (C API requirement)
void MiniaudioBackend::audio_callback(ma_device* pDevice, void* pOutput,
@@ -63,11 +62,12 @@ void MiniaudioBackend::audio_callback(ma_device* pDevice, void* pOutput,
timing_initialized = 1;
// Check for re-entrant calls
- if (callback_reentry > 0) {
- DEBUG_AUDIO("FATAL: Callback re-entered! depth=%d\n", callback_reentry);
- abort();
- }
- callback_reentry++;
+ FATAL_CODE_BEGIN
+ if (callback_reentry > 0) {
+ FATAL_ERROR("Callback re-entered! depth=%d", callback_reentry);
+ }
+ callback_reentry++;
+ FATAL_CODE_END
// Check if frameCount changed unexpectedly
if (last_frameCount != 0 && frameCount != last_frameCount) {
@@ -77,10 +77,8 @@ void MiniaudioBackend::audio_callback(ma_device* pDevice, void* pOutput,
last_frameCount = frameCount;
// Validate device state
- if (!pDevice || pDevice->sampleRate == 0) {
- DEBUG_AUDIO("FATAL: Invalid device in callback!\n");
- abort();
- }
+ FATAL_CHECK(!pDevice || pDevice->sampleRate == 0,
+ "Invalid device in callback!\n");
// Check actual sample rate matches our expectation
if (pDevice->sampleRate != 32000) {
@@ -97,11 +95,9 @@ void MiniaudioBackend::audio_callback(ma_device* pDevice, void* pOutput,
float* fOutput = (float*)pOutput;
// BOUNDS CHECK: Sanity check on frameCount
- if (frameCount > 8192 || frameCount == 0) {
- fprintf(stderr, "AUDIO CALLBACK ERROR: frameCount=%u (unreasonable!)\n",
- frameCount);
- abort();
- }
+ FATAL_CHECK(frameCount > 8192 || frameCount == 0,
+ "AUDIO CALLBACK ERROR: frameCount=%u (unreasonable!)\n",
+ frameCount);
// Read from ring buffer instead of calling synth directly
AudioRingBuffer* ring_buffer = audio_get_ring_buffer();
@@ -152,7 +148,9 @@ void MiniaudioBackend::audio_callback(ma_device* pDevice, void* pOutput,
#if defined(DEBUG_LOG_AUDIO)
// Clear reentry flag
- callback_reentry--;
+ FATAL_CODE_BEGIN
+ callback_reentry--;
+ FATAL_CODE_END
#endif /* defined(DEBUG_LOG_AUDIO) */
}