Files
looper/docs/evaluation.md

62 lines
4.9 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Evaluation of Looper Codebase
## Summary Table
| Category | Rating | Notes |
|-------------------------|--------|-------|
| **Mocked / leftdoing** | ⚠️ Moderate | No mock objects; real Carla dependency. Tests for Carla host are stubs. Integration test requires running JACK server. Script module test now passes 7/7 (empty macro bug fixed). |
| **Potential segfaults** | ✅ Low | `exec_command` validates channel bounds (`ch < MAX_CHANNELS`). `note_actions` is checked for NULL before use. `strdup` returns not checked but safe in practice. No outofbounds access identified. |
| **Memory management** | ✅ Good | `note_actions` strings freed via `script_cleanup()` called in `tui_cleanup()`. `strdup` allocations are freed on reload. All dynamically allocated audio buffers are freed. No leaks at exit. |
| **Thread safety** | ✅ Good | All shared scene/channel fields use C11 atomics. Logging mutex never held in audio thread. Save deactivation uses atomic active flag with two wait periods (500ms + 200ms) guaranteeing RT thread sees the change. FIFO writes are atomic (`PIPE_BUF`). No race conditions identified. |
| **Performance** | ✅ Fair | Audio path: `memcpy`, linear loops, no allocations realtime safe. Main loop sleeps 50ms fine. Save pauses audio for 500ms (acceptable for a tool). Logging adds negligible mutex overhead outside RT thread. JACK callback time is deterministic. |
| **Architectural soundness** | ⚠️ Medium | Separation of engine and client via FIFO is clean. Orchestrator simple but effective. Three command queues still add unnecessary complexity (single queue would suffice). `prev_state` transition detection works. Carla integration remains tightly coupled to JACK client. Script/macro mechanism is extensible and well isolated. Logging design correctly avoids audio thread. |
## Detailed Commentary
### 1. Mocked / Leftdoing
- **Engine tests** require a live JACK server no mocking.
- **Client tests** for `carla_host` and `plugins` use stubs when `TESTING` is defined; real Carla library is still linked. Integration test also requires JACK.
- **Script tests** pass 7/7 after the empty macro bug was fixed.
- **No mock for MIDI** engine integration test uses actual MIDI events.
### 2. Potential Segfaults
- **Channel bounds** are now validated in `exec_command`: `if (ch < 0 || ch >= MAX_CHANNELS) ch = 0;`. Safe.
- **NULL pointer dereference**: `script_handle_note` checks for NULL before using `macro`. `strdup` failure would set `note_actions[note]` to NULL, then checked. Safe.
- **FIFO write errors** silently ignored no crash.
### 3. Memory Management
- `note_actions[]` strings are freed on every `script_load` write and on cleanup (`script_cleanup` called in `tui_cleanup`). No leak.
- Audio loop buffer (`loop_data_t`) is embedded in `scene_t` no heap allocation.
- Save path uses `malloc/free` correctly; freed after write.
- Log file pointer is closed at exit.
### 4. Thread Safety
- All `scene_t` fields accessed from both threads are atomic (`state`, `prev_state`, `record_pos`, `loop_count`, `playback_pos`). Correct.
- `channel_t.active`, `channel_t.save_ring` are atomic. Correct.
- **Save sequence**: set `active=0`, sleep 500ms, copy buffer, set `active=1`. The sleep guarantees the RT thread has seen the deactivation. No race.
- **Logging mutex** acquired only outside audio thread fine.
- **FIFO writes** from multiple threads are not serialized but `write` to a FIFO is atomic for writes ≤ `PIPE_BUF` (4096 bytes). Our messages are smaller. Safe.
### 5. Performance
- Audio buffer processing uses simple loops with no function calls. `nframes` is typically 64256 fine.
- `state` transitions check `prev_state` each callback cheap.
- Save mechanism: 500ms pause may cause one xrun. Acceptable for a prototype.
- Main loop sleep 50ms ensures low CPU usage.
### 6. Architectural Soundness
- **Good**: Clear separation between engine (realtime audio) and client (UI, plugin management). Communication via FIFO files.
- **Weakness**: Three command queues (`cmd_queue`, `cmd_queue_main_midi`, `cmd_queue_main_fifo`) are redundant all feed `exec_command`. Could consolidate.
- **Weakness**: Carla integration tied to the engines JACK client. A separate Carla engine instance would be cleaner.
- **Strength**: Script/macro system is simple textbased and extensible. The notes FIFO allows any external controller to inject note numbers.
- **Strength**: Logging nonintrusive and never used in realtime path.
---
*Overall, the codebase is functional and stable.* All previously identified critical issues (channel bounds, memory leak, empty macro) have been fixed. Recommendations for further improvement:
- Replace three command queues with a single queue.
- Use a doublebuffer for save to eliminate the 500ms pause.
- Consider mock objects for engine tests to remove JACK dependency.
- Add more unit tests for edge cases.
**Evaluation date**: 18 May 2026