feat: stabilize voice activity and audio routing
This commit is contained in:
@@ -270,23 +270,19 @@ Future<BridgeAudioProcessingStats> audioProcessingStats() =>
|
||||
Future<BridgeAudioDeviceList> listAudioDevices() =>
|
||||
RustLib.instance.api.crateApiListAudioDevices();
|
||||
|
||||
/// Set the preferred input device by name. Takes effect on next
|
||||
/// Set the preferred input device by id. Takes effect on next
|
||||
/// `start_audio`.
|
||||
Future<void> setInputDevice({String? name}) =>
|
||||
RustLib.instance.api.crateApiSetInputDevice(name: name);
|
||||
Future<void> setInputDevice({String? id}) =>
|
||||
RustLib.instance.api.crateApiSetInputDevice(id: id);
|
||||
|
||||
/// Set the preferred output device by name.
|
||||
Future<void> setOutputDevice({String? name}) =>
|
||||
RustLib.instance.api.crateApiSetOutputDevice(name: name);
|
||||
/// Set the preferred output device by id.
|
||||
Future<void> setOutputDevice({String? id}) =>
|
||||
RustLib.instance.api.crateApiSetOutputDevice(id: id);
|
||||
|
||||
/// Configure the VAD model path.
|
||||
Future<void> setVadModelPath({required String path}) =>
|
||||
RustLib.instance.api.crateApiSetVadModelPath(path: path);
|
||||
|
||||
/// Configure the TEN VAD ONNX model path.
|
||||
Future<void> setTenVadModelPath({required String path}) =>
|
||||
RustLib.instance.api.crateApiSetTenVadModelPath(path: path);
|
||||
|
||||
/// Enable or disable audio debug WAV dumping.
|
||||
Future<void> enableAudioDebugWavDump({required bool enabled}) =>
|
||||
RustLib.instance.api.crateApiEnableAudioDebugWavDump(enabled: enabled);
|
||||
@@ -321,24 +317,47 @@ enum BridgeAudioBackend {
|
||||
|
||||
/// Audio device info from the platform.
|
||||
class BridgeAudioDevice {
|
||||
/// Stable platform-reported device identifier.
|
||||
final String id;
|
||||
|
||||
/// Human-readable device name.
|
||||
final String name;
|
||||
|
||||
/// Additional device details useful for disambiguation.
|
||||
final String details;
|
||||
|
||||
/// True if the OS reports this as the default device.
|
||||
final bool isDefault;
|
||||
|
||||
const BridgeAudioDevice({required this.name, required this.isDefault});
|
||||
/// True if Chanora currently has this device pinned.
|
||||
final bool isSelected;
|
||||
|
||||
const BridgeAudioDevice({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.details,
|
||||
required this.isDefault,
|
||||
required this.isSelected,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode => name.hashCode ^ isDefault.hashCode;
|
||||
int get hashCode =>
|
||||
id.hashCode ^
|
||||
name.hashCode ^
|
||||
details.hashCode ^
|
||||
isDefault.hashCode ^
|
||||
isSelected.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is BridgeAudioDevice &&
|
||||
runtimeType == other.runtimeType &&
|
||||
id == other.id &&
|
||||
name == other.name &&
|
||||
isDefault == other.isDefault;
|
||||
details == other.details &&
|
||||
isDefault == other.isDefault &&
|
||||
isSelected == other.isSelected;
|
||||
}
|
||||
|
||||
/// List of available audio devices.
|
||||
@@ -512,6 +531,21 @@ class BridgeAudioProcessingStats {
|
||||
/// Clipped samples.
|
||||
final BigInt clippedSamples;
|
||||
|
||||
/// Number of effectively silent processed capture frames.
|
||||
final BigInt zeroFrames;
|
||||
|
||||
/// Number of processed capture frames.
|
||||
final BigInt captureFrames;
|
||||
|
||||
/// Input callbacks carrying 10 ms of audio.
|
||||
final BigInt callbacks10Ms;
|
||||
|
||||
/// Input callbacks carrying 20 ms of audio.
|
||||
final BigInt callbacks20Ms;
|
||||
|
||||
/// Input callbacks carrying other sizes.
|
||||
final BigInt callbacksOther;
|
||||
|
||||
/// Sonora enabled.
|
||||
final bool sonoraEnabled;
|
||||
|
||||
@@ -536,6 +570,11 @@ class BridgeAudioProcessingStats {
|
||||
required this.outputUnderruns,
|
||||
required this.callbackXruns,
|
||||
required this.clippedSamples,
|
||||
required this.zeroFrames,
|
||||
required this.captureFrames,
|
||||
required this.callbacks10Ms,
|
||||
required this.callbacks20Ms,
|
||||
required this.callbacksOther,
|
||||
required this.sonoraEnabled,
|
||||
required this.platformVoiceProcessingEnabled,
|
||||
});
|
||||
@@ -559,6 +598,11 @@ class BridgeAudioProcessingStats {
|
||||
outputUnderruns.hashCode ^
|
||||
callbackXruns.hashCode ^
|
||||
clippedSamples.hashCode ^
|
||||
zeroFrames.hashCode ^
|
||||
captureFrames.hashCode ^
|
||||
callbacks10Ms.hashCode ^
|
||||
callbacks20Ms.hashCode ^
|
||||
callbacksOther.hashCode ^
|
||||
sonoraEnabled.hashCode ^
|
||||
platformVoiceProcessingEnabled.hashCode;
|
||||
|
||||
@@ -584,6 +628,11 @@ class BridgeAudioProcessingStats {
|
||||
outputUnderruns == other.outputUnderruns &&
|
||||
callbackXruns == other.callbackXruns &&
|
||||
clippedSamples == other.clippedSamples &&
|
||||
zeroFrames == other.zeroFrames &&
|
||||
captureFrames == other.captureFrames &&
|
||||
callbacks10Ms == other.callbacks10Ms &&
|
||||
callbacks20Ms == other.callbacks20Ms &&
|
||||
callbacksOther == other.callbacksOther &&
|
||||
sonoraEnabled == other.sonoraEnabled &&
|
||||
platformVoiceProcessingEnabled ==
|
||||
other.platformVoiceProcessingEnabled;
|
||||
@@ -976,6 +1025,12 @@ sealed class BridgeEvent with _$BridgeEvent {
|
||||
required BridgeMessageTarget target,
|
||||
}) = BridgeEvent_ChatMessage;
|
||||
|
||||
/// Human-readable server activity surfaced from protocol bookkeeping events.
|
||||
const factory BridgeEvent.serverActivity({
|
||||
/// TeamSpeak-style activity line.
|
||||
required String message,
|
||||
}) = BridgeEvent_ServerActivity;
|
||||
|
||||
/// Audio route changed (speaker/earpiece/BT/wired).
|
||||
const factory BridgeEvent.audioRouteChanged({
|
||||
/// The new audio route.
|
||||
@@ -1169,9 +1224,6 @@ enum BridgeVadBackend {
|
||||
/// Silero ONNX VAD.
|
||||
sileroOnnx,
|
||||
|
||||
/// TEN VAD.
|
||||
tenVad,
|
||||
|
||||
/// WebRTC fallback VAD.
|
||||
webrtcVad,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user