feat(ai-formatting): collapse adjacent repetitions in Clean/Smart modes + chore(audio): swap deprecated cpal .name() for description-based helper
ai-formatting:
- rule_based.rs: collapse_repetitions() merges adjacent duplicate
tokens like 'I I can' -> 'I can' and 'think think that' -> 'think
that'. Normalises case and punctuation before comparison.
- pipeline.rs: post_process now calls collapse_repetitions when
format_mode is Clean or Smart. Added unit coverage.
audio:
- capture.rs: replace the seven deprecated cpal DeviceTrait::name()
call sites with a device_display_name() helper that uses the
non-deprecated description() path. Keeps identical behaviour,
silences compile warnings, ready for cpal upgrade.
Addresses the 'Christ. Christ.' live-transcription boundary duplicate
Jake saw during Group 1 dogfooding. Does not fix all cross-chunk
overlap cases (see live.rs OVERLAP_SAMPLES for the root cause) but
catches the common stutter pattern at post-processing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -95,7 +95,7 @@ impl MicrophoneCapture {
|
||||
let host = cpal::default_host();
|
||||
let default_name = host
|
||||
.default_input_device()
|
||||
.and_then(|d| d.name().ok())
|
||||
.and_then(|d| device_display_name(&d))
|
||||
.unwrap_or_default();
|
||||
|
||||
let devices = host
|
||||
@@ -110,7 +110,7 @@ impl MicrophoneCapture {
|
||||
|
||||
let mut out = Vec::new();
|
||||
for device in devices {
|
||||
let name = device.name().unwrap_or_else(|_| "<unnamed>".to_string());
|
||||
let name = device_display_name(&device).unwrap_or_else(|| "<unnamed>".to_string());
|
||||
let (sample_rate, channels) = match device.default_input_config() {
|
||||
Ok(cfg) => (cfg.sample_rate(), cfg.channels() as u16),
|
||||
Err(_) => (0, 0),
|
||||
@@ -143,7 +143,7 @@ impl MicrophoneCapture {
|
||||
.map_err(|e| KonError::AudioCaptureFailed(format!("input_devices: {e}")))?;
|
||||
|
||||
for device in devices {
|
||||
let name = device.name().unwrap_or_default();
|
||||
let name = device_display_name(&device).unwrap_or_default();
|
||||
if name == device_name {
|
||||
eprintln!("[kon-audio] start_with_device: opening explicit device '{name}'");
|
||||
return open_and_validate(device, &name, /* require_audio = */ true);
|
||||
@@ -169,7 +169,7 @@ impl MicrophoneCapture {
|
||||
let host = cpal::default_host();
|
||||
let default_name = host
|
||||
.default_input_device()
|
||||
.and_then(|d| d.name().ok())
|
||||
.and_then(|d| device_display_name(&d))
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut all_devices: Vec<cpal::Device> =
|
||||
@@ -181,7 +181,7 @@ impl MicrophoneCapture {
|
||||
|
||||
// Sort: default first, then non-monitor, then monitor-as-last-resort.
|
||||
all_devices.sort_by_key(|d| {
|
||||
let n = d.name().unwrap_or_default();
|
||||
let n = device_display_name(d).unwrap_or_default();
|
||||
let is_default = !default_name.is_empty() && n == default_name;
|
||||
let is_monitor = is_monitor_name(&n);
|
||||
// Smaller key = tried first.
|
||||
@@ -201,7 +201,7 @@ impl MicrophoneCapture {
|
||||
|
||||
// First pass: require real audio energy.
|
||||
for device in &all_devices {
|
||||
let name = device.name().unwrap_or_default();
|
||||
let name = device_display_name(device).unwrap_or_default();
|
||||
if is_monitor_name(&name) {
|
||||
continue; // Save monitor sources for second pass.
|
||||
}
|
||||
@@ -219,7 +219,7 @@ impl MicrophoneCapture {
|
||||
"[kon-audio] no non-monitor mic produced audio; falling back to monitor/loopback sources"
|
||||
);
|
||||
for device in &all_devices {
|
||||
let name = device.name().unwrap_or_default();
|
||||
let name = device_display_name(device).unwrap_or_default();
|
||||
match open_and_validate(device.clone(), &name, false) {
|
||||
Ok(result) => {
|
||||
eprintln!(
|
||||
@@ -267,6 +267,13 @@ fn is_monitor_name(name: &str) -> bool {
|
||||
|| lower.contains("loopback")
|
||||
}
|
||||
|
||||
fn device_display_name(device: &cpal::Device) -> Option<String> {
|
||||
device
|
||||
.description()
|
||||
.ok()
|
||||
.map(|description| description.name().to_string())
|
||||
}
|
||||
|
||||
/// Pull the CARD= value from an ALSA device string.
|
||||
///
|
||||
/// `sysdefault:CARD=Microphones` → `Some("Microphones")`
|
||||
|
||||
Reference in New Issue
Block a user