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` trait.
16
17use anyhow::Result;
18
19/// A type alias for the audio mixing callback function.
20type MixCallback = Box<dyn FnMut(&mut [f32], &StreamInfo) + Send>;
21
22/// A struct providing information about the audio stream.
23#[derive(Debug, Clone, Copy)]
24pub struct StreamInfo {
25 /// The number of channels (e.g., 2 for stereo).
26 pub channels: u16,
27 /// The number of samples per second (e.g., 44100 Hz).
28 pub sample_rate: u32,
29}
30
31/// The abstract contract for a hardware audio device backend.
32///
33/// This trait is the boundary between the engine's audio logic (mixing, spatialization)
34/// and the platform-specific infrastructure that actually communicates with the sound card.
35/// Its design is callback-driven: the engine provides a function that the backend
36/// calls whenever it needs more audio data.
37pub trait AudioDevice: Send + Sync {
38 /// Initializes and starts the audio stream.
39 ///
40 /// This method consumes the `AudioDevice` as it typically runs for the lifetime
41 /// of the application.
42 ///
43 /// # Arguments
44 ///
45 /// * `on_mix_needed`: A closure that will be called repeatedly by the audio backend
46 /// on a dedicated audio thread. This closure is responsible for filling the
47 /// provided `output_buffer` with the next chunk of audio samples. The samples
48 /// should be interleaved for multi-channel audio (e.g., `[L, R, L, R, ...]`).
49 ///
50 /// # Returns
51 ///
52 /// A `Result` indicating success or failure in initializing the audio stream.
53 fn start(self: Box<Self>, on_mix_needed: MixCallback) -> Result<()>;
54}