feat(audio): capture transactional fixed-rate stereo samples
This commit is contained in:
parent
f496f12ea3
commit
902c892d3f
11 changed files with 382 additions and 15 deletions
|
|
@ -65,6 +65,9 @@ The repository is a Cargo workspace with three crates:
|
|||
| `crates/gba-core/src/cpu/fetch_boundary_tests.rs` | Actual fetch-region snapshots, split refills, IWRAM lane requirements, ROM-window boundaries, and nominal timing |
|
||||
| `crates/gba-core/src/io.rs` | I/O registers, timers, HALT/STOP wake-up, next-event bounds, and IRQ latches |
|
||||
| `crates/gba-core/src/audio.rs` | Direct Sound state, PSG sequencer, wave banks, and instantaneous stereo mixing |
|
||||
| `crates/gba-core/src/audio/capture.rs` | Optional fixed-rate sample clock, bounded committed queue, transaction batches, and drop accounting |
|
||||
| `crates/gba-core/tests/audio_capture.rs` | Sample rate/order, timer and pulse samples, HALT/STOP, batching, and bounded overflow |
|
||||
| `crates/gba-core/src/memory/audio_capture_tests.rs` | Sample/store bus ordering, speculative capture, failed-step rollback, and preflight isolation |
|
||||
| `crates/gba-core/src/audio/pulse.rs` | Shared pulse oscillator; sweep is mapped only for channel 1 |
|
||||
| `crates/gba-core/src/audio/modulation.rs` | Shared PSG length, envelope, logical DAC gate, and activity state |
|
||||
| `crates/gba-core/src/audio/wave.rs` | Single-bank wave samples, rotating RAM, length/gate state, and fractional gain |
|
||||
|
|
|
|||
|
|
@ -226,8 +226,8 @@ This centered mixer follows GBATEK's signed range and the NanoBoyAdvance compari
|
|||
The mixer adds all supported channels and the ten-bit bias, clips each side to `0..1023`, and subtracts 512.
|
||||
`StereoLevel` therefore contains signed levels in `-512..511`. Master disable returns zero.
|
||||
Bias resolution bits retain their values but do not yet drive pulse-width modulation (PWM) sampling or quantization.
|
||||
There is no resampling, analog filtering, sample queue, or host output backend.
|
||||
Polling once per video frame will not reconstruct audio.
|
||||
The optional capture stream below samples this mixer. Hardware PWM sampling and analog filtering remain unimplemented.
|
||||
Polling `audio_level()` once per video frame will not reconstruct audio.
|
||||
|
||||
Timer and sound state share the staged CPU/DMA clock.
|
||||
Reads and writes observe their nominal bus-completion phase, after earlier timer overflows.
|
||||
|
|
@ -235,6 +235,33 @@ Successful steps commit once. Failed steps discard FIFO consumption, held sample
|
|||
Block-store validation simulates sound enable/disable in a temporary state before committing any RAM or I/O writes.
|
||||
Other devices retain their existing scheduling limits.
|
||||
|
||||
## Fixed-rate digital capture
|
||||
|
||||
`Memory::set_audio_capture(true)` enables optional stereo capture at `AUDIO_SAMPLE_RATE` (32,768 Hz).
|
||||
The first sample occurs after 512 system clocks. Later samples use the same interval, independent of video frames.
|
||||
This is a nominal digital stream, not the hardware PWM/resolution model selected by SOUNDBIAS.
|
||||
|
||||
Each sample observes PSG advancement and timer-driven Direct Sound consumption through its clock boundary.
|
||||
When a CPU write completes on that same boundary, sampling precedes the write under the existing bus-phase ordering.
|
||||
No host time, window code, device dependency, resampling, or file operation enters the core.
|
||||
Master sound disable produces silence while capture continues. HALT continues capture; STOP freezes its phase and produces no frames.
|
||||
|
||||
`drain_audio_samples` copies committed stereo frames, oldest first, into a caller-provided slice.
|
||||
Values use the same signed ten-bit scale as `StereoLevel`, not normalized host PCM.
|
||||
CPU/DMA steps stage samples alongside timer/audio state. A failed step discards its samples and sample-clock changes.
|
||||
Block-store preflight never publishes samples. Row capture does not clock sound a second time.
|
||||
CPU-only stepping retains its existing no-device-clock behavior.
|
||||
|
||||
The committed queue holds at most `AUDIO_QUEUE_CAPACITY` (4,096) stereo frames.
|
||||
A transaction stages at most eight frames. Ordinary instruction/DMA timing fits within this budget.
|
||||
Full buffers discard new frames, retain older frames, and increment `audio_dropped_samples` without blocking emulation.
|
||||
Large device-only clock advances bound work by available capacity, then advance remaining hardware state in bulk.
|
||||
Draining often avoids loss; callers must inspect the drop counter rather than assuming lossless capture.
|
||||
|
||||
Capture is disabled by default. Changing enable state clears queued frames, phase, and the drop counter, but does not reset audio hardware.
|
||||
Repeating the current enable state preserves capture state. Configure capture between machine steps.
|
||||
Original tests cover exact sample boundaries, timer consumption, pulse phases, batching, queue overflow, HALT/STOP, and transactional rollback.
|
||||
|
||||
## Validation and remaining work
|
||||
|
||||
Original tests cover signed samples, byte order, queue capacity, partial writes, resets, underflow, stereo routing, and clipping.
|
||||
|
|
@ -251,7 +278,7 @@ CPU/DMA tests include noise register writes at bus completion and failed-step ro
|
|||
BIOS reset tests verify that selected sound reset stops all supported PSG channels, while unselected sound state remains active.
|
||||
|
||||
These tests validate the documented nominal model, not hardware audio fidelity.
|
||||
Remaining audio work: two-bank wave playback, verified live bank changes, a continuous output stream, PWM/mixer sampling, and a Darwin host backend.
|
||||
Remaining audio work: two-bank wave playback, verified live bank changes, hardware PWM sampling, filtering/resampling, and a Darwin host backend.
|
||||
A local Emerald input probe exposed a wave trigger with the gate disabled. This is now accepted without activating playback.
|
||||
The same scheduled-input probe passes that point and completes its extended frame budget; audible output and gameplay remain unverified.
|
||||
See [the local runtime result](../research/emerald-reset.md).
|
||||
|
|
|
|||
|
|
@ -153,7 +153,8 @@ The optional [cartridge GPIO/RTC subset](hardware/cartridge-gpio.md) supports ca
|
|||
RTC persistence, interrupts, invalid-date correction, physical subsecond timing, GPIO aliases, and byte writes remain unsupported or unverified.
|
||||
The core uses deterministic caller time. Desktop RTC runs use host UTC/elapsed time and are not fully deterministic.
|
||||
The [audio subset](hardware/audio.md) supports Direct Sound, both PSG pulse channels, single-bank wave channel 3, noise channel 4, and instantaneous digital mixing.
|
||||
It does not yet provide a continuous sample stream. Two-bank wave playback, active wave-bank changes, and unverified sound-DMA pairings remain diagnostic.
|
||||
Optional 32,768 Hz digital capture provides bounded, transactional stereo samples with explicit drop counts.
|
||||
Two-bank wave playback, active wave-bank changes, and unverified sound-DMA pairings remain diagnostic.
|
||||
PSG timing and signed mixing are nominal; hardware startup edges and analog behavior remain unverified.
|
||||
The [serial subset](hardware/serial.md) supports disconnected normal 8/32-bit transfers, external-clock waiting, idle multiplayer configuration, and general-purpose pins.
|
||||
Internal clocks shift high input at nominal rates, clear busy, and request completion IRQs. External requests retain busy without clock edges.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue