Arquitectura
Contenido
- Descripción general
- Procesos
- Transporte: BTstack + WinUSB
- Estructura de crates
- Ruta del audio e hilos
- Núcleo e IPC
- Asignación del controlador
- Módulos clave
- Elementos de información de códecs de fabricante
- Configuración y archivos
- Sistema de compilación
- Consideraciones importantes
Descripción general
BlueCaster habilita el audio Bluetooth LHDC V5, LDAC, aptX Adaptive, aptX HD, aptX Low Latency, aptX, Opus, AAC, SBC XQ y SBC en Windows (y LC3 sobre LE Audio). La pila Bluetooth propia de Windows solo admite SBC, aptX clásico y (solo en Windows 11) AAC para A2DP; esta herramienta añade los demás sin necesidad de un controlador de kernel.
Usa BTstack + WinUSB: todo en modo de usuario, sin necesidad de firmar controladores.
BlueCaster 2.0 está escrito en Rust. Las bibliotecas en C que no se pueden sustituir (BTstack y los codificadores de los códecs) se compilan desde el código fuente y se llaman a través de pequeños crates FFI; todo lo demás, incluido el codificador SBC, es Rust.
Procesos
BlueCaster se ejecuta como hasta tres programas:
| Programa | Se ejecuta | Función |
|---|---|---|
bluecaster-core.exe | Mientras BlueCaster está en ejecución (lo inician la ventana, el menú Inicio o Iniciar con Windows) | Bluetooth, captura y codificación del audio, perfiles y configuración, el icono de la bandeja y su menú, el servidor IPC. --cli ejecuta el mismo núcleo desde una consola |
bluecaster.exe | Solo mientras hay una ventana abierta (se cierra 3 minutos después de cerrar la última) | La ventana principal y el panel desplegable de la bandeja (Tauri 2, SolidJS + TypeScript). No guarda ningún estado propio |
bluecaster-driver.exe | Para un único cambio de controlador o una importación de claves, con derechos de administrador (UAC) | Asigna WinUSB a un adaptador o restaura su controlador anterior, o lee las claves de enlace que el Bluetooth de Windows guarda para un adaptador (windows-keys), y se cierra |
---
config:
flowchart:
wrappingWidth: 480
rankSpacing: 30
---
flowchart TB
ui["bluecaster.exe:<br>ventana y panel desplegable<br>de la bandeja<br>(Tauri + SolidJS)"]
src["Audio de Windows:<br>loopback del sistema /<br>dispositivo virtual /<br>una aplicación"]
subgraph core["bluecaster-core.exe"]
ctl["Menú de la bandeja /<br>servidor IPC / CLI (--cli)"] --> svc["Servicio del núcleo:<br>máquina de estados de la conexión,<br>selección de códec, perfiles,<br>reconexión"]
svc --> cap["Captura WASAPI"]
cap -- PCM --> enc["Canal de codificación:<br>LDAC / familia aptX / LHDC V5 /<br>Opus / AAC / SBC"]
enc --> bt["BTstack:<br>HCI / L2CAP / AVDTP /<br>A2DP / AVRCP"]
end
ui <-->|"canalización con nombre<br>por usuario"| ctl
src --> cap
bt -->|"WinUSB (nusb)"| usb["Adaptador Bluetooth USB<br>(controlador WinUSB)"]
usb -. Bluetooth .-> hp["Auriculares / altavoces"]
usb -.-|SetupAPI| drv["bluecaster-driver.exe (elevado):<br>asignar / restaurar WinUSB,<br>leer las claves de enlace de Windows"]
- El núcleo no es un servicio de Windows. Es un proceso normal del usuario que ha iniciado sesión, porque el loopback de WASAPI captura el audio de la sesión de ese usuario. Un mutex por sesión lo limita a una sola instancia; iniciarlo de nuevo abre la ventana.
- La bandeja pertenece al núcleo. Su menú de clic derecho (abrir, los 10 primeros dispositivos, desconectar, salir) se abre al instante, sin iniciar la ventana. Un clic izquierdo inicia el panel desplegable de la ventana (o la ventana principal, según la Configuración).
- La ventana solo muestra. Recibe una instantánea del estado del núcleo y después los cambios; cerrarla, o que la ventana se bloquee, no detiene el audio. Cerrar una ventana solo la oculta, así que volver a abrirla desde la bandeja es instantáneo.
- La línea de comandos usa el mismo núcleo.
bluecaster-core.exe --cliejecuta el servicio del núcleo sin bandeja ni IPC; la prueba con el emulador se ejecuta así.
Transporte: BTstack + WinUSB
Omite por completo la pila Bluetooth de Windows comunicándose directamente con un adaptador Bluetooth USB mediante WinUSB (controlador USB genérico firmado por Microsoft). BTstack, una pila Bluetooth de código disponible (licencia no comercial), implementa HCI, L2CAP, AVDTP y A2DP en modo de usuario.
Ventajas:
- Sin coste de firma de controladores
- No requiere el modo de firma de prueba
- No hay que desactivar el Arranque seguro
- Todo el código se ejecuta en modo de usuario (depuración más sencilla)
Inconvenientes:
- Requiere un adaptador Bluetooth USB dedicado (aparte del Bluetooth integrado de Windows)
- Mientras WinUSB lo controla, el adaptador no está disponible para el Bluetooth normal de Windows
- La dirección del dispositivo se escribe a mano o se encuentra con una búsqueda (GAP inquiry) con el adaptador USB
Cómo funciona:
- Se asigna WinUSB a un adaptador Bluetooth USB, desde la aplicación (Adaptador > Reemplazar por el controlador WinUSB, consulte Asignación del controlador) o con Zadig
- El crate
hci-transportabre el adaptador a través de WinUSB connusby lo conecta a BTstack como su transporte HCI - BTstack envía comandos HCI para inicializar el controlador Bluetooth
- (Adaptadores Realtek, Intel y Broadcom) Se carga el firmware si es necesario
- BTstack establece una conexión ACL y abre canales L2CAP (PSM 0x0019)
- La señalización AVDTP descubre los SEP remotos y negocia los códecs
- El audio codificado se envía como paquetes multimedia AVDTP sobre L2CAP
sequenceDiagram
participant App as BlueCaster (BTstack)
participant Ad as Adaptador USB
participant Sink as Auriculares
App->>Ad: Apertura mediante WinUSB,<br>reinicio / inicialización HCI
opt Realtek, Intel, Broadcom
App->>Ad: Carga del firmware
end
App->>Sink: Conexión ACL
Note over App,Sink: SSP Just Works en la primera conexión<br>(se guarda la clave de enlace)
App->>Sink: Canal L2CAP, PSM 0x0019<br>(señalización AVDTP)
App->>Sink: AVDTP DISCOVER / GET_CAPABILITIES
Sink-->>App: Extremos de transmisión y códecs
App->>Sink: SET_CONFIGURATION<br>(códec seleccionado), OPEN, START
loop Durante la transmisión
App->>Sink: Paquetes multimedia<br>AVDTP sobre L2CAP
end
El transporte USB conserva los pasos de recuperación que necesitaron los adaptadores reales en la v1: las canalizaciones de eventos y ACL se restablecen al abrir el adaptador, una lectura de eventos fallida se reintenta, los comandos HCI tienen tiempo de espera y al cerrar el adaptador se envía HCI Reset (no a un controlador que sigue en su bootloader), de modo que la siguiente sesión encuentra un controlador inactivo.
Estructura de crates
Un único workspace de Cargo (Cargo.toml en la raíz del repositorio) en cinco capas; cada capa depende solo de las capas inferiores. Las bibliotecas están en app/src/crates/, los programas en app/src/core, app/src/ui y app/src/driver; el aptx-adaptive incluido en el repositorio es una dependencia por ruta de codec, fuera del workspace. Solo los crates *-sys y win-sys pueden contener código unsafe; todos los demás crates tienen #![forbid(unsafe_code)].
| Capa | Crate | Función |
|---|---|---|
| 1. FFI | btstack-sys | Compila BTstack con cc (MSVC), declaraciones FFI escritas a mano y envoltorios seguros, btstack_config.h. BTstack solo puede llamarse en el hilo de su bucle de ejecución: el token !Send Stack lo garantiza |
| 1. FFI | ldac-sys, openaptx-sys, fdkaac-sys, lhdcv5-sys, opus-sys, lc3-sys | Compilan los codificadores en C y los exponen; un crate por biblioteca, para que cada licencia quede separada |
| 1. FFI | win-sys | API de Win32 sin biblioteca de Rust: MMCSS, el dispositivo de audio predeterminado (IPolicyConfig), la API WLAN (AFH), las notificaciones de energía, la clave Run, las teclas multimedia, la DACL de la canalización, la elevación, la asignación del controlador WinUSB (SetupAPI) y el Bluetooth propio de Windows (sus radios, dispositivos emparejados y claves de enlace) |
| 2. Componentes | hci-transport | HCI sobre USB («H2») con nusb, y H4 sobre TCP hacia un controlador virtual (tools/emu) |
| 2. Componentes | aptx-adaptive | El codificador aptX Adaptive en Rust (incluido en el repositorio desde AKS-Logic/aptx-adaptive-linux, MIT) |
| 2. Componentes | codec | El trait Encoder, el codificador SBC (port en Rust del de Bluedroid), envoltorios seguros de los codificadores en C, el análisis de Codec Information y la elección del códec |
| 2. Componentes | audio-capture | Captura WASAPI (crate wasapi): loopback del sistema, dispositivo virtual, una aplicación (loopback de proceso); listas de dispositivos y aplicaciones, tono de prueba, volumen por aplicación (Mezclador de volumen) |
| 2. Componentes | voice-link | El audio del micrófono del auricular (modo de desarrollador): PCM mono reproducido en el dispositivo de salida elegido (WASAPI), la captura mezclada a mono para el sentido de subida y los códecs de voz CVSD / mSBC / LC3-SWB sobre cargas SCO |
| 3. Motor | bt-host | Ejecuta BTstack en su propio hilo, controlado mediante comandos y eventos tipados: GAP, A2DP Source, AVRCP, SDP, canales RFCOMM para el paso directo (rfcomm.*), claves de enlace, los servicios SDP de un dispositivo, AFH, carga de firmware y cargadores de chips (bringup), la lectura de datos del chip y los scripts de chip, captura HCI (.pklg), LE Audio (le/) |
| 2. Componentes | le-audio | LE Audio: la lógica sin BTstack ni Windows (números asignados, LTV, PDU de PACS / ASCS, preajustes, los modelos CSIP / VCP / MCP / CCP) |
| 3. Motor | pipeline | Búferes circulares de PCM, conversión de formato, mezcla descendente, codificación, cargas útiles multimedia, ritmo de envío, ABR |
| 4. Núcleo | bluecaster-core (directorio core) | La máquina de estados, las reconexiones, suspensión / reanudación, los perfiles, la configuración y la migración desde la v1, la sincronización de volumen, el silencio de la salida, la búsqueda de actualizaciones, la descarga del firmware de Realtek, el cliente de la prueba con receptor, las estadísticas, los protocolos de fabricante (vendor/) |
| 4. Núcleo | ipc | Los tipos del protocolo compartidos por el núcleo y la ventana (serde; tipos de TypeScript generados con ts-rs) y el entramado de la canalización |
| 5. Programas | bluecaster-core-exe (app/src/core) | bluecaster-core.exe: núcleo, bandeja (tray-icon sobre un bucle de eventos tao), servidor IPC, --cli |
| 5. Programas | bluecaster-ui (app/src/ui) | bluecaster.exe: Tauri 2; la parte de Rust es un cliente IPC, la página es SolidJS + TypeScript + Vite |
| 5. Programas | bluecaster-driver (app/src/driver) | bluecaster-driver.exe: el auxiliar elevado |
Ruta del audio e hilos
---
config:
flowchart:
wrappingWidth: 480
rankSpacing: 30
---
flowchart TD
out["Salida de audio del sistema<br>(loopback / dispositivo virtual / una aplicación)"]
out --> cap["hilo capture:<br>WASAPI, controlado por eventos<br>(normalmente float32, 44.1–96 kHz)"]
cap -->|"búfer circular<br>sin bloqueos (PCM)"| enc["hilo encode:<br>conversión, mezcla descendente, codificador,<br>carga útil multimedia + encabezado RTP, ABR"]
enc -->|"búfer circular sin<br>bloqueos (paquetes)"| stack["hilo bt-runloop: BTstack → AVDTP → L2CAP → HCI"]
stack --> usb["hci-transport → WinUSB → adaptador Bluetooth USB → radio"]
usb -.-> hp["Auriculares / altavoces"]
| Hilo | Prioridad | Trabajo |
|---|---|---|
| capture | MMCSS “Audio” | Lee WASAPI; rellena con silencio los tramos sin sonido |
| encode | MMCSS “Pro Audio” | Convierte al formato que admite el codificador, codifica bloques completos del codificador (el resto espera a la siguiente ronda) y empaqueta las tramas en cargas útiles multimedia, en rondas de unos 10 ms para que los paquetes salgan de forma regular |
| bt-runloop | – | El bucle de ejecución de BTstack; envía un paquete en cola cada vez que L2CAP puede enviar. La cola de envío (64 paquetes) descarta un paquete que lleva 350 ms esperando, del más antiguo al más reciente, cada vez que se pone un paquete en cola |
| USB | – | Transferencias WinUSB: tres lecturas en curso en cada canalización IN (eventos, datos ACL), un escritor para los comandos y otro para los datos ACL (hasta 8 transferencias en curso) |
| core | Normal | Máquina de estados, IPC (tokio; las colas del paso directo RFCOMM, por conexión), configuración, estadísticas (4 Hz), búsqueda de actualizaciones |
Una vez que la transmisión está en marcha, la ruta del audio no asigna memoria ni toma ningún bloqueo. Las estadísticas son contadores atómicos que el núcleo lee cuatro veces por segundo. BTstack no es seguro entre hilos: los demás hilos le envían comandos, que se ejecutan en el hilo bt-runloop.
Núcleo e IPC
La ventana se comunica con el núcleo a través de la canalización con nombre del usuario \\.\pipe\bluecaster-<user SID>, cuya DACL solo admite a ese usuario. Los mensajes son tramas JSON precedidas de su longitud:
- La ventana envía
hello { protocol, client }. Un núcleo con otra versión de protocolo respondereject, y la ventana indica que los dos programas son de versiones distintas. Si no, el núcleo respondewelcome { protocol, server, features };featuresnombra las ampliaciones del protocolo (rfcomm). - El núcleo envía un
snapshot: todo su estado (adaptador, dispositivos, transmisión, perfiles, configuración, actualización) y un número de revisión. - A partir de ahí, el núcleo envía
events con los cambios. Si falta una revisión, la ventana obtiene una instantánea nueva. - Las acciones son
request { id, method, params }con unaresponse { id, result | error }. Los grupos de métodos sonstate.*,stream.*,device.*,profile.*,settings.*,adapter.*,audio.*,diag.*,receiver.*,rfcomm.*yapp.*.
Otros programas usan la misma canalización; lo que necesitan está en Integración (IPC). Las versiones anteriores a la 3.0.0 llamaban a la canalización \\.\pipe\a2dpwb-<user SID>; el núcleo también atiende ese nombre, durante al menos 6 meses después de la 3.0.0.
Los errores son códigos con parámetros (por ejemplo adapter.driver_missing), no textos; la ventana los traduce y ofrece la solución junto al mensaje. Los datos de alta frecuencia (calidad del enlace, el registro) solo se envían mientras una pantalla está suscrita a ellos.
La máquina de estados de la conexión:
stateDiagram-v2
[*] --> Idle
Idle --> Connecting: Iniciar
Connecting --> Streaming: transmisión iniciada
Connecting --> Idle: detenido
Connecting --> Error: fallo de inicialización /<br>conexión / códec
Streaming --> Reconnecting: conexión perdida
Reconnecting --> Streaming: reconectado
Reconnecting --> Error: fallo de reconexión
Streaming --> Idle: Detener
Error --> Connecting: Iniciar de nuevo
Una conexión fallida se intenta hasta 3 veces. Un enlace perdido se reconecta hasta 3 veces, o hasta 10 veces después de reiniciar la pila (suspensión, un adaptador que dejó de funcionar). Cuando el PC entra en suspensión, el núcleo detiene BTstack sin contar el enlace perdido como un fallo y vuelve a conectar cuando el PC se reanuda.
Asignación del controlador
Windows 8 y posteriores incluyen el controlador WinUSB firmado por Microsoft (winusb.inf). bluecaster-driver.exe hace lo mismo que «Actualizar controlador > Elegir en una lista > WinUsb Device» del Administrador de dispositivos, mediante SetupAPI:
- Abre el adaptador por su ID de instancia de dispositivo.
- Escribe un valor
DeviceInterfaceGUIDsen susDevice Parameters, para que WinUSB registre una interfaz de dispositivo para él. - Selecciona el modelo «WinUsb Device» de
%SystemRoot%\INF\winusb.infy lo instala conDiInstallDevice. El controlador incluido en Windows está firmado, así que no se instala ningún certificado (a diferencia de Zadig / libwdi, que firman un INF generado con un certificado propio). - Restaurar: quita el dispositivo (
DiUninstallDevice) y lo vuelve a enumerar; Windows elige entonces de nuevo su controlador mejor clasificado (normalmenteBthUSBo el del fabricante). El controlador que tenía antes el adaptador se registra en la carpeta de configuración (driver\) y se compara tras la restauración.restore --records <folder>restaura todos los adaptadores registrados en una sola ejecución elevada; el desinstalador lo usa después de preguntar.
El núcleo nunca se ejecuta como administrador: para una asignación o una restauración inicia el auxiliar con una solicitud de UAC (ShellExecuteEx “runas”) y lee su resultado JSON. Enumerar los adaptadores y su controlador no requiere elevación.
sequenceDiagram
participant Core as bluecaster-core
participant Drv as bluecaster-driver (elevado)
participant Win as Windows (SetupAPI)
Core->>Drv: inicio con un aviso de UAC
alt Asignar
Drv->>Win: DeviceInterfaceGUIDs<br>en Device Parameters
Drv->>Win: instalar winusb.inf<br>(WinUsb Device)
else Restaurar
Drv->>Win: quitar el dispositivo<br>y volver a enumerarlo
Win->>Win: vuelve a elegir su<br>mejor controlador
end
Drv-->>Core: resultado (JSON)
Módulos clave
Elección del códec (codec::caps)
- Analiza las capacidades del dispositivo remoto: los elementos estándar de SBC y AAC y los códecs de fabricante, incluido aptX LL con ambos Vendor ID y aptX Adaptive (receptores R1 y R2; solo utilizable con 48 kHz estéreo)
- Elige el códec: Automático toma el códec de mayor calidad de sonido que ofrece el remoto; un códec solicitado que el remoto no ofrece se sustituye por el mismo códec que tomaría Automático (siempre para un perfil, desde el issue #86; en la línea de comandos solo con
--fallback), y en caso contrario es un error - Transmite cada perfil A2DP como Automático, con los ajustes predeterminados de Automático, mientras el ajuste
auto_codecestá activado (Códecs > Seleccionar automáticamente el códec compatible de mayor calidad, un único ajuste para todos los dispositivos desde el esquema 5); el códec elegido para el dispositivo se conserva en su perfil para cuando esté desactivado - Sigue el orden de códecs del dispositivo tal como el usuario arrastró sus tarjetas (el
codec_orderdel perfil;codec::AutoOrder, vacío para mayor calidad de sonido primero), para la elección de Automático y para la alternativa de un códec elegido, también con la selección automática. FastStream y Opus 05 nunca son la elección de Automático ni una alternativa. (Las betas de 2.0.2 tenían un orden para todos los dispositivos, elauto_orderde settings.json, que ahora se ignora.) - Elige la frecuencia de muestreo de la familia aptX (44.1 / 48 kHz entre las que anuncia el remoto; WASAPI remuestrea la captura); aptX Adaptive usa 48 kHz, o 96 kHz cuando se eligen 96 kHz, la calidad es Alta y el receptor es R2 y anuncia 96 kHz. Una frecuencia en Automático (también con la selección automática) pide 48 kHz, y el selector de cada códec toma la mejor que anuncia el receptor si no la tiene (issue #86: no la frecuencia más alta que anuncia ni la frecuencia de mezcla de Windows)
- Asigna la calidad del perfil a las que ofrece el códec (
Quality::for_codec, issue #86): LDAC y LHDC V5 Alta / Media (sq) / Baja (mq), LHDC V5 también Media-alta (mhq), aptX Adaptive Alta / Baja latencia, todos los demás códecs Alta (la tasa de bits más alta que acepta el dispositivo); una calidad que el códec ya no tiene (Estándar / Móvil de aptX Adaptive, los niveles inferiores de AAC) funciona como Alta - Registra lo que anuncia cada códec que ofreció el dispositivo (
KnownCodecs.caps: frecuencias de muestreo, profundidades de bits, tasa de bits máxima;RemoteCaps::listed_*), para que los ajustes del códec solo ofrezcan esos valores; el rango de bitpool de SBC ya se registraba
Host Bluetooth (bt-host)
Responsabilidades:
- Ejecutar BTstack con el transporte HCI USB (o TCP) en su propio hilo
- Registrar los extremos de transmisión: códecs de fabricante (LDAC, aptX HD, aptX, aptX LL, LHDC V5, FastStream, Opus, Opus 05, aptX Adaptive) además de SBC (que también usa SBC XQ) y AAC: 11 en total (
MAX_NR_AVDTP_STREAM_ENDPOINTSde BTstack) - Registrar los registros SDP (A2DP Source, AVRCP Controller, AVRCP Target; HFP Audio Gateway, solo para el nivel de batería, mientras ese ajuste está activado)
- Gestionar el emparejamiento SSP (Just Works, General Bonding; claves de enlace persistentes)
- Cerrar una conexión semiabierta tras un tiempo de espera de conexión, para que los reintentos funcionen
- Reintentar una conexión fallida (hasta 3 intentos) y distinguir las causas (sin respuesta, enlace sin datos, el remoto cerró el enlace, autenticación); descartar una clave de enlace que el dispositivo ya no reconoce y volver a emparejar
- GAP inquiry para la búsqueda de dispositivos
- Volumen absoluto AVRCP y los botones de los auriculares
- Clasificación de canales AFH del host y lecturas de RSSI / AFH para la vista de calidad del enlace
- Carga de firmware: Realtek y Broadcom mediante los controladores de chipset de BTstack, Intel (bootloaders heredado y TLV) en Rust sobre la interfaz común de cargadores de chips (
bringup), cuyo progreso muestra la pantalla Adaptador mientras se inicia el adaptador - Modo de desarrollador: la lectura de datos del chip (lo que un adaptador responde a comandos de lectura estándar, un informe JSON en
logs\probe\), los scripts de chip (solicitudes escritas como texto, ejecutadas en un adaptador con WinUSB) y los servicios SDP que anuncia un dispositivo conectado - Captura HCI (
.pklg), incluido el establecimiento de la conexión si empieza con la conexión ya en curso
API clave de BTstack utilizadas:
a2dp_source_create_stream_endpoint()— Registrar los extremos de códeca2dp_source_establish_stream()— Conectar con el receptor A2DPa2dp_source_set_config_other()— Configurar un códec específico del fabricantea2dp_source_stream_send_media_payload_rtp()— Enviar audio codificado con encabezado RTP (LDAC, aptX HD, AAC, SBC, SBC XQ, LHDC V5, Opus)a2dp_source_stream_send_media_packet()— Enviar paquetes multimedia sin procesar, sin encabezado RTP (aptX, aptX LL, FastStream), o con el encabezado RTP propio de BlueCaster (aptX Adaptive)
Captura de audio (audio-capture)
Captura el audio en tiempo real mediante Windows Audio Session API.
- Loopback del sistema del dispositivo de salida predeterminado, loopback de un dispositivo (virtual) elegido, o loopback de proceso de una aplicación y sus procesos secundarios (Windows 10 compilación 19041 o posterior)
- Entrega el formato de mezcla del modo compartido del dispositivo (normalmente float32; el pipeline lo convierte para el codificador)
- En el modo Aplicación, espera a la aplicación y la vuelve a captar cuando se reinicia
- Ajusta el volumen y el silencio de una aplicación en la salida predeterminada, como hace el mezclador de volumen de Windows (
mixer): el volumen de una sesión llega a la captura loopback, también mientras el núcleo silencia esa salida durante una transmisión con Loopback del sistema (bluecaster-core::mute_output)
Protocolos de fabricante (bluecaster-core::vendor)
Algunos auriculares solo ofrecen un códec o una tasa de bits después de que su propia app cambie un modo a través de su propio servicio RFCOMM. Un módulo por fabricante lo hace a través del enlace que tiene BlueCaster, para los auriculares que se distinguen por el nombre que indican:
- Huawei / Honor: un perfil que pide LDAC a unos auriculares que no lo anuncian activa su modo «prioridad a la calidad de sonido» y vuelve a conectar; a los auriculares que tenían el modo desactivado se les devuelve así cuando no se obtuvo LDAC. Nunca con Automático
- OPPO: cuando LHDC V5 transmite (elegido o por Automático), se pide Hi-Res a los auriculares una vez, con una sola conexión nueva para leer lo que anuncian entonces; el registro de ello se guarda con los códecs del dispositivo (
device_codecs.json) hasta quedevice.forget_codecslo borra
La pestaña Fabricantes del modo de desarrollador cambia cuándo se usa cada uno (Automático por nombre, Siempre, Nunca) y ofrece las opciones propias del fabricante.
Emparejamientos (link_keys, win-sys::bt_keys)
Las claves de enlace se guardan en link_keys.txt. Donde se añaden dispositivos, el núcleo puede adoptar las claves que el Bluetooth de Windows guardó para el adaptador que BlueCaster usa ahora: bluecaster-driver.exe windows-keys las lee (una solicitud de UAC), una clave que BlueCaster ya tiene se conserva, y los dispositivos de audio entre ellas se guardan con los nombres de Windows. El modo de desarrollador muestra la clave de enlace de un dispositivo y los servicios SDP que anuncia.
Los archivos de claves de pairing\ (claves de enlace, vínculos LE, conjuntos coordinados, claves LE tomadas de Windows, claves de Windows reemplazadas) se cifran con DPAPI para el usuario de Windows (win-sys::dpapi); otros usuarios, y los mismos archivos copiados a otro PC, no pueden leerlos. Los archivos en texto plano de versiones anteriores se leen y se reescriben cifrados. Un archivo que no se puede descifrar se conserva como <nombre>.undecryptable y sus dispositivos se emparejan de nuevo. BlueCaster guarda él mismo el TLV LE de BTstack (el TlvStore de btstack-sys, con el contenido que escribía btstack_tlv_windows). keys_for_windows.json, que el asistente con permisos de administrador lee al restaurar, sigue en texto plano (el asistente puede ejecutarse como otro administrador) y se borra cuando termina.
Codificadores de audio
| Codificador | Biblioteca | Tasa de bits | Características |
|---|---|---|---|
| LHDC V5 | lhdcv5-enc (port en C del codificador de AOSP) | 400/500/900/1000 kbps (Baja/Media/Media-alta/Alta), como máximo el máximo que anuncia el receptor, ABR 160–400 kbps | 16/24 bits, tramas de 5 ms, encabezado de carga útil multimedia de 2 bytes, encabezado RTP |
| LDAC | libldac (AOSP) | 330/660/990 kbps | Modos Alta/Media/Baja (HQ/SQ/MQ), ABR |
| aptX Adaptive | aptx-adaptive (codificador en Rust puro de AKS-Logic/aptx-adaptive-linux, MIT) | 427 kbps en Alta, 265 kbps en Baja latencia (receptores R2: 270); ABR baja a 364/318 (R2: 270/204) | 48 kHz estéreo (96 kHz en Alta cuando se eligen, a un receptor R2 que los anuncia: 646/340/255 kbps), 24 bits; un paquete del códec por paquete multimedia tras el encabezado RTP propio de BlueCaster; ABR en Alta; Automático lo toma después de LHDC V5 y LDAC |
| Opus | libopus 1.5.2 | 256 kbps (estéreo; mono la mitad) | Opus A2DP de Android: 48 kHz, tramas de 20 ms (10 ms si el receptor solo admite eso), VBR restringida limitada a la carga útil multimedia, una trama por paquete, encabezado de carga útil multimedia de 1 byte, encabezado RTP |
| aptX HD | libopenaptx | 576 kbps | Entrada de 24 bits, tasa fija, encabezado RTP |
| aptX | libopenaptx | 352/384 kbps (44.1/48 kHz) | Estéreo de 16 bits, sin encabezado RTP |
| aptX LL | libopenaptx | 352 kbps | Latencia de ~32 ms, sin encabezado RTP, paquetes ≤ ~7.5 ms |
| AAC | fdk-aac | hasta 256 kbps (como máximo la tasa de bits que anuncia el receptor) | AAC-LC, transporte LATM |
| SBC XQ | el mismo codificador SBC | ~385/505/552 kbps | Canal dual, bitpool 47 / 43 a 44.1 / 48 kHz (Alta); solo cuando el SBC del receptor admite canal dual y un bitpool de al menos 29 (el bitpool se limita entonces al máximo del receptor, como PipeWire); comparte con SBC el extremo de transmisión, el encabezado de carga útil multimedia y el encabezado RTP |
| SBC | Port en Rust del codificador de Bluedroid | hasta ~345 kbps | Base obligatoria de A2DP; idéntico bit a bit al codificador en C (probado en todas las configuraciones) |
| FastStream | el mismo codificador SBC | 198/216 kbps (44.1/48 kHz) | Códec de fabricante de CSR, solo en la dirección de música (sin canal de retorno de voz): SBC joint stereo con bitpool 29, tramas rellenadas hasta 72 bytes, 3 por paquete, sin encabezado de carga útil multimedia ni encabezado RTP (como PipeWire); Automático nunca lo elige |
Todos los codificadores implementan el trait codec::Encoder: indican el formato PCM y el número de tramas que consume una llamada, y devuelven tramas del códec.
libopenaptx espera grupos de 4 muestras estéreo como PCM de 24 bits empaquetado little-endian; los envoltorios de aptX convierten las muestras de 16 o 32 bits a ese formato, y la entrada mono se duplica en ambos canales.
Elementos de información de códecs de fabricante
Los códecs no estándar se registran como Vendor Specific en AVDTP:
| Códec | Vendor ID | Codec ID |
|---|---|---|
| LHDC V5 | Savitech (0x0000053A) | 0x4C35 |
| LDAC | Sony (0x0000012D) | 0x00AA |
| aptX Adaptive | Qualcomm (0x000000D7) | 0x00AD |
| Opus | Google (0x000000E0) | 0x0001 |
| aptX HD | Qualcomm (0x000000D7) | 0x0024 |
| aptX | APT (0x0000004F) | 0x0001 |
| aptX Low Latency | CSR (0x0000000A) o Qualcomm (0x000000D7) | 0x0002 |
| FastStream | CSR (0x0000000A) | 0x0001 |
| Opus 05 | The Linux Foundation (0x000005F1, PipeWire) | 0x1005 |
AAC y SBC usan los Codec ID estándar de A2DP definidos en la especificación de A2DP.
Tamaños de los elementos de información de códec (incluidos los 6 bytes de Vendor ID/Codec ID):
- aptX: 7 bytes (byte 6 = frecuencia de muestreo / modo de canal)
- aptX HD: 11 bytes (byte 6 como en aptX, más 4 bytes reservados); se requiere estéreo
- aptX LL: 8 bytes, o 17 bytes cuando el receptor activa el indicador extendido («new caps»). BlueCaster registra un único extremo aptX LL y configura el flujo con el Vendor ID que usó el receptor
- LHDC V5: 11 bytes (
a2dp_vendor_lhdcv5_constants.hde Android): byte 6 frecuencias de muestreo (0x20 44.1k, 0x10 48k, 0x04 96k, 0x01 192k), byte 7 profundidad de bits (0x04 16 bits, 0x02 24 bits) y los límites mínimo/máximo de tasa de bits del receptor, byte 8 subversión del códec (0x01 = V5 ver.1) y 0x10 = tramas de 5 ms, bytes 9-10 funciones opcionales (baja latencia, sin pérdida, JAS, AR, META), ninguna de las cuales ofrece BlueCaster. Solo estéreo. Los límites de tasa de bits del receptor se devuelven en la configuración y se aplican al codificador, como hace Android. Los paquetes multimedia llevan un encabezado de carga útil de 2 bytes: número de tramas « 2 (bits de latencia 0) y un número de secuencia - FastStream: 8 bytes (
a2dp_faststream_tde PipeWire): byte 6 dirección (0x01 sink = música, 0x02 source = voz), byte 7 en el nibble bajo las frecuencias del receptor (0x2 44.1k, 0x1 48k), en el nibble alto la frecuencia de la fuente (0x2 16k). BlueCaster ofrece y configura solo la dirección de música - Opus: 7 bytes (
a2dp_vendor_opus_constants.hde Android): byte 6 bits 2..0 modo de canal (0x01 mono, 0x02 estéreo, 0x04 mono dual), bits 4..3 duración de trama (0x08 10 ms, 0x10 20 ms), bit 7 48 kHz. BlueCaster ofrece mono y estéreo, 10 y 20 ms, y configura estéreo a 20 ms (mono solo para una entrada mono hacia un receptor que lo admita). Los paquetes multimedia llevan un paquete Opus tras un encabezado de carga útil de 1 byte (número de tramas 1 en los 4 bits bajos) - aptX Adaptive: 40 bytes. El evento de capacidades de BTstack recorta la información del códec del receptor a 30 bytes, que siguen conteniendo todo lo que usa BlueCaster. SET_CONFIGURATION: 48 kHz con tipo de fuente 2 (codificador en el host: el receptor temporiza la reproducción por sí mismo), estéreo; un receptor R1 recibe de vuelta sus propios bytes de latencia objetivo, con LL0 elevada a al menos 80 ms y una latencia HQ de cero sustituida por 200 ms; un receptor R2 recibe el bloque R2 propio de la fuente
Con o sin RTP: los paquetes multimedia de LDAC, aptX HD, AAC, SBC, SBC XQ, LHDC V5 y Opus llevan el encabezado RTP de 12 bytes. aptX, aptX LL y FastStream se envían sin encabezado RTP (como hacen Android y PipeWire), de modo que toda la MTU de L2CAP queda disponible para las tramas aptX.
aptX Adaptive envía un paquete del códec por paquete multimedia tras el encabezado RTP de 12 bytes propio de BlueCaster (BTstack no añade ninguno): tipo de carga útil 96, número de secuencia +1 por paquete, marca de tiempo = las muestras por canal del paquete (no un reloj), SSRC = el modo de latencia del receptor (0x000000A3 HQ, 0x000000A1 LL). La carga útil lleva los bytes intercambiados en palabras de 16 bits. Los paquetes HQ tienen 656 bytes (12 ms) y los LL 348 bytes (10 ms). Automático lo prefiere a aptX clásico, Opus y AAC (el orden del issue #86), por debajo de LHDC V5 y LDAC.
Configuración y archivos
Todo se guarda en la carpeta de configuración, %APPDATA%\BlueCaster (o la carpeta indicada por la variable de entorno BLUECASTER_CONFIG_DIR); los archivos que tenían la v1 y la 2.0.x conservan sus formatos (la 2.0.x usaba %APPDATA%\A2DPWB; la 3.0.0 cambia el nombre de esa carpeta en su primer inicio y ordena los archivos en las carpetas de abajo):
| Ruta | Contenido |
|---|---|
settings.json | Configuración de la aplicación, con un schema_version; las claves desconocidas se conservan |
profiles.json | Perfiles |
devices\devices.txt | Dispositivos conocidos |
devices\le_audio_devices.txt | LE Audio: las entradas LE Audio de la lista de dispositivos |
devices\device_codecs.json | Lo que ofreció cada dispositivo clásico en su última conexión (y si se pidió Hi-Res a unos auriculares OPPO) |
pairing\link_keys.txt | Claves de enlace: los auriculares emparejados con la v1 o la 2.0.x se reconectan sin volver a emparejar |
pairing\le_audio_bonds.tlv, pairing\le_audio_csip.txt | LE Audio: los vínculos LE (con los valores CCC persistentes del servidor GATT) y los conjuntos coordinados |
pairing\windows_le_keys.txt, pairing\replaced_windows_keys.json | Claves LE tomadas de Windows hasta que una pila con LE las añade; las claves de Windows que reemplazó Restaurar el controlador original |
adapters\adapter_caps.json | Lo que una pila averiguó de cada adaptador (compatibilidad con LE Audio, dirección, versión HCI, el nombre que le da Windows) |
adapters\driver\<instance id>.json | El controlador anterior de cada adaptador al que se asignó WinUSB |
firmware\ | Archivos de firmware (*.bin, *.hcd, ibt-*; los de Intel también en firmware\intel\, como los organiza linux-firmware); los archivos que versiones anteriores dejaban sueltos en la carpeta de configuración se mueven aquí |
logs\<YYYY-MM-DD>\core.log, ui.log, driver.log | Los registros del núcleo, de la ventana y del auxiliar del controlador, una carpeta por día (UTC); sin enmascarar |
logs\hci\*.pklg | Capturas HCI: las del registrador de vuelo, escritas cuando falla una transmisión o se pierde una conexión (las 10 más recientes), y las que inicia usted mismo (hci_<date>_<time>.pklg) |
logs\probe\ | Informes de la lectura de datos del chip y de los scripts de chip (los 10 más recientes) |
logs\crash\ | Informes de bloqueo: un minivolcado (*.dmp) y un archivo de texto por bloqueo (los 5 más recientes por programa) |
logs\bundles\*.zip | Paquetes de diagnóstico (los 3 más recientes) |
backup\v1\ | Una copia de la configuración de la v1, creada una sola vez en el primer inicio de la v2 |
backup\v2\ | Una copia de la configuración y los emparejamientos de la 2.0.x, creada una sola vez en el primer inicio de la 3.0.0 |
backup\profiles-before-codecs.json | profiles.json tal como estaba antes de que la pantalla Códecs integrara varios perfiles de un dispositivo en uno (se escribe una vez) |
La carpeta del programa es %LOCALAPPDATA%\BlueCaster\: los tres programas, el desinstalador y licenses\ (licenses\README.txt, licenses\bluecaster\LICENSE..., licenses\third-party\...). La caché de descarga del firmware es %TEMP%\bluecaster-cache.
Sistema de compilación
- Cargo compila los programas; no necesitan CMake. Cada crate
-syscompila su biblioteca en C desde el submódulo git deextern/con MSVC enbuild.rs. Solo la herramienta para desarrolladorestools/a2dp_decodese compila con CMake - La página de la ventana se compila con Vite (
pnpm buildenapp/src/ui) y Tauri la incrusta enbluecaster.exe - Los tipos de TypeScript del protocolo IPC se generan a partir de los tipos de Rust (
cargo test -p ipc export_bindings) - Los archivos de idioma (
app/lang/*.json) los usan la ventana y el menú de la bandeja del núcleo installer/build-release.ps1genera el instalador (Inno Setup,installer/BlueCaster.iss), el zip portable y el manifiesto del actualizador. Consulte Compilación
Consideraciones importantes
- Compatibilidad de adaptadores: Realtek (los más probados), CSR, Intel, Broadcom, MediaTek y otros (Hardware verificado). Los adaptadores Realtek necesitan cargar el firmware al iniciar, y también los Intel en modo bootloader
- Emparejamiento: usa SSP Just Works con General Bonding. Las claves de enlace se guardan en un archivo local, o se adoptan del Bluetooth de Windows para el adaptador
- Se recomienda un segundo adaptador: mantenga el Bluetooth integrado para Windows y use un adaptador USB dedicado para BlueCaster
- El firmware de algunos adaptadores Bluetooth limita la tasa de bits alcanzable
- Por lo general, los adaptadores USB Bluetooth 5.0+ funcionan bien con LDAC
- Prioridad de la selección automática de códec (por calidad de sonido, issue #86): LHDC V5 > LDAC > aptX Adaptive > Opus > aptX HD > aptX > aptX LL > AAC > SBC XQ > SBC (FastStream y Opus 05 solo si se eligen); un códec elegido que el dispositivo no ofrece pasa al primero del orden del dispositivo que este ofrezca