feat(audio): A.5 — surface mobile voice-preset + effects toggles in AudioEngineConfig
The Beta scope for mobile DSP is OS-source-driven (Android `MediaRecorder.AudioSource.VOICE_COMMUNICATION`, iOS `AVAudioSession.Mode.voiceChat`) — letting the platform's built-in AEC / NS engage instead of shipping our own DSP chain on constrained devices. Linux desktop stays a deliberate no-op: PipeWire / ALSA's default source is correct for desktop voice and adding a software AEC there would regress against an already-good baseline. This commit lands the *config surface* through every layer: * `AudioEngineConfig` gains `effects: AudioEffects` (mirrors the DEC-007/008/009/010 toggles) and `mobile_voice_preset: bool` (default `true`). * On Android, `AudioEngine::start` logs the preset + effects requests so a future cpal / Oboe upstream switch can be observed via the redacted diagnostic export. * On iOS, the same log line documents the binding gap — Chanora iOS audio is documented-only for Beta per the release notes. * On Linux desktop, the flags are honoured by name but the engine continues to use the default ALSA / PipeWire source. No behaviour change. RISK-AUDIO-MOBILE-001 (new) tracks the actual preset switch. The follow-up work either pulls in an Oboe-based input host or waits for cpal upstream to expose `set_input_preset`. Either way the config flag is forward-compatible — callers do not need to change when the binding lands.
This commit is contained in:
@@ -43,6 +43,25 @@ pub struct AudioEngineConfig {
|
|||||||
/// Initial PTT state. When false the encoder is bypassed and no
|
/// Initial PTT state. When false the encoder is bypassed and no
|
||||||
/// outbound packets are produced.
|
/// outbound packets are produced.
|
||||||
pub ptt_initial: bool,
|
pub ptt_initial: bool,
|
||||||
|
/// Audio-effect toggles. The struct is honoured by *naming* but
|
||||||
|
/// the filters themselves are still no-op in Beta — see the
|
||||||
|
/// crate-level docs and DEC-007/008/009/010.
|
||||||
|
pub effects: crate::AudioEffects,
|
||||||
|
/// A.5 mobile: prefer the OS-provided "voice communication"
|
||||||
|
/// audio source on mobile platforms (Android
|
||||||
|
/// `MediaRecorder.AudioSource.VOICE_COMMUNICATION`, iOS
|
||||||
|
/// `AVAudioSession.Mode.voiceChat`). On Linux desktop this is
|
||||||
|
/// ignored — the DSP chain stays a no-op and we use the
|
||||||
|
/// default ALSA/PipeWire source.
|
||||||
|
///
|
||||||
|
/// Beta status: the *config flag* is plumbed through every
|
||||||
|
/// layer; the *Android-side preset switch* is documented but
|
||||||
|
/// not yet wired through cpal, which currently uses the
|
||||||
|
/// AAudio default input. RISK-AUDIO-MOBILE-001 tracks this gap.
|
||||||
|
/// Setting `true` is a forward-compatible no-op for Beta and
|
||||||
|
/// will become active once cpal exposes input-preset hooks (or
|
||||||
|
/// when Chanora ships an Oboe-based fork).
|
||||||
|
pub mobile_voice_preset: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AudioEngineConfig {
|
impl Default for AudioEngineConfig {
|
||||||
@@ -50,6 +69,8 @@ impl Default for AudioEngineConfig {
|
|||||||
Self {
|
Self {
|
||||||
mic_gain: 1.0,
|
mic_gain: 1.0,
|
||||||
ptt_initial: false,
|
ptt_initial: false,
|
||||||
|
effects: crate::AudioEffects::default(),
|
||||||
|
mobile_voice_preset: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,6 +135,36 @@ impl AudioEngine {
|
|||||||
"starting audio engine"
|
"starting audio engine"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// A.5 mobile-only preset acknowledgement. On Linux desktop
|
||||||
|
// the flag is ignored; on Android we log it so a future cpal
|
||||||
|
// / Oboe wiring can be observed in the diagnostic export.
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
{
|
||||||
|
if cfg.mobile_voice_preset {
|
||||||
|
info!(
|
||||||
|
target: "chanora_audio",
|
||||||
|
"android: mobile_voice_preset requested (RISK-AUDIO-MOBILE-001 — flag plumbed, switch pending cpal upstream)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if cfg.effects.aec || cfg.effects.noise_suppression {
|
||||||
|
info!(
|
||||||
|
target: "chanora_audio",
|
||||||
|
aec = cfg.effects.aec,
|
||||||
|
ns = cfg.effects.noise_suppression,
|
||||||
|
"android: effects requested; awaiting OS-source switch to engage hardware AEC/NS"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
|
{
|
||||||
|
if cfg.mobile_voice_preset {
|
||||||
|
info!(
|
||||||
|
target: "chanora_audio",
|
||||||
|
"ios: voice-chat session mode requested (binding pending — Chanora iOS audio is documented-only for Beta)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let ptt = Arc::new(AtomicBool::new(cfg.ptt_initial));
|
let ptt = Arc::new(AtomicBool::new(cfg.ptt_initial));
|
||||||
let frames_sent = Arc::new(AtomicU32::new(0));
|
let frames_sent = Arc::new(AtomicU32::new(0));
|
||||||
let frames_received = Arc::new(AtomicU32::new(0));
|
let frames_received = Arc::new(AtomicU32::new(0));
|
||||||
|
|||||||
Reference in New Issue
Block a user