aboutsummaryrefslogtreecommitdiffstats
path: root/crates/asist-audio/src/lib.rs
diff options
context:
space:
mode:
authorelvis <elvis@claros.ar>2026-09-26 20:20:19 -0300
committerelvis <elvis@claros.ar>2026-09-26 20:20:19 -0300
commit8518a63f55153e7f45fd49ad6caff5555f4e374f (patch)
tree636684eea3fa6f35d78282ab95eb687ef49154af /crates/asist-audio/src/lib.rs
parent69de76dc9cbedc6092d1e5ce84094a8030de1470 (diff)
downloadasist-p-8518a63f55153e7f45fd49ad6caff5555f4e374f.tar.gz
asist-p-8518a63f55153e7f45fd49ad6caff5555f4e374f.zip
Translate code, comments, logs and terminal UI to English; add English README; rename scriptsHEADmain
Diffstat (limited to 'crates/asist-audio/src/lib.rs')
-rw-r--r--crates/asist-audio/src/lib.rs58
1 files changed, 29 insertions, 29 deletions
diff --git a/crates/asist-audio/src/lib.rs b/crates/asist-audio/src/lib.rs
index de3f002..a339d16 100644
--- a/crates/asist-audio/src/lib.rs
+++ b/crates/asist-audio/src/lib.rs
@@ -1,35 +1,35 @@
-//! Entrada y salida de audio, y el detector de voz que las separa en turnos.
+//! Audio input and output, and the voice detector that splits them into turns.
//!
-//! La regla que gobierna este crate: **la retrollamada de audio no bloquea
-//! nunca**. cpal la ejecuta en un hilo de tiempo real y cualquier espera ahí
-//! se oye como un chasquido, así que se limita a copiar muestras a un canal
-//! (entrada) o a vaciar un anillo ya rellenado (salida). Todo el trabajo real
-//! —remuestreo, VAD, HTTP— ocurre en hilos normales al otro lado.
+//! The rule that governs this crate: **the audio callback never blocks**. cpal
+//! runs it on a real-time thread and any wait there is heard as a click, so it
+//! only copies samples to a channel (input) or drains an already filled ring
+//! (output). All the real work (resampling, VAD, HTTP) happens on regular
+//! threads on the other side.
pub mod capture;
pub mod playback;
pub mod vad;
-/// Se reexporta para que el binario pueda listar dispositivos sin volver a
-/// declarar cpal y arriesgarse a resolver otra versión.
+/// Re-exported so the binary can list devices without declaring cpal
+/// again and risking resolving another version.
pub use cpal;
pub use capture::{Capture, CaptureBlock, InputFormat};
pub use playback::{detached_handle, Playback, PlaybackHandle};
pub use vad::{Gate, Segmenter, Utterance, VoiceEvent};
-/// Frecuencia a la que trabaja Canary. La captura se abre directamente aquí
-/// cuando el dispositivo lo permite, lo que quita el remuestreo del camino.
+/// Rate Canary works at. Capture is opened directly at this rate when the
+/// device allows it, which takes resampling off the path.
pub const ASR_SAMPLE_RATE: u32 = 16_000;
-/// Frecuencia a la que sintetiza qwentts.
+/// Rate qwentts synthesizes at.
pub const TTS_SAMPLE_RATE: u32 = 24_000;
-/// Nombre legible de un dispositivo.
+/// Human-readable device name.
///
-/// `DeviceTrait::name` está obsoleto en cpal 0.17 a favor de `description`,
-/// que devuelve una ficha entera; aquí sólo interesa el nombre, y tener un
-/// único sitio donde extraerlo evita repetir el desempaquetado.
+/// `DeviceTrait::name` is deprecated in cpal 0.17 in favour of `description`,
+/// which returns a whole record; only the name matters here, and having a
+/// single place to extract it avoids repeating the unwrapping.
pub fn describe(device: &impl cpal::traits::DeviceTrait) -> String {
device
.description()
@@ -37,7 +37,7 @@ pub fn describe(device: &impl cpal::traits::DeviceTrait) -> String {
.unwrap_or_else(|_| "desconocido".into())
}
-/// Nivel RMS de un bloque, la medida con la que el VAD decide.
+/// RMS level of a block, the measure the VAD decides on.
pub fn rms(samples: &[f32]) -> f32 {
if samples.is_empty() {
return 0.0;
@@ -46,11 +46,11 @@ pub fn rms(samples: &[f32]) -> f32 {
(sum / samples.len() as f32).sqrt()
}
-/// Mezcla a mono y remuestrea linealmente a `target`.
+/// Mixes down to mono and resamples linearly to `target`.
///
-/// La interpolación lineal basta: el dispositivo ya entrega la señal limitada
-/// en banda, y un remuestreador decente costaría más que la decodificación a
-/// la que alimenta.
+/// Linear interpolation is enough: the device already delivers a
+/// band-limited signal, and a decent resampler would cost more than the
+/// decoding it feeds.
pub fn to_mono_at(samples: &[f32], format: InputFormat, target: u32) -> Vec<f32> {
let mono: Vec<f32> = if format.channels > 1 {
samples
@@ -78,7 +78,7 @@ pub fn to_mono_at(samples: &[f32], format: InputFormat, target: u32) -> Vec<f32>
.collect()
}
-/// Convierte s16le a f32 en [-1, 1]. Es el formato en el que el TTS entrega.
+/// Converts s16le to f32 in [-1, 1]. It is the format the TTS delivers.
pub fn s16le_to_f32(bytes: &[u8], out: &mut Vec<f32>) {
for pair in bytes.chunks_exact(2) {
let sample = i16::from_le_bytes([pair[0], pair[1]]);
@@ -91,13 +91,13 @@ mod tests {
use super::*;
#[test]
- fn el_rms_de_una_senal_constante_es_su_amplitud() {
+ fn rms_of_a_constant_signal_is_its_amplitude() {
assert!((rms(&[0.5; 100]) - 0.5).abs() < 1e-6);
assert_eq!(rms(&[]), 0.0);
}
#[test]
- fn el_estereo_se_mezcla_a_mono_promediando() {
+ fn stereo_is_mixed_to_mono_by_averaging() {
let format = InputFormat {
sample_rate: 16_000,
channels: 2,
@@ -107,17 +107,17 @@ mod tests {
}
#[test]
- fn el_remuestreo_ajusta_la_duracion() {
+ fn resampling_adjusts_the_duration() {
let format = InputFormat {
sample_rate: 48_000,
channels: 1,
};
let out = to_mono_at(&vec![0.0; 4800], format, 16_000);
- assert_eq!(out.len(), 1600, "48 kHz -> 16 kHz debe dividir por tres");
+ assert_eq!(out.len(), 1600, "48 kHz -> 16 kHz must divide by three");
}
#[test]
- fn a_la_misma_frecuencia_el_remuestreo_no_toca_nada() {
+ fn resampling_at_the_same_rate_changes_nothing() {
let format = InputFormat {
sample_rate: 16_000,
channels: 1,
@@ -127,7 +127,7 @@ mod tests {
}
#[test]
- fn s16le_recorre_el_rango_completo() {
+ fn s16le_covers_the_full_range() {
let mut out = Vec::new();
s16le_to_f32(&[0x00, 0x00, 0xff, 0x7f, 0x00, 0x80], &mut out);
assert_eq!(out[0], 0.0);
@@ -136,13 +136,13 @@ mod tests {
}
#[test]
- fn un_byte_suelto_no_produce_una_muestra_a_medias() {
+ fn stray_byte_does_not_produce_a_partial_sample() {
let mut out = Vec::new();
s16le_to_f32(&[0x00, 0x00, 0x11], &mut out);
assert_eq!(
out.len(),
1,
- "el byte impar se ignora en vez de corromper la muestra"
+ "the odd byte is ignored instead of corrupting the sample"
);
}
}