@@ -3,13 +3,13 @@ title: "Audio Device Abstraction"
33document_id : " audio-device-abstraction-2026-01-28"
44status : " draft"
55created : " 2026-01-28T22:59:00Z"
6- last_updated : " 2026-01-30T22:15:27Z "
7- version : " 0.1.10 "
6+ last_updated : " 2026-01-30T23:21:06Z "
7+ version : " 0.1.12 "
88engine_workspace_version : " 2023.1.30"
99wgpu_version : " 26.0.1"
1010shader_backend_default : " naga"
1111winit_version : " 0.29.10"
12- repo_commit : " e179f7de3b43f9cd822b4f7ab520c095dc3c6911 "
12+ repo_commit : " 7e7851da903fbc7b4aa35acd511999df659af237 "
1313owners : ["lambda-sh"]
1414reviewers : ["engine", "rendering"]
1515tags : ["spec", "audio", "lambda-rs", "platform", "cpal"]
@@ -82,23 +82,23 @@ tags: ["spec", "audio", "lambda-rs", "platform", "cpal"]
8282
8383## Architecture Overview
8484
85- - Crate ` lambda-rs `
85+ - Crate ` lambda ` (package: ` lambda -rs` )
8686 - ` audio ` module provides the application-facing API for output device access.
8787 - The public API MUST remain backend-agnostic and MUST NOT expose ` cpal ` or
8888 ` lambda-rs-platform ` types.
89- - Crate ` lambda-rs-platform `
90- - ` cpal ` module provides internal implementations used by ` lambda-rs `
91- implementations.
89+ - Crate ` lambda_platform ` (package: ` lambda-rs-platform ` )
90+ - ` cpal ` module provides internal implementations used by ` lambda-rs ` .
9291 - ` cpal::device ` wraps ` cpal ` device discovery and stream creation.
92+ - The backend dependency MUST be pinned to ` cpal = "=0.17.1" ` .
9393
9494Data flow
9595
9696```
9797application
98- └── lambda-rs ::audio
98+ └── lambda::audio
9999 ├── enumerate_output_devices() -> Vec<AudioOutputDeviceInfo>
100100 └── AudioOutputDeviceBuilder::build() -> AudioOutputDevice
101- └── lambda-rs-platform ::cpal (internal)
101+ └── lambda_platform ::cpal (internal)
102102 ├── enumerate_devices() -> Vec<AudioDeviceInfo>
103103 └── AudioDeviceBuilder::build() -> AudioDevice
104104 └── cpal (host + device + stream)
@@ -220,16 +220,17 @@ pub fn enumerate_devices() -> Result<Vec<AudioDeviceInfo>, AudioError>;
220220### lambda-rs Public API
221221
222222` lambda-rs ` provides the application-facing audio API and translates to
223- ` lambda-rs-platform::cpal ` internally. The ` lambda-rs ` layer MUST remain
224- backend-agnostic and MUST NOT expose ` cpal ` types.
223+ ` lambda_platform::cpal ` (package: ` lambda-rs-platform ` ) internally. The
224+ ` lambda-rs ` layer MUST remain backend-agnostic and MUST NOT expose ` cpal `
225+ types.
225226
226227Crate boundary
227228
228229- Applications MUST use ` lambda-rs ` for audio and MUST NOT use
229230 ` lambda-rs-platform ` directly.
230231- ` lambda-rs-platform ` audio APIs are internal implementation details and MAY
231232 change without regard for application compatibility.
232- - ` lambda-rs ::audio ` MUST remain backend-agnostic and MUST NOT require direct
233+ - ` lambda::audio ` MUST remain backend-agnostic and MUST NOT require direct
233234 use of ` lambda-rs-platform ` types by applications.
234235
235236Application-facing API surface
@@ -316,29 +317,30 @@ pub fn enumerate_output_devices(
316317
317318Implementation rules
318319
319- - ` lambda-rs::audio ` MUST translate into ` lambda-rs-platform::cpal ` internally.
320- - ` lambda-rs::audio ` MUST define its own public types and MUST NOT re-export
320+ - ` lambda::audio ` MUST translate into ` lambda_platform::cpal ` (package:
321+ ` lambda-rs-platform ` ) internally.
322+ - ` lambda::audio ` MUST define its own public types and MUST NOT re-export
321323 ` lambda-rs-platform ` audio types.
322- - ` lambda-rs ::audio::AudioError ` MUST remain backend-agnostic and MUST NOT
324+ - ` lambda::audio::AudioError ` MUST remain backend-agnostic and MUST NOT
323325 expose ` cpal ` types.
324326
325327Features
326328
327329- ` lambda-rs ` granular feature: ` audio-output-device ` (default: enabled)
328- - Enables the ` lambda-rs ::audio ` output device surface.
330+ - Enables the ` lambda::audio ` output device surface.
329331 - Enables ` lambda-rs-platform ` ` audio-device ` internally.
330332- ` lambda-rs ` umbrella feature: ` audio ` (default: enabled)
331333 - Composes ` audio-output-device ` only.
332334
333335### Application Interaction
334336
335337This section describes the intended application-facing workflow via
336- ` lambda-rs ::audio ` .
338+ ` lambda::audio ` .
337339
338340Initialization flow
339341
340- - An application SHOULD enumerate devices to present names in diagnostics or a
341- settings UI .
342+ - An application SHOULD enumerate devices to present names in diagnostics
343+ output .
342344- An application SHOULD create exactly one default output device during
343345 startup.
344346- The application MUST keep the returned device handle alive for as long as
@@ -347,7 +349,7 @@ Initialization flow
347349Device enumeration
348350
349351``` rust
350- let devices = lambda_rs :: audio :: enumerate_output_devices ()? ;
352+ let devices = lambda :: audio :: enumerate_output_devices ()? ;
351353for device in devices {
352354 println! (
353355 " audio: {}{}" ,
@@ -363,7 +365,7 @@ Default device initialization (deterministic test tone)
363365let mut phase : f32 = 0.0 ;
364366let frequency_hz : f32 = 440.0 ;
365367
366- let _audio_output = lambda_rs :: audio :: AudioOutputDeviceBuilder :: new ()
368+ let _audio_output = lambda :: audio :: AudioOutputDeviceBuilder :: new ()
367369 . with_sample_rate (48_000 )
368370 . with_channels (2 )
369371 . build_with_output_callback (move | writer , info | {
@@ -394,11 +396,11 @@ Runtime interaction
394396Minimal application sketch
395397
396398``` rust
397- use lambda_rs :: runtime :: start_runtime;
398- use lambda_rs :: runtimes :: ApplicationRuntimeBuilder ;
399+ use lambda :: runtime :: start_runtime;
400+ use lambda :: runtimes :: ApplicationRuntimeBuilder ;
399401
400- fn main () -> Result <(), lambda_rs :: audio :: AudioError > {
401- let _audio_output = lambda_rs :: audio :: AudioOutputDeviceBuilder :: new ()
402+ fn main () -> Result <(), lambda :: audio :: AudioError > {
403+ let _audio_output = lambda :: audio :: AudioOutputDeviceBuilder :: new ()
402404 . build ()? ;
403405
404406 let runtime = ApplicationRuntimeBuilder :: new (" Lambda App" ). build ();
@@ -409,7 +411,7 @@ fn main() -> Result<(), lambda_rs::audio::AudioError> {
409411
410412### Behavior
411413
412- Device enumeration (` lambda_rs ::audio::enumerate_output_devices` )
414+ Device enumeration (` lambda ::audio::enumerate_output_devices` )
413415
414416- ` enumerate_output_devices ` MUST return only output-capable devices.
415417- ` enumerate_output_devices ` MUST include the default output device when one
@@ -425,9 +427,9 @@ Default device initialization (`AudioOutputDeviceBuilder::build`)
425427- ` build ` MUST validate the requested configuration against the device’s
426428 supported output configurations.
427429- When ` sample_rate ` is not specified, ` build ` MUST prefer 48_000 Hz when
428- supported and otherwise fall back to the device default configuration.
429- - When ` channels ` is not specified, ` build ` MUST prefer stereo ( ` 2 ` ) when
430- supported and otherwise fall back to the device default configuration .
430+ supported and otherwise clamp to the nearest supported rate within the chosen
431+ configuration range.
432+ - When ` channels ` is not specified, ` build ` MUST NOT filter by channel count .
431433- ` build ` MUST create an output stream that produces silence (all samples set
432434 to zero) and MUST keep the stream alive for the lifetime of
433435 ` AudioOutputDevice ` .
@@ -484,15 +486,15 @@ Error type
484486
485487- ` lambda-rs ` MUST define an ` AudioError ` error enum suitable for actionable
486488 diagnostics.
487- - ` lambda-rs ::audio::AudioError ` MUST remain backend-agnostic and MUST NOT
489+ - ` lambda::audio::AudioError ` MUST remain backend-agnostic and MUST NOT
488490 expose ` cpal ` or ` lambda-rs-platform ` types.
489491- ` lambda-rs-platform ` MUST define an internal ` AudioError ` suitable for
490492 actionable diagnostics inside the platform layer.
491- - ` lambda-rs-platform ::cpal::AudioError` MUST NOT expose ` cpal ` types in its
492- public API.
493- - ` lambda-rs ` MUST translate ` lambda-rs-platform ::cpal::AudioError` into
494- ` lambda-rs::audio::AudioError ` . Backend-specific failures SHOULD map to
495- ` AudioError::Platform { details } ` .
493+ - ` lambda_platform ::cpal::AudioError` (package: ` lambda-rs-platform ` ) MUST NOT
494+ expose ` cpal ` types in its public API.
495+ - ` lambda-rs ` MUST translate ` lambda_platform ::cpal::AudioError` (package:
496+ ` lambda-rs-platform ` ) into ` lambda ::audio::AudioError` . Backend-specific
497+ failures SHOULD map to ` AudioError::Platform { details } ` .
496498
497499Platform ` AudioError ` variants (internal)
498500
@@ -521,7 +523,7 @@ Features introduced by this spec
521523
522524- Crate: ` lambda-rs `
523525 - Granular feature: ` audio-output-device ` (default: enabled)
524- - Enables ` lambda-rs ::audio ` output device APIs.
526+ - Enables ` lambda::audio ` output device APIs.
525527 - Enables ` lambda-rs-platform ` ` audio-device ` internally.
526528 - Umbrella feature: ` audio ` (default: enabled)
527529 - Composes ` audio-output-device ` only.
@@ -568,32 +570,50 @@ Feature gating requirements
568570## Requirements Checklist
569571
570572- Functionality
571- - [ ] Feature flags defined (` lambda-rs ` : ` audio-output-device ` , ` audio ` )
572- - [ ] Feature flags defined (` lambda-rs-platform ` : ` audio-device ` , ` audio ` )
573- - [ ] ` enumerate_output_devices ` implemented and returns output devices
574- - [ ] ` AudioOutputDeviceBuilder::build ` initializes default output device
575- - [ ] ` AudioOutputDeviceBuilder::build_with_output_callback ` invokes callback
576- - [ ] Stream created and kept alive for ` AudioOutputDevice ` lifetime
577- - [ ] Platform enumeration implemented (` lambda-rs-platform::cpal ` )
578- - [ ] Platform builder implemented (` lambda-rs-platform::cpal ` )
573+ - [x] Feature flags defined (` lambda-rs ` : ` audio-output-device ` , ` audio ` )
574+ (` crates/lambda-rs/Cargo.toml:22 ` )
575+ - [x] Feature flags defined (` lambda-rs-platform ` : ` audio-device ` , ` audio ` )
576+ (` crates/lambda-rs-platform/Cargo.toml:53 ` )
577+ - [x] ` enumerate_output_devices ` implemented and returns output devices
578+ (` crates/lambda-rs/src/audio.rs:294 ` )
579+ - [x] ` AudioOutputDeviceBuilder::build ` initializes default output device
580+ (` crates/lambda-rs/src/audio.rs:222 ` ,
581+ ` crates/lambda-rs-platform/src/cpal/device.rs:403 ` )
582+ - [x] ` AudioOutputDeviceBuilder::build_with_output_callback ` invokes callback
583+ (` crates/lambda-rs/src/audio.rs:247 ` ,
584+ ` crates/lambda-rs-platform/src/cpal/device.rs:524 ` )
585+ - [x] Stream created and kept alive for ` AudioOutputDevice ` lifetime
586+ (` crates/lambda-rs/src/audio.rs:182 ` ,
587+ ` crates/lambda-rs-platform/src/cpal/device.rs:352 ` )
588+ - [x] Platform enumeration implemented (` lambda_platform::cpal ` )
589+ (` crates/lambda-rs-platform/src/cpal/device.rs:807 ` )
590+ - [x] Platform builder implemented (` lambda_platform::cpal ` )
591+ (` crates/lambda-rs-platform/src/cpal/device.rs:365 ` )
579592- API Surface
580- - [ ] Public ` lambda-rs ` types implemented: ` AudioOutputDevice ` ,
593+ - [x ] Public ` lambda ` types implemented: ` AudioOutputDevice ` ,
581594 ` AudioOutputDeviceInfo ` , ` AudioOutputDeviceBuilder ` , ` AudioCallbackInfo ` ,
582- ` AudioOutputWriter ` , ` AudioError `
583- - [ ] Internal platform types implemented: ` AudioDevice ` , ` AudioDeviceInfo ` ,
595+ ` AudioOutputWriter ` , ` AudioError ` ( ` crates/lambda-rs/src/audio.rs:12 ` )
596+ - [x ] Internal platform types implemented: ` AudioDevice ` , ` AudioDeviceInfo ` ,
584597 ` AudioDeviceBuilder ` , ` AudioCallbackInfo ` , ` AudioOutputWriter ` , ` AudioError `
585- - [ ] ` lambda-rs::audio ` does not re-export ` lambda-rs-platform ` types
598+ (` crates/lambda-rs-platform/src/cpal/device.rs:12 ` )
599+ - [x] ` lambda::audio ` does not re-export ` lambda-rs-platform ` types
600+ (` crates/lambda-rs/src/audio.rs:10 ` )
586601- Validation and Errors
587- - [ ] Invalid builder inputs rejected (sample rate and channel count)
588- - [ ] Descriptive ` AudioError ` variants emitted on failures
589- - [ ] Unsupported configurations reported via ` AudioError::UnsupportedConfig `
602+ - [x] Invalid builder inputs rejected (sample rate and channel count)
603+ (` crates/lambda-rs-platform/src/cpal/device.rs:403 ` ,
604+ ` crates/lambda-rs-platform/src/cpal/device.rs:847 ` )
605+ - [x] Descriptive ` AudioError ` variants emitted on failures
606+ (` crates/lambda-rs/src/audio.rs:65 ` ,
607+ ` crates/lambda-rs-platform/src/cpal/device.rs:265 ` )
608+ - [x] Unsupported configurations reported via ` AudioError::UnsupportedConfig `
609+ (` crates/lambda-rs-platform/src/cpal/device.rs:800 ` ,
610+ ` crates/lambda-rs/src/audio.rs:72 ` )
590611- Documentation and Examples
591- - [ ] ` docs/features.md ` updated with audio feature documentation
592- - [ ] Example added demonstrating audible playback (behind ` audio-output-device ` )
593- - [ ] ` lambda-rs ` audio facade implemented
594-
595- For each checked item, include a reference to a commit, pull request, or file
596- path that demonstrates the implementation.
612+ - [x] ` docs/features.md ` updated with audio feature documentation
613+ (` docs/features.md:1 ` )
614+ - [x] Example added demonstrating audible playback (behind ` audio-output-device ` )
615+ (` crates/lambda-rs/examples/audio_sine_wave.rs:1 ` )
616+ - [x] ` lambda-rs ` audio facade implemented (` crates/lambda-rs/src/audio.rs:1 ` )
597617
598618## Verification and Testing
599619
@@ -603,7 +623,7 @@ This example is the primary application-facing reference.
603623
604624- Add ` crates/lambda-rs/examples/audio_sine_wave.rs ` (feature:
605625 ` audio-output-device ` , enabled by default) that:
606- - Prints ` lambda_rs ::audio::enumerate_output_devices()` output.
626+ - Prints ` lambda ::audio::enumerate_output_devices()` output.
607627 - Builds the default output device via the facade builder and plays a
608628 deterministic 440 Hz tone for at least 2 seconds.
609629
@@ -614,7 +634,7 @@ Unit tests (crate: `lambda-rs-platform`)
614634 - ` with_sample_rate ` and ` with_channels ` override requested values.
615635 - Invalid values (` 0 ` ) are rejected.
616636- Enumeration
617- - ` enumerate_devices ` returns ` Ok(_) ` and does not panic.
637+ - ` enumerate_devices ` returns ` Result<_, _> ` and does not panic.
618638
619639Commands
620640
@@ -633,12 +653,18 @@ Manual checks
633653
634654## Changelog
635655
656+ - 2026-01-30 (v0.1.12) — Populate the requirements checklist with file
657+ references matching the implemented surface.
658+ - 2026-01-30 (v0.1.11) — Align examples with the ` lambda ` crate name, document
659+ the internal ` lambda_platform::cpal ` path and pin, and refine default
660+ configuration selection requirements to match the implementation.
636661- 2026-01-30 (v0.1.10) — Enable ` lambda-rs ` audio features by default.
637662- 2026-01-29 (v0.1.9) — Fix YAML front matter to use a single ` version ` field.
638663- 2026-01-29 (v0.1.8) — Make the ` lambda-rs ` facade example the primary
639664 reference and remove the platform example requirement.
640665- 2026-01-29 (v0.1.7) — Rename the platform audio implementation module to
641- ` lambda-rs-platform::cpal ` to reflect the internal backend.
666+ ` lambda_platform::cpal ` (package: ` lambda-rs-platform ` ) to reflect the
667+ internal backend.
642668- 2026-01-29 (v0.1.6) — Specify ` lambda-rs ` as the only supported
643669 application-facing API and treat ` lambda-rs-platform ` as internal.
644670- 2026-01-29 (v0.1.5) — Specify how ` lambda-rs ` applications enumerate devices
0 commit comments