pub struct AudioService { /* private fields */ }Expand description
The main service that orchestrates real-time audio loopback between an input and output device.
AudioService manages the full lifecycle of the audio processing pipeline:
- Device management — holds references to the active CPAL input/output devices
through an
AudioHandlerTraitimplementation and supports hot-swapping either device without a full restart. - Resampling — on
start_loopbackthe input and output sample rates are compared and aResamplePolicyis selected automatically:input == output→ no resampling, zero overhead.input > output→ downsample before the DSP chain.input < output→ upsample after the DSP chain.
- DSP chain — every sample passes through gain, tone stack, and master volume
processors in order. Additional processors can be inserted into
start_loopback’srun_dspclosure. - Thread lifecycle — the loopback runs on a dedicated background thread with a
lock-free ring buffer between the CPAL callbacks and the worker; the thread is
cleanly shut down via
stop_loopback.
Implementations§
Source§impl AudioService
Auto-generated by derive_getters::Getters.
impl AudioService
Auto-generated by derive_getters::Getters.
Sourcepub fn audio_handler(&self) -> &Arc<dyn AudioHandlerTrait>
pub fn audio_handler(&self) -> &Arc<dyn AudioHandlerTrait>
Get field audio_handler from instance of AudioService.
Sourcepub fn loopback_thread(&self) -> &Option<JoinHandle<()>>
pub fn loopback_thread(&self) -> &Option<JoinHandle<()>>
Get field loopback_thread from instance of AudioService.
Sourcepub fn current_channel_id(&self) -> &u32
pub fn current_channel_id(&self) -> &u32
Get field current_channel_id from instance of AudioService.
Sourcepub fn master_volume(&self) -> &Arc<AtomicF32>
pub fn master_volume(&self) -> &Arc<AtomicF32>
Get field master_volume from instance of AudioService.
Sourcepub fn next_channel_id(&self) -> &u32
pub fn next_channel_id(&self) -> &u32
Get field next_channel_id from instance of AudioService.
Sourcepub fn spectrum_tap(&self) -> &Arc<SpectrumTap>
pub fn spectrum_tap(&self) -> &Arc<SpectrumTap>
Get field spectrum_tap from instance of AudioService.
Source§impl AudioService
impl AudioService
Sourcepub fn dsp_chain_sample_rate(&self) -> u32
pub fn dsp_chain_sample_rate(&self) -> u32
Returns the sample rate at which the DSP chain effectively runs.
With current resampling policy, DSP executes at the lower of input/output rates.
Sourcepub fn new(
input_device: Device,
output_device: Device,
input_config: StreamConfig,
output_config: StreamConfig,
) -> Self
pub fn new( input_device: Device, output_device: Device, input_config: StreamConfig, output_config: StreamConfig, ) -> Self
Creates a new AudioService using the provided CPAL input/output devices and stream config.
An AudioHandler is constructed internally from the given parameters.
§Arguments
input_device- The CPAL device to capture audio from.output_device- The CPAL device to send processed audio to.input_config- The [StreamConfig] used for the input stream.output_config- The [StreamConfig] used for the output stream.
Sourcepub fn new_with_handler(handler: Arc<dyn AudioHandlerTrait>) -> Self
pub fn new_with_handler(handler: Arc<dyn AudioHandlerTrait>) -> Self
Creates an AudioService with a custom handler.
This constructor is primarily intended for unit and integration testing,
where a mock AudioHandlerTrait implementation can be injected in place
of a real AudioHandler.
§Arguments
handler- AnArc-wrapped implementation ofAudioHandlerTrait.
Sourcepub fn start_loopback(&mut self)
pub fn start_loopback(&mut self)
Starts the audio loopback on a dedicated background thread.
On startup the service:
- Reads the input and output sample rates from the active
AudioHandlerTrait. - Selects a
ResamplePolicybased on those rates (logged atinfolevel). - Builds a pair of lock-free ring buffers sized to the larger of the two rates.
- Asks the handler to open the input and output CPAL streams.
- Spawns a worker thread that:
- Pops samples from the input buffer.
- Routes them through the
ResamplePolicywhich interleavesrun_dspat the correct point (before or after resampling). - Pushes results into the output buffer.
- On shutdown, flushes any remaining resampler tail before exiting.
If the loopback is already active this method is a no-op.
Sourcepub fn stop_loopback(&mut self)
pub fn stop_loopback(&mut self)
Stops the audio loopback and joins the background thread.
Unparks the loopback thread, signals the inner worker to shut down, and waits for both threads to finish. If the loopback is not currently active this method is a no-op.
Sourcepub fn set_master_volume(&self, master_volume: f32)
pub fn set_master_volume(&self, master_volume: f32)
Sourcepub fn set_input_device(&mut self, input: Device, input_config: StreamConfig)
pub fn set_input_device(&mut self, input: Device, input_config: StreamConfig)
Switches the audio input device without interrupting playback longer than necessary.
Constructs a new AudioHandler that pairs the given input device with the
existing output device and stream config, then delegates to set_audio_handler.
§Arguments
input- The new CPAL input device to capture audio from.
Sourcepub fn set_output_device(&mut self, output: Device, output_config: StreamConfig)
pub fn set_output_device(&mut self, output: Device, output_config: StreamConfig)
Switches the audio output device without interrupting playback longer than necessary.
Constructs a new AudioHandler that pairs the existing input device with the
given output device and stream config, then delegates to set_audio_handler.
§Arguments
output- The new CPAL output device to send processed audio to.
Sourcepub fn toggle_loopback(&mut self, is_on: bool)
pub fn toggle_loopback(&mut self, is_on: bool)
Toggles the audio loopback on or off.
- If
is_onistrueand the loopback is not active,start_loopbackis called. - If
is_onisfalseand the loopback is active,stop_loopbackis called. - If the requested state already matches the current state, this method is a no-op.
Sourcepub fn add_channel(&mut self, channel_name: String) -> u32
pub fn add_channel(&mut self, channel_name: String) -> u32
Adds a new channel to the channel list and return the new channel.
New channels are initialized with default values and the current_channel_id is updated to the new channel’s id.
§Arguments
channel_name- The name of the new channel (30 characters max).
Sourcepub fn channels_mut(&mut self) -> &mut Vec<Channel>
pub fn channels_mut(&mut self) -> &mut Vec<Channel>
Returns a mutable reference to the channel list, allowing channels to be modified or reordered.
Sourcepub fn remove_channel(&mut self, channel_id: u32)
pub fn remove_channel(&mut self, channel_id: u32)
Removes the channel with the given id from the channel list and sets current_channel_id to 0 (default channel).
§Arguments
channel_id- The id of the channel to remove. Cannot be 0 (default channel).
Sourcepub fn set_current_channel_id(&mut self, new_current_channel_id: u32)
pub fn set_current_channel_id(&mut self, new_current_channel_id: u32)
Sets the current channel id, restarting the loopback if it was active to ensure the new channel’s parameters are applied.
§Arguments
new_current_channel_id- The id of the channel to set as current. Must exist in the channel list.
Sourcepub fn buffer_size_frames(&self) -> u32
pub fn buffer_size_frames(&self) -> u32
Returns the current buffer size in frames.
If the handler uses BufferSize::Default, returns 256 as a practical fallback.
Sourcepub fn set_buffer_size_frames(&mut self, frames: u32) -> Result<(), String>
pub fn set_buffer_size_frames(&mut self, frames: u32) -> Result<(), String>
Updates the buffer size for both input and output streams.
Rebuilds the audio handler with a BufferSize::Fixed(frames) config and
restarts the loopback if it was active.
§Arguments
frames- The desired buffer size in frames.
Sourcepub fn apply_amp_config(&mut self, config: AmpConfigDto)
pub fn apply_amp_config(&mut self, config: AmpConfigDto)
Applies a persisted amp configuration snapshot to the live service.
Restore behavior summary:
- channels are recreated from the persisted DTOs,
- gain, volume, tone stack, and effect-chain state are restored,
- if the snapshot contains no channels, a default channel is created,
- if the stored current channel no longer exists, the first restored channel becomes the active channel,
next_channel_idis recalculated from the restored set,- loopback is toggled according to
config.is_active.
Note that the current JSON persistence implementation always loads with
is_active = false, so persisted sessions restart with loopback turned
off even though this method is capable of applying either state.