Skip to main content

khora_core/audio/
device.rs

1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Defines the abstract [`AudioDevice`] / [`AudioStream`] traits.
16//!
17//! An `AudioDevice` is a *factory* for an output stream: call
18//! [`AudioDevice::open`] once and you get a long-lived [`AudioStream`]
19//! handle whose `Drop` stops the stream. The device itself is consumed
20//! during opening — it has no state worth keeping after the stream is
21//! live.
22//!
23//! The backend's hardware callback drains samples from the
24//! [`AudioMixBus`](super::mix_bus::AudioMixBus) provided to `open`. Audio
25//! lanes write into the same bus from the main thread; the bus is the
26//! sole synchronisation boundary between the two worlds.
27
28use std::sync::Arc;
29
30use anyhow::Result;
31
32use super::mix_bus::AudioMixBus;
33
34/// A struct providing information about the audio stream.
35#[derive(Debug, Clone, Copy)]
36pub struct StreamInfo {
37    /// The number of channels (e.g., 2 for stereo).
38    pub channels: u16,
39    /// The number of samples per second (e.g., 44100 Hz).
40    pub sample_rate: u32,
41}
42
43/// Factory for an audio output stream.
44///
45/// The device is consumed during [`AudioDevice::open`] — backends store
46/// their hardware handles inside the returned [`AudioStream`].
47pub trait AudioDevice: Send + Sync {
48    /// Opens the output stream. The backend's audio callback will pull
49    /// samples from `mix_bus` on a dedicated real-time thread.
50    ///
51    /// The returned handle keeps the stream alive for as long as it
52    /// exists. Dropping the handle stops the stream.
53    fn open(self: Box<Self>, mix_bus: Arc<dyn AudioMixBus>) -> Result<Box<dyn AudioStream>>;
54}
55
56/// Live audio stream handle. Drop = stop.
57pub trait AudioStream: Send + Sync {
58    /// Channel count and sample rate of the stream as actually opened by
59    /// the backend (may differ from the bus's nominal info if the
60    /// hardware imposed a different format).
61    fn stream_info(&self) -> StreamInfo;
62}