# Loros — registro de experimentos de voz modular para FINAZ

Fecha: 11 de septiembre de 2026.

> **Cambio de nombre previsto:** el proyecto y repositorio pasan a llamarse
> **Loros**. El directorio actual ya es `Loros`. Los identificadores
> históricos de ejecuciones y las carpetas `output/runs/carrier_*` no deben
> renombrarse: forman parte de la trazabilidad de los experimentos.

## Actualización 2026-09-11 — Comparación de frases largas con seed

A petición del usuario: dos textos ficticios de 34 palabras, cada uno como toma completa, montaje de dos bloques y montaje de cuatro bloques. Todas las fuentes con Charon, es-ES, seed 12345, GenerateContent y misma plantilla de instrucciones. Diez fuentes nuevas exitosas, sin reintentos. Los bloques se generaron aisladamente; el cierre es el mismo PCM en los cuatro montajes y la introducción se comparte entre ambos de cuatro bloques.

Recorte de extremos de baja energía y atenuación uniforme también en referencias para comparar niveles. Pausas añadidas de 80 ms en comas y 250 ms entre oraciones; sin fundidos ni cambios de tono/velocidad. Constructor `tools/pilot_seed_long.py` valida que cada tramo sea el PCM exacto de su unidad. La bitácora admite ahora A/B/C/D y accesos a las tres uniones.

Whisper Small reconoce contenido y cifras de las seis versiones; pendiente de escucha humana. La prueba compara longitudes de bloque usando seed, no atribuye causalidad al parámetro. Entrada `bitacora.html#seed-frases-largas`; informe `docs/SEED_FRASES_LARGAS.md`. Coste 0,033404 USD; acumulado documentado 0,788924 USD. Costes por toma en `qa/seed_long_coste.json`.

## Actualización 2026-09-11 — Subfrases aisladas con seed fijo

El usuario aclara que desea pedir activo, verbo y cantidad separadamente con la misma semilla, para combinarlos después. Piloto en `bitacora.html#seed-subfrases`: seis piezas independientes (Inditex, BBVA, sube, baja, un uno por ciento, un dos por ciento), ocho combinaciones y dos referencias completas.

Cuatro errores HTTP 400 para el verbo bajo el prompt contextual, entre Interactions y GenerateContent. Un prompt breve funcionó con «sube»; se generaron las demás piezas con esa misma plantilla, ruta GenerateContent, Charon y seed 12345. No se mezclaron los cuatro activos producidos antes con los nuevos. Subfrase «sube» diagnóstica reutilizada, sin repetir su cargo. Originales, errores, peticiones y uso conservados.

Constructor local `tools/build_seed_units.py`: recorte de extremos de baja energía con margen y cruce por cero, atenuación RMS uniforme, concatenación directa y 80 ms añadidos después del activo. Sin cortes de sílabas ni fundidos. Verifica bytes idénticos de cada módulo en sus usos. Las tarjetas muestran A/B/C, ambas uniones, fuentes y volumen.

Whisper reconoce cifras en los montajes, pero da alertas en BBVA/«sube» y unidades aisladas. No se diagnostica error TTS sin escucha ni se aplica la aprobación de BBVA histórico a la toma nueva. No se ha demostrado beneficio causal de seed; falta control equivalente sin semilla y escucha.

Coste por uso reportado: 0,014007 USD (incluye doce tomas completas exitosas, cuatro no utilizadas en el montaje y dos referencias). Seis piezas útiles: 0,006007 USD. Acumulado 0,755520 USD. Cuatro HTTP 400 sin uso reportado; cargo no conciliado. Informe `docs/SEED_SUBFRASES.md` y `qa/seed_units_coste.json`.

## Actualización 2026-09-11 — Seed medido y cortes visibles

Doce POST reales sin caché local ni reintentos. Cinco tomas con seed y petición idéntica: tres PCM distintos, dos parejas exactas. Tres sin seed: tres distintos. Cuatro textos cruzados adicionales; no se han validado sus empalmes. Whisper reconoce verbos y cantidades. Informe: `docs/SEED_GEMINI.md`; resultados reproducibles: `qa/seed_resultados.json`. No ID de respuesta disponible en metadatos interpretados; no inferir versión fija ni determinismo del proveedor.

Coste nuevo 0,020172 USD; acumulado 0,741513 USD. No se activa una semilla maestra ni se regeneran unidades aprobadas. Entrada `bitacora.html#seed-prueba-1` con originales y peticiones.

H3 incorpora en sus veinte tarjetas una distinción visible entre toma TTS completa y montaje local: colores A/B, centro y duración de fundido, intervalos exactos, audio de cada fragmento, original completo y ganancia por donante. Explica los cortes dentro de /u/ o fricación candidata de «es», NumPy, SciPy/STFT y atenuación RMS; control autorreconstruido señalado. Audios históricos intactos.

## Actualización 2026-09-11 — Análisis de seed

El usuario aporta un informe sobre seed. Se verifica soporte anunciado en OpenRouter y el campo en Google Interactions, API actual de Loros. Análisis en `docs/SEED_GEMINI.md` y nueva entrada `bitacora.html#seed-analisis`. Se propone piloto escalonado de seis llamadas y después cuatro, evitando caché local y sin cambiar voz/proveedor. Todavía no ejecutado: coste nuevo 0 USD. No se adopta una semilla maestra ni se atribuye estabilidad entre textos sin evidencia.

Validación de la bitácora/H3: 73 tests de `tests/` pasan. Comprobados navegación histórica, búsqueda, filtro, audio, notas persistentes y exportación en navegador, sin errores JS y sin desbordamiento horizontal a 390 px. La búsqueda global de tests también ejecutó el paquete antiguo: 2701 pasan y un error de recogida en `biblioteca_v2/tests/test_library.py::test` por fixture `self` inexistente; ajeno a estos cambios.

## Actualización 2026-09-11 — H3 y bitácora permanente

- El usuario confirmó que BBVA estaba bien pronunciado: el error «BDVA» fue de Whisper. Evidencia: `qa/loros_bbva_pronunciacion.json`.
- H3 prueba reutilizar cantidades entre subida y bajada, primero «La subida/bajada es de…» y después «Sube/baja un…». Siete tomas nuevas, doce montajes locales y ocho referencias. Cortes y método en `docs/H3_RESULTADOS.md`; resultados pendientes de escucha, sin aprobación automática.
- Revisado el histórico: H1/H2 preservaban el predicado completo para el «sube un uno» aceptado. V7 interno se rechazó. La nueva prueba corta usa contexto «un uno», no «un cuarenta»; `short_up_1` es control del mismo donante, no evidencia de transferencia.
- Coste H3: **0,015297 USD**; acumulado **0,721341 USD**. Uso en `qa/loros_h3_coste.json`. Sin generación masiva ni inglés.
- Se crea **`bitacora.html`**, entrada permanente, con catálogo `data/bitacora.json`, histórico con fecha/hora, búsqueda, comparaciones, audios fuente, prompts, cortes, procesamiento y confianza de Whisper por palabra/segmento. Notas locales exportables, separadas de aprobación.
- Constructor `tools/build_bitacora.py`: comprueba hashes históricos y evidencias locales; no hace llamadas TTS. H3 actualiza esta misma página. `visor.py` la abre por defecto y mantiene el acceso restringido.

## Actualización 2026-09-11 — H2 aceptado y comparación de tres versiones

- El usuario declara «de momento excelente, lo escucho todo muy natural». H2 queda aceptado para el piloto por sus hashes en `qa/loros_h2_escucha.json`, sin extender la aprobación a otros cortes ni publicación.
- Se aclaró que las tres variantes de H1 eran ensamblado con pausa, referencia completa con pausa y referencia completa continua. «Continua» y «sin pausa tras activo» son la misma variante. Se preguntó si quería además ensamblados sin pausa; sin respuesta, se completó primero la comparación original, también útil como referencia para ese experimento posterior.
- Se preparó y ejecutó `data/loros_h2_tres_versiones_es.json`: 5 peticiones nuevas y 3 hits de caché, un intento por clip, sin rechazos. Run `loros_h2_tres_versiones_es_v1-2a5d7b6c1a51`.
- Comparador: `output/loros_h2_comparacion/index.html`. Construcción local: `python tools/build_loros_comparison.py`. Casos: Inditex baja 2 %, BBVA sube 1,05 %, euro dólar sube 1,05 % y boletín de cuatro activos.
- Los ensamblados son copias exactas de los WAV aprobados. Referencias niveladas mediante atenuación uniforme por fuente; sin aceleración ni cambios de tono. No se presenta ninguna referencia como ensamblado continuo.
- Las nuevas referencias pasan la comprobación aproximada de cifras y movimientos con Whisper Small local. En BBVA continua, ASR devuelve «BDVA»: escuchar antes de aprobar la pronunciación; no afirmar que el TTS se equivocó solo por ASR. Advertencia visible en comparador.
- Coste nuevo calculado **0,017631 USD**; acumulado documentado **0,706044 USD**. Registro completo de uso: `qa/loros_h2_comparacion_coste.json`. Dentro del presupuesto autorizado de 3 USD.
- **69 tests pasan**; constructor verifica integridad PCM y conserva los hashes de los ensamblados aprobados. Enlaces de los 12 audios del comparador verificados.
- Referencias nuevas pendientes de escucha. La composición interna de cantidades y fechas sigue siendo objetivo pendiente; esta comparación de estilos no la sustituye.

## Actualización 2026-09-11 — H1 aprobado y H2 compuesto

**Estado vigente:** el usuario aceptó por escucha las tres versiones concretas de H1 y autorizó continuar sin consultar gasto cuando el presupuesto esté por debajo de 3 USD. La autorización sustituye las peticiones de permiso históricas de abajo. Mantener pruebas parciales y no confundir presupuesto con aprobación de calidad ni con permiso para generar el banco masivamente.

- La aprobación por hash está en `qa/loros_h1_escucha.json`. El comparador de H1 la refleja.
- Se ejecutó H2: cuatro activos × dos movimientos × tres cantidades = **24 combinaciones** con **10 módulos de audio**. Dos donantes de H1 reutilizados; ocho nuevos. Tres referencias completas adicionales para comparar.
- Comparador: `output/loros_h2/index.html`. Informe: `docs/H2_RESULTADOS.md`. Banco y recetas en `output/loros_h2/bank.json` y `recipes.json`.
- Composición individual SIN TTS: `python tools/build_loros_h2.py --asset bbva --movement baja --amount 1_05`. Matriz piloto: añadir `--matrix`.
- Plan donantes: `data/loros_h2_es.json`; cortes vinculados a fuente por hash: `data/loros_h2_units.json`. Referencias revisadas: `data/loros_h2_referencias_es.json`.
- Run donantes: `loros_h2_bloques_es_v1-087b26abc8ab`. Su manifiesto termina en error por las referencias rechazadas, pero los diez donantes útiles quedaron guardados. Referencias terminadas en `loros_h2_referencias_es_v2-74fac1ba440c`.
- Hubo dos rechazos de duración de una referencia; el runner eliminó esos WAV. Sus tokens se conservaron antes de reanudar en `qa/loros_h2_intento_1.json` y `qa/loros_h2_intento_2.json`. No regenerar los donantes útiles para repetir una referencia.
- **Coste H2: 0,066212 USD calculados**, incluyendo dos rechazos; 13 solicitudes nuevas (8+3+2). Acumulado documentado: **0,688413 USD**, por debajo de 3 USD. No es factura conciliada. Registro: `qa/loros_h2_coste.json`.
- **69 tests pasan**: 67 del runner y 2 de reutilización/integridad/rechazo de fuentes cambiadas. Mismo módulo implica mismo PCM; repetir composición conserva hash. No se llama a Gemini para combinar.
- ASR local correcto en diez donantes y cuatro ensamblajes, cubriendo todos los activos, movimientos y cantidades, además del boletín compuesto. No es escucha ni certificación acústica. Archivos en `output/transcribe/loros_h2/`.
- **H2 pendiente de escucha.** El predicado aún conserva verbo + cantidad + unidad. Tras escuchar H2, pilotar composición interna de cantidades y fechas; no enumerar todos sus valores ni extender cortes por semejanza ortográfica.

## Actualización 2026-09-11 — H1 ejecutado y objetivo combinatorio confirmado

- El usuario autoriza las cuatro tomas bajo la reserva propuesta de 0,40 USD. Recalca la necesidad de unir subfrases, cantidades y fechas: no es viable generar todas las combinaciones.
- Se ejecutó `data/loros_h1_es.json` con Charon, `ideal_200`, cuatro peticiones y un intento por clip. Run: `loros_h1_es_v1-94ec53f7c3a1`.
- Uso reportado: 1.438 tokens de entrada y 343 tokens de audio. A las tarifas consultadas: **0,008298 USD** nuevos; acumulado histórico más H1: **0,622201 USD calculados**, no factura conciliada.
- Montaje candidato y referencias: `output/runs/loros_h1_es_v1-94ec53f7c3a1/experimentos/h1_pausa_v1/index.html`. Reproducible con `python tools/build_loros_h1.py`, que verifica hashes y PCM. Sin nuevas APIs para montaje ni ASR local.
- Se extrae el rótulo del donante de cuarenta y se añade el predicado entero de uno. Baja energía del rótulo: 0,918542–1,25167 s; corte candidato en el centro y recorte de silencio inicial del predicado. Sin crossfade ni aceleración. Atenuación uniforme por donante para comparación.
- Whisper Small local reconoce las cantidades previstas en los tres primeros donantes; omite «un» en referencia continua. No distingue por sí solo fallo TTS de omisión ASR. Resultados en `output/transcribe/loros_h1/`.
- El ensamblado se transcribe localmente como «Telefónica. Sube un 1%.». Las 67 pruebas del runner pasan y el constructor comprueba hashes, ventanas y PCM al ejecutarse.
- **No hay aprobación auditiva todavía.** Próximo paso: escucha de H1 y después pilotos separados para cantidad 2×2 y fecha 2×2×2, con donantes compartidos y combinaciones reservadas para evaluación. Sin generar calendarios ni productos cartesianos.
- El plan actualizado aclara que frase completa es referencia/respaldo, no solución única a la combinatoria.

## Actualización 2026-09-11 — planificación de ampliación y H1

Esta entrada prevalece sobre las propuestas históricas de abajo para el trabajo nuevo.

- Orden confirmado por el usuario: **primeras entregas y prototipos solo es-ES peninsular**; en-US después. El runner sigue exclusivamente en español.
- El usuario acepta probar pausa tras el activo si suena natural y ágil. No es aprobación de un audio todavía no generado.
- Decisiones, investigación, encaje local con Finaz y hitos: `docs/PLAN_LOROS.md`.
- H1: `data/loros_h1_es.json`, cuatro donantes Charon, 23 palabras, referencias con pausa y continua. Preparado con `--pace ideal_200 --prepare`; extracción, síntesis y escucha pendientes.
- Informe recibido preservado en `InputExternal/informe_contextual.txt`; núcleo externo verificado: 24 tests. Runner existente: 67 tests superados. Prueba técnica del plan y evidencia en `qa/loros_h1_preparacion.json`.
- Aclaración del diagnóstico anterior: la asimilación de la nasal es plausible, no una realización acústica confirmada en estos archivos. La v7 sigue rechazada independientemente de la explicación.
- Se consultó Finaz-Director **local**, commit `71e51b4` (2026-08-30), y el esquema local AudioManifestV1. El remoto no pudo verificarse. Loros no se ha conectado ni publicado a Finaz.
- Esta carpeta no tiene `.git`. No se ha inicializado ni hecho commit.
- **Coste TTS nuevo: 0 USD; solicitudes TTS: 0.** El saldo histórico no es autorización de gasto nuevo. Próximo paso: fijar presupuesto específico y sintetizar solo H1.
- No escalar antes de escucha y medición de coste/tiempo. No instalar alineadores ni construir un selector de empalmes antes de demostrar necesidad.

## Traspaso a la próxima sesión de Loros

Esta sección es la fuente de verdad sobre el estado final. El resto del archivo
mantiene la cronología completa, incluidas hipótesis que después fueron
rechazadas.

### Objetivo del proyecto

Loros investiga cómo producir boletines financieros de FINAZ en español de
España, con voz natural, ritmo cercano a 200 palabras por minuto y datos
variables para miles de activos. Se busca minimizar llamadas y coste de TTS sin
crear una voz «Frankenstein» al recombinar grabaciones.

Las dimensiones probadas son:

- activo: euro/dólar, Telefónica, Repsol, BBVA e Inditex;
- dirección: `sube` y `baja`;
- porcentaje de precio y volumen: 1, 2, 17, 40, 73 y 89 %;
- indicador: RSI o estocástico con distintos valores;
- cierres como `Y esto es todo por hoy` y `Y ahora, devolvemos la conexión…`.

Gemini TTS produjo las fuentes; toda recombinación, nivelación, corte,
conversión WAV/MP3 y transcripción posterior se hizo localmente.

### Estado final: aceptado, corregido y pendiente

| Elemento | Estado | Conclusión |
|---|---|---|
| Frases o cláusulas completas unidas en pausas | **Aceptado** | Es el método más robusto y escalable disponible actualmente. |
| Matriz larga 6×6×6 | **Aceptada** | 216 combinaciones; las uniones principales están en silencios naturales. |
| Cierre completo `Y ahora, devolvemos…` | **Aceptado** | Se extrae como bloque completo desde una pausa. |
| `Telefónica baja un uno por ciento` v4 | **Aceptado por escucha** | Conserva `un uno por ciento` completo y la unión resultó natural. |
| `Telefónica sube un` + 2, 17, 40, 73 y 89 % v6 | **Aceptado por escucha** | El usuario indicó que estas cinco cantidades se oyen muy bien. |
| `Telefónica sube un cuarenta…` v6 inicial | **Corregido** | Whisper colocó tarde el comienzo de `cuarenta` y recortó `/k/`; el corte se adelantó de 1,32 a 1,19 s. |
| `Telefónica sube un uno…` v1–v7 | **Rechazado** | Todas las recombinaciones siguen mostrando salto, eco o enlace artificial. No reutilizar como producción. |
| Cortes sujeto + `sube/baja` de pruebas antiguas | **No aprobados globalmente** | Algunos ejemplos son útiles, pero se detectaron uniones audibles tras el nombre del activo. |
| Whisper como aprobación de naturalidad | **Rechazado** | Sirve para contenido y alineación aproximada, nunca como prueba acústica suficiente. |

### Conclusión principal

Una frontera ortográfica no es necesariamente una frontera acústica. Las
palabras no se pronuncian como bloques independientes: los gestos
articulatorios atraviesan sus límites. Por eso no existe un módulo universal
`sube un` que pueda preceder naturalmente a cualquier cantidad.

El caso que reveló el problema fue:

```text
Telefónica sube un cuarenta por ciento  → fuente del prefijo
Telefónica sube un uno por ciento      → destino deseado
```

En la fuente, la `/n/` de `un` se prepara para la `/k/` de `cuarenta` y puede
realizarse como nasal velar `[ŋ]`. Delante de `uno`, en cambio, la consonante
participa en la resilabificación aproximada `/u.nu.no/` y requiere una nasal
alveolar enlazada con la vocal siguiente. Conservar `sube un` desde
`un cuarenta` arrastra, por tanto, el alófono y la coarticulación equivocados.

Esta explicación corrige dos conclusiones provisionales anteriores:

1. Cortar dentro de la `/u/` no resolvía el problema; podía duplicar restos de
   `un` y crear un eco.
2. Conservar `sube un` completo tampoco es universal; su `/n/` depende del
   primer sonido de la cantidad posterior.

### Qué salió mal, por versiones

| Versión | Estrategia | Resultado y aprendizaje |
|---|---|---|
| v1 | Unión en mitad de la `/u/` con 12 ms de fundido y búsqueda de fase | Whisper aceptó el texto, pero la escucha detectó eco en `un uno`. Correlaciones: 0,6384 (`sube`) y 0,4066 (`baja`). |
| v2 | Conservar el ataque de `un uno` | La variante de bajada fue transcrita como `bajo B1%`; rechazada. |
| v3 | Elegir otro donante por correlación | `baja` mejoró sólo hasta 0,5164; insuficiente. |
| v4 | Conservar `un uno por ciento` y cortar antes de `un` | `baja` quedó bien; `sube` creó una unión vocálica perceptible. |
| v4 gaps | Separaciones de 0, 10 y 20 ms con fundidos independientes | Todas conservaron el texto, pero ninguna arregló la naturalidad. Añadir silencio no corrige la coarticulación. |
| v5 | Conservar `Telefónica sube un` y añadir `uno por ciento` | Mejoró el ASR, pero la frontera `/n#u/` seguía siendo acústicamente activa. |
| v6 | Aplicar `sube un` a seis cantidades | 2, 17, 40, 73 y 89 % fueron aceptadas por escucha. `uno` siguió fallando. |
| v7 | Fundir dentro de la nasal compartida con correlación 0,7532 | Whisper dio probabilidades altas, pero la escucha volvió a rechazarlo. Confirmó que correlación y ASR no predicen por sí solos naturalidad. |

Todas las versiones rechazadas se conservan como evidencia y para pruebas de
regresión. No deben borrarse ni presentarse como ejemplos finales.

### Fenómenos que debe conocer el algoritmo

#### Español

| Frontera | Ejemplos | Tratamiento |
|---|---|---|
| Consonante + vocal | `un uno`, `los activos`, `el euro` | Resilabificación: conservar una unidad que atraviese la frontera o generar una frase completa. |
| Vocal + vocal | `sube ahora`, `euro aumenta`, `de interés` | Sinalefa, semivocal o hiato: sólo cortar si existe una pausa prosódica real. |
| Nasal + consonante | `un porcentaje`, `un dato`, `un cuarenta` | Asimilación del lugar de articulación: clasificar por el fonema siguiente. |
| Vocal/nasal + `/b d g/` | `la bolsa`, `sin datos`, `un gráfico` | El contexto decide entre aproximante y oclusiva; conservarlo. |
| `/n l s/` + `r` | `un repunte`, `el rendimiento`, `las rentabilidades` | La `r` fuerte depende del contexto anterior; no separar. |
| Consonantes iguales | `las señales`, `un nivel` | Puede haber una sola articulación prolongada; usar una unidad contextual. |

En cantidades españolas, `un` necesita al menos clases según el sonido inicial:

- vocal: uno, ocho, once, ochenta;
- bilabial: veinte, mil, millón;
- dental o alveolar: dos, diez, tres, setenta, nueve;
- velar: cuatro, catorce, cuarenta;
- interdental en español peninsular: cero, cinco, cincuenta.

La clasificación debe hacerse con fonemas, no con la primera letra.

#### Inglés

También requieren contexto: consonante + vocal (`an asset`, `pick it up`),
vocal + vocal (`go up`), asimilación nasal (`ten percent`, `ten bucks`),
`t/d` intervocálicas y flapping (`get it`), linking o intrusive `r` en acentos
no róticos (`share is`, `data are`), yod coalescence (`did you`, `got you`) y
consonantes compartidas o sin explosión (`big gain`, `stock climbed`). La voz y
el acento forman parte de la clave de contexto.

### Política de cortes para Loros

Orden obligatorio de preferencia:

1. **Pausa natural, final de oración o cambio de locutor.** Corte permitido.
2. **Cláusula completa.** Reutilizarla si su prosodia encaja en el nuevo bloque.
3. **Unidad contextual que atraviese la frontera.** Debe conservar los fonemas
   de ambos lados y proceder del mismo tipo de contexto.
4. **Centro de un teléfono estable.** Sólo si los dos donantes tienen el mismo
   alófono, vecinos fonéticos, F0, energía, duración y estilo compatibles.
5. **Edición o inpainting de voz.** Evaluar cuando sea imprescindible sustituir
   datos dentro de una frase.
6. **Generación TTS completa.** Usarla cuando ninguna opción anterior sea
   acústicamente segura.

Debe prohibirse por defecto cortar exactamente en límites escritos `palabra |
palabra` que participen en resilabificación, sinalefa, asimilación, reducción,
flapping o cambio alofónico.

Una representación mínima de cada candidato sería:

```text
voz + modelo + idioma/acento + velocidad + estilo
+ dos fonemas izquierdos + unidad + dos fonemas derechos
+ acento léxico + posición prosódica + F0 + energía + duración
```

### Validación necesaria

```text
texto estructurado
→ fonemización
→ clasificación de la frontera
→ alineación fonética forzada
→ selección de donantes compatibles
→ montaje
→ comprobación de contenido con ASR
→ métricas acústicas
→ escucha A/B
```

- **Whisper:** nombres, palabras, cifras, negaciones, unidades, repeticiones y
  probabilidades anómalas. Sus tiempos de palabra son aproximados; el error de
  `/k/` en `cuarenta` demuestra que no deben usarse literalmente como cortes.
- **Alineador fonético:** inicio y fin aproximado de cada teléfono. Sigue
  necesitando ajuste acústico local.
- **SciPy/Numpy:** salto de muestras, RMS, energía, duración, silencios,
  correlación, F0 aproximada y distancia espectral.
- **Métricas perceptivas:** NISQA, UTMOS o equivalentes pueden priorizar
  candidatos, pero deben validarse antes con defectos reales de Loros.
- **Escucha humana:** criterio final para eco, ritmo, coarticulación, timbre y
  naturalidad. Una transcripción correcta nunca equivale a aprobación.

Los casos de riesgo alto —por ejemplo `un uno`— deben quedar bloqueados hasta
tener aprobación auditiva explícita.

### Arquitectura recomendada a partir de ahora

Para producción a gran escala, priorizar intervenciones completas separadas por
fronteras discursivas naturales:

```text
«Y ahora es tiempo de… Telefónica.»
«Ha bajado un dos por ciento.»
```

El cambio de oración, pausa, cortinilla o locutor convierte la modularidad en
una decisión editorial, no en un defecto. La variedad debe obtenerse mediante
planificación de discurso, formulaciones completas, caché y varias voces; no
mediante cortes cada vez más pequeños dentro de habla continua.

Si se insiste en una sola oración para `Telefónica sube un uno por ciento`, las
opciones fiables son conservar `sube un uno` desde una misma toma compatible,
generar la frase completa o emplear edición/inpainting. No debe volver a usarse
el `un` grabado antes de `cuarenta`.

### Investigación SOTA preparada y pendiente

Se preparó un prompt completo para solicitar a ChatGPT una investigación actual
sobre una arquitectura alternativa para miles de activos. La idea central es
evitar empalmes internos y producir intervenciones completas, variadas y
factualmente controladas. El estudio debe comparar:

- una llamada TTS por frase, intervención, párrafo o boletín;
- frases completas en caché y generación por lotes;
- planificación de discurso, data-to-text y variación lingüística controlada;
- un locutor frente a presentador, analista, corresponsales y mesa cuant;
- Gemini TTS frente a servicios comerciales y alternativas abiertas;
- edición/inpainting de voz, incluyendo soporte real de español y licencias;
- control de factualidad, costes, latencia y repetición;
- evaluación con ASR, alineación forzada, métricas acústicas y escucha humana.

El primer experimento propuesto debe costar menos de 3 USD. El entregable debe
incluir tres formatos de boletín —un locutor, dos voces y formato híbrido—,
diagrama, pseudocódigo, esquema de datos, política de caché, tabla de costes y
un plan implementable en dos semanas. Este estudio todavía no se ha ejecutado;
no debe confundirse el prompt preparado con resultados investigados.

### Coste y límite

- Total acumulado documentado: **0,613903 USD**.
- Presupuesto máximo histórico de la sesión: **3 USD**.
- Margen restante documentado: **2,386097 USD**.
- Las recombinaciones v1–v7 posteriores a las carriers costaron **0 USD de
  API**.
- Ninguna nueva sesión debe inferir que puede gastar el margen: debe mantener
  el límite de 3 USD y calcular el coste antes de generar.

### Rutas y comandos importantes

```text
tools/build_long_matrix.py          matriz robusta 6×6×6
tools/build_euro_matrix.py          matriz euro/dólar
tools/build_company_examples.py     sustitución de activos
tools/build_baja_examples.py        experimentos con «baja»
tools/build_mid_u_pilot.py           historial reproducible v1–v7
output/runs/                         fuentes, experimentos y resultados
output/transcribe/                   transcripciones locales
```

Comprobación principal:

```bash
python -m pytest -q tests/test_demo.py
```

Estado al cerrar esta sesión: **67 pruebas superadas**. El `pytest` global
descubre además un error previo de colección en
`biblioteca_v2/tests/test_library.py` (`fixture 'self' not found`), ajeno a los
cambios de audio; antes de usar el total global debe corregirse ese test
dinámico.

Tras renombrar el directorio a `Loros`, comprobar `pwd`, ejecutar las 67 pruebas
y abrir `index.html`. Los scripts principales calculan `ROOT` desde su propia
ruta y los manifiestos guardan rutas relativas, por lo que el cambio de nombre
no debería exigir regenerar audios. No mover ni renombrar individualmente las
carpetas históricas de `output/runs`.

### Referencias técnicas consultadas

- [Durational Cues to Resyllabification in Spanish](https://loquens.revistas.csic.es/index.php/loquens/article/view/111)
- [Resyllabification and Coarticulatory Nasalization in Spanish](https://www.mdpi.com/2226-471X/9/6/219)
- [Spanish `/b d g/` allophony](https://pmc.ncbi.nlm.nih.gov/articles/PMC3703669/)
- [Spanish rhotic production](https://www.cambridge.org/core/journals/bilingualism-language-and-cognition/article/missing-link-in-spanish-heritage-trill-production/2EEF354237A02A623B914F1AA11CD595)
- [English allophonic word-boundary cues](https://pmc.ncbi.nlm.nih.gov/articles/PMC2677262/)
- [English nasal place assimilation](https://doi.org/10.5334/labphon.119)
- [Diphone database construction and stable cut regions](https://www.isca-archive.org/icslp_2002/vepa02_icslp.pdf)
- [Perceptually based concatenation costs](https://www.isca-archive.org/ssw_2004/syrdal04_ssw.html)

---

## Registro cronológico original

## Resultado actual

Se ha validado una matriz de frases financieras largas construida a partir de cláusulas completas. La primera versión tenía tres alternativas para precio, volumen y RSI, por lo que produjo 3 × 3 × 3 = 27 frases. La ampliación añade tres alternativas por eje y produce 6 × 6 × 6 = 216 frases distintas sin nuevas llamadas a Gemini durante la combinación.

No se cortan números aislados. Cada activo intercambiable conserva la oración completa que contiene su cantidad. Esta decisión evita cortar coarticulación dentro de «por ciento», «erre ese i» o el propio número, que fue la causa principal del sonido Frankenstein en pruebas anteriores.

## Estructura modular

Cada carrier contiene cuatro oraciones:

1. `La acción sube un <valor> por ciento.`
2. `El volumen supera en un <valor> por ciento la media de veinte sesiones.`
3. `El erre ese i alcanza <valor> puntos.`
4. `Y esto es todo por hoy.`

Las combinaciones se montan como:

```text
precio completo + volumen completo + (RSI + cierre de la misma carrier)
```

Mantener juntos RSI y cierre reduce a dos las uniones entre carriers diferentes. Ambas ocurren en silencios creados naturalmente por Gemini al terminar una oración.

## Valores disponibles

| Eje | Valores |
|---|---|
| Precio | 1, 2, 17, 40, 73 y 89 % |
| Volumen | 1, 2, 17, 40, 73 y 89 % |
| RSI | 5, 10, 50, 65, 89 y 95 puntos |

Para volumen 73 % se usa la forma equivalente `El volumen supera la media de veinte sesiones en un setenta y tres por ciento.` Gemini alteró dos veces la redacción original; la reformulación fue transcrita correctamente y, al ser una cláusula completa, sigue siendo intercambiable.

## Generación de las carriers

- Modelo: `gemini-3.1-flash-tts-preview`.
- Voz: `Charon`.
- Perfil: `carrier`.
- Ritmo solicitado: `nativa_rapida`, objetivo de 240 ppm.
- No se aplicó aceleración, cambio de tono ni ajuste temporal después de Gemini.
- El texto locutable apareció una sola vez en cada petición.
- Las variantes conservaron la misma estructura y sólo cambiaron las cantidades, salvo la reformulación documentada para volumen 73 %.

Fuentes aceptadas:

| Valores precio/volumen/RSI | Ejecución | Ritmo medido |
|---|---|---:|
| 1 / 1 / 5 | `carrier_long_matrix_v2-964d7e3ffa2c` | 227,1 ppm |
| 2 / 2 / 10 | `carrier_long_matrix_additions-ea847f56df99` | 259,2 ppm |
| 17 / 17 / 65 | `carrier_long_matrix_additions-ea847f56df99` | 220,6 ppm |
| 40 / 40 / 50 | `carrier_long_matrix_v2-964d7e3ffa2c` | 211,5 ppm |
| 73 / 73 / 95 | `carrier_long_matrix_73_rephrased-b1713da54618` | 247,9 ppm |
| 89 / 89 / 89 | `carrier_long_matrix_v2-e5477c8fca18-take-572356093893` | 255,5 ppm |

## Selección de cortes

1. Gemini genera primero la carrier completa.
2. Whisper Small local verifica texto, signo, cifras, unidades e indicador.
3. Las marcas de palabra delimitan aproximadamente cada oración.
4. FFmpeg identifica el intervalo silencioso correspondiente.
5. El corte se coloca en el centro del silencio y se ajusta al cruce por cero más cercano dentro de 3 ms.
6. La partición debe reconstruir exactamente el PCM nivelado de su carrier.

Las pausas de las fuentes aceptadas están aproximadamente entre 220 y 450 ms. No se añaden silencios ni fundidos y no se corta dentro de habla activa.

## Nivelación

Antes de cortar, cada carrier completa se ajusta al RMS de la fuente aceptada más silenciosa. Se aplica una única ganancia constante a toda la carrier; no se normaliza cada palabra o cláusula por separado. Esto conserva la dinámica interna y reduce saltos de nivel al intercambiar módulos. Sólo se atenúa: no se fuerza clipping.

## Construcción y archivos

El proceso reproducible está en `tools/build_long_matrix.py`:

```bash
python tools/build_long_matrix.py
```

Genera:

- 216 WAV individuales;
- 216 MP3 individuales;
- módulos separados para inspección;
- carriers niveladas;
- `resultados.json` con fuentes, cortes, ganancias, textos, velocidades y rutas;
- un montaje de las 216 combinaciones.

Salida principal:

```text
output/runs/carrier_long_matrix_v2-964d7e3ffa2c/
  experimentos/recombinacion_6x6x6_v1/
```

Whisper volvió a transcribir correctamente tres combinaciones híbridas no pronunciadas completas por Gemini: 2/73/95, 73/2/10 y 17/89/65. La transcripción valida contenido, no naturalidad; la aceptación final de las uniones sigue siendo auditiva.

## Tomas rechazadas

- El primer diseño usó punto y coma. Gemini dejó pausas inconsistentes —desde ninguna pausa hasta unos 600 ms—, así que no se utilizó para módulos.
- Una carrier 89 % añadió `a` antes de `la media`; se sustituyó por una toma exacta.
- Dos carriers 73 % alteraron la cláusula de volumen; se sustituyeron por la reformulación equivalente.
- La primera prueba de euro dólar hizo que Whisper interpretara `un diecisiete por ciento` como `1,17 %`; se sustituyó por 40 %.

Las tomas rechazadas se conservan como evidencia, pero el ensamblador no las referencia.

## Segundo molde: euro dólar y estocástico

Se creó además esta frase independiente:

> El euro dólar sube un cuarenta por ciento. El volumen supera en un setenta y tres por ciento la media de veinte sesiones. El estocástico alcanza sesenta y cinco puntos. Devolvemos la conexión a la mesa cuant para que nos comente alfas y señales interesantes.

Ejecución aceptada: `carrier_euro_dolar-f6f101bca8f4`. Duración: 11,92 s. Ritmo: 226,5 ppm. Whisper verificó euro dólar, 40 %, volumen 73 %, estocástico 65 y el cierre completo.

## Matriz euro dólar sin nuevas peticiones

La carrier aceptada de euro dólar se reutilizó como armazón para construir otras 216 combinaciones sin llamar a Gemini:

```text
euro dólar + porcentaje de precio
+ cláusula completa de volumen
+ estocástico + cantidad de indicador
+ devolución a la mesa cuant
```

El volumen se intercambia como una oración completa. Para conservar `euro dólar` y `estocástico`, los porcentajes de precio se cortan después de `sube un` y los valores del indicador después de `alcanza`. Los dos contextos fonéticos coinciden con las carriers donantes. Cada frontera activa se ajusta al cruce por cero de menor energía dentro de 3 ms. Este ajuste redujo el mayor salto de muestra de 1.878 a 390 sobre 32.768.

La carrier de euro dólar se atenúa hasta el mismo RMS de −19,2 dBFS usado en la biblioteca de cantidades. No hay aceleración, cambio de tono, fundidos ni solicitudes externas. El proceso está en:

```bash
python tools/build_euro_matrix.py
```

Salida:

```text
output/runs/carrier_euro_dolar-f6f101bca8f4/
  experimentos/recombinacion_6x6x6_v1/
```

Se generaron 216 WAV, 216 MP3 y un montaje de 43 min 59,95 s. El rango global es 202,0–232,7 ppm. Whisper conservó las cantidades en tres híbridos extremos. En el híbrido 17/73/10 transcribió una `a` que no aparece al transcribir la fuente donante; como el bloque de volumen se copia sin modificar, queda registrado como variación del ASR y pendiente de escucha humana.

Esta matriz es una prueba más exigente que la anterior: precio y estocástico requieren una unión dentro de habla activa. Su contenido está controlado por procedencia exacta de los módulos, pero la naturalidad sólo puede aprobarse escuchando.

## Puente «Y ahora»

Se generó una única carrier completa con el cierre `Y ahora, devolvemos la conexión a la mesa cuant para que nos comente alfas y señales interesantes.` No se sintetizaron las palabras `Y ahora` de forma aislada: se extrajo todo el cierre desde la pausa natural anterior para conservar su prosodia.

La fuente `carrier_euro_dolar_y_ahora-1aa81244eb7c` dura 11,68 s y alcanza 241,4 ppm. Whisper verificó todas las cifras y el cierre. El módulo se insertó en la combinación euro 17 % / volumen 73 % / estocástico 10, sustituyendo el cierre anterior dentro del silencio. El resultado dura 12,23 s, alcanza 220,7 ppm y volvió a superar la transcripción de contenido.

Coste de la única generación: 0,007866 USD. Total acumulado de la sesión tras esta prueba: 0,563777 USD; margen restante hasta 3 USD: 2,436223 USD.

## Coste registrado

| Trabajo | Coste |
|---|---:|
| Matriz inicial 3×3×3, incluidos pilotos rechazados | 0,071556 USD |
| Ampliación y nuevo molde, incluidas tomas rechazadas | 0,045726 USD |
| Total acumulado de toda la sesión | 0,555911 USD |
| Margen restante hasta el límite de 3 USD | 2,444089 USD |

El coste se calcula con los tokens de entrada y audio declarados en los manifiestos de Gemini y las tarifas usadas en esta investigación. La combinación local de WAV y MP3 cuesta 0 USD de API.

## Corrección de «euro dólar sube un…» y sustitución por empresas

En la primera matriz de euro dólar, la carrier terminaba en `sube un` y el
porcentaje procedía de otra toma. Ese corte separaba el determinante de la
cantidad y hacía audible una unión defectuosa, especialmente con 89 %. Se
corrigió sin sintetizar audio: ahora cada módulo conserva unido el predicado
completo `sube un <cantidad> por ciento`, y de la carrier de euro dólar sólo se
toma el sujeto. La versión anterior se conserva y la corregida está en:

```text
output/runs/carrier_euro_dolar-f6f101bca8f4/
  experimentos/recombinacion_6x6x6_v2_predicado_completo/
```

Después se generaron cuatro carriers completas, una por sujeto: Telefónica,
Repsol, `be be uve a` e Inditex. Se usaron Gemini, la voz Charon y el perfil
`nativa_rapida` con objetivo de 240 ppm. Las fuentes midieron entre 219,9 y
232,8 ppm. Sólo el sujeto se extrae de cada nueva carrier; predicados,
volúmenes, valores del estocástico y cierre se reutilizan de la biblioteca ya
aceptada y se nivelan al RMS de la fuente más silenciosa.

Se materializaron cuatro ejemplos con cantidades distintas:

| Sujeto | Precio | Volumen | Estocástico | Ritmo |
|---|---:|---:|---:|---:|
| Telefónica | 1 % | 17 % | 50 | 203,3 ppm |
| Repsol | 2 % | 40 % | 65 | 216,3 ppm |
| Be be uve a | 73 % | 2 % | 95 | 237,5 ppm |
| Inditex | 89 % | 73 % | 10 | 222,2 ppm |

Whisper Small local verificó los cuatro contenidos completos. El proceso está
en `tools/build_company_examples.py` y la salida en:

```text
output/runs/carrier_companies-1117688a2a66/experimentos/sustituciones_v1/
```

Las cuatro carriers nuevas requirieron 4 peticiones y costaron 0,032701 USD.
La recombinación local costó 0 USD. Total acumulado registrado: 0,596478 USD;
margen restante hasta 3 USD: 2,403522 USD.

## Acción «baja» reutilizando las cantidades

La primera interpretación de esta prueba fue innecesariamente amplia: una
única petición pronunció seis frases de bajada, aunque las cantidades ya
existían. Costó 0,009281 USD y se conserva como evidencia, pero sus cantidades
no se usan en la versión final.

La versión correcta extrae una sola vez el bloque contextual `baja un` de la
primera frase y le concatena los seis módulos `price_value` existentes. Los
sujetos, volumen, estocástico y cierre también se reutilizan. Por tanto, todas
las combinaciones finales emplean una sola toma nueva de `baja un` y no vuelven
a sintetizar cantidades. Whisper Small verificó correctamente 1, 2, 17, 40,
73 y 89 % en el montaje final.

```text
output/runs/carrier_baja_predicates-fc1d288f63dc/
  experimentos/ejemplos_baja_v2_reutiliza_cantidades/
```

El proceso está en `tools/build_baja_examples.py`. Total acumulado registrado:
0,605759 USD; margen restante hasta 3 USD: 2,394241 USD.

También se probó a separar `baja` de `un <cantidad>`, preservando juntos el
determinante y la cifra. Whisper interpretó repetidamente el verbo como
`baje`, por lo que esa variante v3 queda rechazada. La v2, que une `baja un`
con las cantidades antiguas, conservó correctamente verbo y cifras en las
seis transcripciones.

Tras detectar auditivamente la frontera anterior a `baja`, se creó la versión
v4 con un fundido lineal de 20 ms exclusivamente entre el sujeto y `baja un`.
El solape suaviza el cambio local de energía y timbre; cantidades y demás
módulos permanecen intactos. Whisper volvió a reconocer correctamente el
verbo y las seis cifras. No hubo peticiones ni coste de API adicionales.

```text
output/runs/carrier_baja_predicates-fc1d288f63dc/
  experimentos/ejemplos_baja_v4_fundido_20ms/
```

## Piloto de unión en la vocal de «un»

Para evitar generar cada combinación `activo + dirección + cantidad`, se
probó una unidad partida dentro de la zona estable de la vocal `/u/`:

```text
[Telefónica + dirección + primera mitad de «un»]
[segunda mitad de «un» + cantidad + por ciento]
```

El corte usa 12 ms de solape y busca la fase de mayor correlación en ±6 ms.
Para 40 %, la selección automática eligió una toma antigua de Repsol para
`baja` y la toma original de Telefónica para `sube`; ambas preservaron `un`.
Whisper Small verificó finalmente las seis cantidades con las dos direcciones:
1, 2, 17, 40, 73 y 89 %. Las cantidades proceden de fuentes ya aceptadas.

Se generó una sola carrier nueva de `Telefónica baja` para conservar junta la
transición nombre-dirección. Coste: 0,008144 USD. Total acumulado registrado:
0,613903 USD; margen restante hasta 3 USD: 2,386097 USD.

```text
output/runs/carrier_telefonica_baja-aeb1b28aa96e/
  experimentos/piloto_union_media_u_v1/
```

El proceso reproducible está en `tools/build_mid_u_pilot.py`.

### Corrección del caso «un uno»

La escucha humana detectó un eco en `Telefónica sube/baja un uno por ciento`
que Whisper no había rechazado. El diagnóstico mostró por qué: la v1 cortaba
dentro de la `/u/` del primer `un` y añadía otra toma en el contexto repetido
`un uno`. La correlación de onda en la unión era sólo 0,6384 para `sube` y
0,4066 para `baja`; además, Whisper asignó al `por` de la versión `sube` una
probabilidad anormalmente baja de 0,0407. La transcripción literal correcta no
era, por tanto, una prueba de naturalidad.

Se probó una v2 que conservaba `un uno` desde el ataque de la vocal, pero
Whisper transcribió la variante de bajada como `bajo B1%`; queda rechazada y se
conserva sólo como evidencia. Una selección alternativa de donante (v3) mejoró
la correlación de `baja` a 0,5164, todavía insuficiente para aprobarla por sí
sola.

La v4 evita partir la secuencia problemática: conserva completo el bloque
natural `un uno por ciento` de una toma `sube` o `baja`, y lo une antes de `un`
con un fundido de 5 ms. Whisper reconoce ahora ambos ejemplos completos; las
probabilidades del verbo son 0,662 (`sube`) y 0,988 (`baja`), y las del bloque
numérico son superiores a 0,70 salvo el símbolo `%` aislado de `sube` (0,459).
El contexto `un uno` queda marcado siempre para escucha humana: ni Whisper ni
una métrica de SciPy pueden certificar por sí solos que no haya eco o prosodia
artificial.

```text
output/runs/carrier_telefonica_baja-aeb1b28aa96e/
  experimentos/piloto_union_media_u_v4_un_uno_completo/
```

Esta corrección reutiliza audio existente: 0 peticiones nuevas y 0 USD de API.
El total acumulado permanece en 0,613903 USD.

La escucha posterior aceptó `baja un uno`, pero rechazó `sube un uno`: el
fundido de 5 ms solapaba la `/e/` final todavía energética de `sube` con el
ataque vocálico de `un`, creando una sinalefa perceptible aunque no hubiera un
clic y Whisper mantuviera el texto correcto. Por tanto, la v4 no queda
aprobada globalmente.

Se añadieron tres candidatos locales para `sube`, sin solapar las palabras:
cada borde recibe un desvanecimiento independiente de 12 ms y entre ambos se
prueban 0, 10 y 20 ms de separación. Whisper reconoce `Telefónica sube un 1 %`
en los tres. La variante de 20 ms obtiene la mayor confianza para `sube`
(0,724), pero todas siguen pendientes de escucha; la confianza de ASR no
selecciona de forma fiable la variante más natural.

```text
output/runs/carrier_telefonica_baja-aeb1b28aa96e/experimentos/
  piloto_union_media_u_v4_un_uno_completo/diagnostico_sube_uno/
```

### V5: conservar «sube un» completo — hipótesis después rechazada

La estrategia anterior seguía escogiendo mal la unidad. Para `sube`, la
carrier de Telefónica ya contiene una realización natural y aprobada de
`Telefónica sube un`; no había motivo para cortar antes de `un` ni dentro de
su vocal. La v5 conserva ese bloque íntegro hasta 1,02 s y añade únicamente
`uno por ciento` desde una fuente existente. Ambos cortes se ajustan al cruce
por cero más próximo en ±3 ms, sin solape ni silencio añadido.

Whisper conserva `Telefónica sube un 1 %` y la confianza del verbo mejora de
0,662 en v4 a 0,824 en v5. Esto no sustituye la escucha, pero confirma que ya
no se ha alterado la transición natural `sube → un`.

```text
output/runs/carrier_telefonica_baja-aeb1b28aa96e/experimentos/
  piloto_union_media_u_v5_sube_un_completo/
```

La hipótesis provisional fue conservar `activo + dirección + un` y sustituir
sólo `cantidad + por ciento`. La prueba posterior demostró que no es una regla
universal: el alófono de la nasal depende del sonido inicial de la cantidad.
En concreto, el `un` de esta carrier estaba grabado antes de `cuarenta` y no es
compatible con `uno`. Coste adicional: 0 USD.

### V6: seis combinaciones conservando «sube un»

La regla corregida se aplicó a las seis cantidades disponibles: 1, 2, 17,
40, 73 y 89 %. Todas conservan exactamente el mismo audio fuente para
`Telefónica sube un`; sólo cambia `cantidad + por ciento`.

La primera versión de 40 % usó literalmente el inicio de palabra de Whisper
(1,32 s) y perdió el ataque `/k/`. El análisis de energía situó ese ataque
desde aproximadamente 1,20 s, por lo que se adelantó el corte a 1,19 s, en la
zona de baja energía anterior. Whisper reconoce ahora `Telefónica sube un
40 %` con probabilidades 0,970 para `sube`, 0,990 para `un` y 0,912 para la
cantidad.

```text
output/runs/carrier_telefonica_baja-aeb1b28aa96e/experimentos/
  combinaciones_sube_un_v6/
```

Las seis combinaciones se construyeron localmente: 0 peticiones y 0 USD.

### V7: unión nasal específica para «un uno» — rechazada por escucha

La escucha consideró buenas las demás cantidades de v6, pero detectó un salto
en `un uno`. La causa es la resilabificación habitual `/u.nu.no/`: la `/n/`
final de `un` actúa acústicamente como ataque de `uno`, de modo que la frontera
ortográfica entre las dos palabras no es una frontera limpia.

La v7 conserva íntegra la transición natural `sube → u` y realiza un fundido
de 12 ms dentro de la nasal compartida. La búsqueda de fase en ±6 ms seleccionó
una unión con correlación 0,7532. Whisper reconoce la frase completa y mejora
sus probabilidades frente a v5: `sube` pasa de 0,824 a 0,940, `un` de 0,626 a
0,933 y `1 %` alcanza 0,890.

```text
output/runs/carrier_telefonica_baja-aeb1b28aa96e/experimentos/
  combinaciones_sube_un_v7_nasal/telefonica_sube_1.mp3
```

Aunque las métricas automáticas mejoraron, la escucha posterior volvió a
detectar una unión artificial y rechazó la versión. La explicación completa es
la asimilación contextual: la nasal donante estaba preparada para la `/k/` de
`cuarenta`, no para la vocal de `uno`. Este resultado confirma que correlación
y ASR no bastan. No hubo generación TTS ni coste de API adicional.
