menios icon indicating copy to clipboard operation
menios copied to clipboard

Audio validation and tooling (WAV player, tests)

Open pbalduino opened this issue 3 months ago • 0 comments

Goal

Develop comprehensive validation tools, tests, and utilities to verify audio subsystem correctness before Doom integration.

Context

Part of #33 (Audio subsystem). This work ensures the entire audio stack (#382, #383, #384, #385) works correctly through systematic testing and practical tools.

Scope

Testing Infrastructure

1. Host Test Harness (Unity Framework)

Unit Tests
// test/test_audio_mixer.c
- test_mix_two_streams_16bit()
- test_mix_overflow_clipping()
- test_sample_rate_conversion()
- test_buffer_wraparound()
- test_format_conversion_u8_to_s16()
Mock Infrastructure
  • Mock DMA buffers (simulate hardware ring)
  • Mock interrupt delivery
  • Timing simulation (virtual time for deterministic tests)

2. Kernel Integration Tests

// test/test_audio_syscalls.c
- test_dsp_open_close()
- test_dsp_write_blocking()
- test_dsp_write_nonblocking()
- test_dsp_ioctl_format()
- test_dsp_buffer_underrun_recovery()

3. Stress Tests

  • Multiple streams simultaneously (4-8 streams)
  • Rapid open/close cycles (resource leak detection)
  • Buffer underrun/overrun injection
  • Latency measurement (time-to-first-sample)

Validation Tools

1. Tone Generator (/bin/tone)

Simple PCM sine wave generator:

# Generate 440 Hz tone at 22050 Hz, 5 seconds
/bin/tone 440 22050 5

Features:

  • Configurable frequency (Hz)
  • Configurable sample rate (11025, 22050, 44100, 48000)
  • Duration control
  • Format selection (8-bit, 16-bit)
  • Mono/stereo output

Implementation:

// app/tone/tone.c
- Parse command-line arguments
- Generate sine wave samples (lookup table or math.h)
- Open /dev/dsp, configure format
- Write samples in chunks
- Report timing and buffer stats

2. WAV File Player (/bin/play)

Play RIFF WAVE files from filesystem:

# Play a WAV file
/bin/play /HOME/DOOM/sounds/pistol.wav

Features:

  • Parse RIFF WAVE header (fmt chunk, data chunk)
  • Support common formats (8/16-bit PCM, mono/stereo)
  • Automatic rate conversion if needed
  • Progress indicator
  • Error reporting (unsupported format, file not found)

Implementation:

// app/play/play.c
- Read and parse WAV header
- Validate format (reject compressed formats)
- Configure /dev/dsp to match WAV format
- Stream data chunks to audio device
- Handle short reads, EOF

3. Audio Diagnostic Tool (/bin/audioinfo)

Query audio subsystem status:

# Show audio device information
/bin/audioinfo

Output:

Audio Device: /dev/dsp
  Driver: AC'97 (Intel ICH)
  Status: Ready
  Supported Formats: U8, S16_LE
  Supported Rates: 11025, 22050, 44100, 48000
  Buffer Size: 16384 bytes (4 fragments × 4096)
  Latency: ~93 ms
  Active Streams: 0

Implementation:

  • Query via ioctl (SNDCTL_DSP_GETCAPS, GETOSPACE, etc.)
  • Read /proc/audio (if implemented)
  • Pretty-print capabilities

Sample Audio Files

Provide test WAV files in initrd or FAT32:

  • tone440.wav - 440 Hz sine wave, 16-bit, 22050 Hz, 2 sec
  • sweep.wav - Frequency sweep 20 Hz - 20 kHz
  • pistol.wav - Doom pistol sound effect (from shareware WAD)
  • music.wav - Short music clip (E1M1 excerpt)

Documentation

1. Testing Guide (docs/testing/audio.md)

  • How to run audio tests
  • Interpreting test failures
  • QEMU audio setup (enable AC'97)
  • Real hardware validation checklist

2. Audio API Reference (docs/api/audio.md)

  • libc audio functions
  • /dev/dsp ioctl reference
  • Code examples
  • Troubleshooting common issues

3. Developer Notes (docs/design/audio.md)

  • Architecture overview (driver → core → syscalls → libc)
  • Buffer flow diagrams
  • Timing and latency analysis
  • Known limitations

Implementation Phases

Phase 1: Host Unit Tests (3-4 days)

  • Set up Unity test framework for audio
  • Write mixer unit tests
  • Write buffer management tests
  • Mock DMA and interrupts

Phase 2: Kernel Integration Tests (3-4 days)

  • Implement syscall tests
  • Test blocking/non-blocking semantics
  • Verify ioctl configuration
  • Test error conditions

Phase 3: Validation Tools (4-5 days)

  • Implement tone generator (/bin/tone)
  • Implement WAV player (/bin/play)
  • Implement audioinfo utility
  • Create sample WAV files

Phase 4: Documentation and Stress Tests (2-3 days)

  • Write testing guide
  • Write API reference
  • Run stress tests (multi-stream, leak detection)
  • Document findings and limitations

Definition of Done

  • [ ] Unit tests for mixer and buffer management (host harness)
  • [ ] Integration tests for /dev/dsp syscalls
  • [ ] Tone generator (/bin/tone) working
  • [ ] WAV player (/bin/play) plays sample files
  • [ ] Audio info utility (/bin/audioinfo) displays status
  • [ ] Sample WAV files included in build
  • [ ] Documentation: testing guide, API reference, design notes
  • [ ] All tests passing in QEMU
  • [ ] Stress tests complete (no leaks, no crashes)
  • [ ] Ready for Doom integration (#33)

Dependencies

  • #382 - PCI audio driver (to test real hardware path)
  • #383 - Kernel audio core (mixer tests)
  • #384 - Audio syscalls (integration tests)
  • #385 - Userland audio API (for tools)
  • #193 - Minimal libc ✅ (for utility programs)
  • #189 - FAT32 write support ✅ (for WAV files)

Risks

  • QEMU audio quirks: QEMU AC'97 may not match real hardware
  • WAV parsing bugs: Malformed files cause crashes
  • Timing sensitivity: Tests may be flaky on slow systems
  • Sample file licensing: Ensure Doom sound effects are shareware

Timeline

Estimated effort: 2 weeks (12-16 days)

Testing Strategy

Automated Tests

make test-audio          # Run all audio tests
make test-audio-unit     # Unit tests only
make test-audio-stress   # Stress tests

Manual Validation

  1. Boot meniOS in QEMU with audio enabled
  2. Run /bin/tone 440 22050 3 → verify audible 440 Hz tone
  3. Run /bin/play /HOME/test.wav → verify WAV playback
  4. Run /bin/audioinfo → verify device info
  5. Load Doom → verify sound effects and music

Acceptance Criteria

  • Tone generator produces clean sine wave (no clicks/pops)
  • WAV player handles 8/16-bit, mono/stereo files
  • No buffer underruns during normal playback
  • Tests pass on both host and native

Example Test Output

[TEST] test_mix_two_streams_16bit ... PASS
[TEST] test_mix_overflow_clipping ... PASS
[TEST] test_sample_rate_conversion ... PASS
[TEST] test_buffer_wraparound ... PASS
[TEST] test_dsp_open_close ... PASS
[TEST] test_dsp_write_blocking ... PASS

Audio Tests: 6/6 passed ✓

Tone Generator Test:
  Frequency: 440 Hz
  Sample Rate: 22050 Hz
  Duration: 3.0 sec
  Samples Written: 66150
  Buffer Underruns: 0
  ✓ Playback complete

WAV Player Test:
  File: /HOME/pistol.wav
  Format: S16_LE, 22050 Hz, Mono
  Size: 8192 bytes
  Duration: 0.37 sec
  ✓ Playback complete

References

  • Unity Testing Framework: http://www.throwtheswitch.org/unity
  • RIFF WAVE format: http://soundfile.sapp.org/doc/WaveFormat/
  • OSS testing examples: Linux sound/oss/ tests
  • Audio testing best practices

Related Issues

  • Parent: #33 (Audio subsystem)
  • Depends on: #382, #383, #384, #385, #193, #189
  • Validates: Entire audio stack

Priority

Medium - Part of Doom audio milestone, blocked by #279

Status

BLOCKED BY #279 (Dynamic IRQ handler registration API)

This issue is part of the audio subsystem implementation for the Doom milestone. It cannot proceed until #279 is complete.

Dependency Chain

#279 (Dynamic IRQ) ← CRITICAL BLOCKER (HIGH priority)
  ↓
#382 + #383 (Audio driver + core) ← YOU ARE HERE
  ↓
#384 (Syscalls) → #385 (API) → #386 (Testing)
  ↓
Doom audio integration

Related Issues

  • #33 (Audio subsystem parent) - umbrella issue
  • #279 (Dynamic IRQ) - BLOCKS THIS ISSUE

Priority Rationale: Medium priority appropriate for Doom milestone work, but cannot start until HIGH priority #279 is complete.

pbalduino avatar Oct 29 '25 22:10 pbalduino