Instrumento digital gestual
No hay osciladores RF ni medida de capacitancia. La cámara entrega coordenadas y Web Audio genera la señal.
Documento 03 · Especificación técnica
Inventario verificable del instrumento: adquisición de vídeo, estimación de manos, matemáticas de afinación, automatización continua, síntesis, dinámica, espacio, persistencia, captura y límites.
Esta especificación describe el código de Theremin Web 3 en julio de 2026. Los valores indicados son constantes o comportamientos de la implementación, no objetivos de marketing.
No hay osciladores RF ni medida de capacitancia. La cámara entrega coordenadas y Web Audio genera la señal.
HTML, CSS y JavaScript ES modules; sin framework, bundler, build, base de datos ni backend propio.
Los perfiles RCA/Rockmore modelan tendencias espectrales y registros; no son emulación circuital ni clon medido.
| Módulo | Responsabilidad | No debe decidir |
|---|---|---|
main.js | Orquestación, estado de sesión, modos, calibración, herramientas. | Algoritmo DSP interno. |
handTracking.js | Cámara, MediaPipe, timestamps y asociación temporal. | Frecuencias musicales. |
mapping.js | Landmarks → frecuencia/volumen/velocidad. | Forma de onda. |
scale.js | Conversión MIDI/nombre y atracción a escala. | Adquisición visual. |
pitchTrajectory.js | Puente exponencial continuo entre controles. | Rango o escala. |
thereminVoice.js | Fuente, saturación, formantes, filtro, VCA y vibrato. | Cámara o persistencia. |
audioEngine.js | Mezcla, cabinet, sala, eco, master y bus de grabación. | Identidad de manos. |
recorder.js | MediaRecorder y WAV PCM. | Vídeo o micrófono. |
El grafo Web Audio se crea después del gesto EMPEZAR. Las dos voces nacen una sola vez por sesión; los cambios de preset o cabinet usan automatización y crossfade, no destrucción inmediata de nodos.
MediaPipe Tasks Vision 0.10.35, Hand Landmarker float16, modo VIDEO, máximo dos manos. Umbrales de detección, presencia y tracking: 0,5.
Cámara frontal por defecto, 1280×720 ideal, hasta 60 FPS, audio:false. Las restricciones son ideales: el navegador negocia lo disponible.
Se intenta GPU. Si la creación falla, se reconstruye el modelo con CPU. Esto cambia rendimiento, no mapeo musical.
requestVideoFrameCallback si existe; requestAnimationFrame como fallback. Se evita procesar dos veces el mismo video.currentTime.
Con dos tracks previos se comparan asignación directa e intercambiada usando posición predicha por velocidad. Sin historial, las manos se ordenan por X teniendo en cuenta el espejo. Una sola mano se conecta al track cercano si la distancia es menor que 0,32; si no, se decide por mitad de imagen.
Una mano ausente conserva su último estado hasta 110 ms. Después la voz se silencia y se reinician mapeo y afinador. Un watchdog comprueba cada 100 ms si dejaron de llegar callbacks: su umbral nominal es 260 ms, por lo que el apagado efectivo puede caer aproximadamente entre 260 y 360 ms.
MediaPipe estima una mano visible; no recupera datos detrás de una oclusión completa. El seguimiento temporal reduce intercambios, pero no puede garantizar identidad si ambas manos desaparecen y reaparecen cruzadas.
Referencia externa: Hand Landmarker para Web y artículo de MediaPipe Hands.
El centro Y de la palma se filtra, se invierte —porque Y=0 está arriba—, se normaliza a la zona calibrada y se convierte a frecuencia:
p = clamp((1 − yFiltrada − inputLow) / (inputHigh − inputLow), 0, 1)f = fMin × (fMax / fMin)p
El exponente hace que una distancia visual igual represente un intervalo igual en octavas/cents. X no entra en la fórmula; solo ayuda a identidad y dibujo.
| Señal | minCutoff | beta | dCutoff | Objetivo |
|---|---|---|---|---|
| Posición | 1,8 | 0,32 | 1,2 | Estabilidad en reposo con respuesta al movimiento. |
| Apertura | 1,5 | 0,010 | 1,0 | Dinámica menos nerviosa. |
| Velocidad | 2,5 | 0 | 1,0 | Decidir atracción a escala. |
En Dúo, la pinza normalizada se convierte así: silencio en ratio ≤0,18, máximo desde 1,05 y curva v1,3. En Clásico, la mano izquierda usa altura calibrada para emular la antena de volumen. La derecha mantiene el tono.
La VCA no aplica esa amplitud linealmente en los perfiles históricos: usa −48 × (1 − √amplitud) dB para ganar resolución expresiva en el tramo bajo.
La cámara entrega objetivos discretos a 24–60 FPS; el audio trabaja normalmente a decenas de miles de muestras por segundo. Theremin Web no mantiene cada objetivo como escalón: programa el tramo que debe recorrer la frecuencia hasta el siguiente control.
exponentialRampToValueAtTime interpola geométricamente: lineal en octavas/cents, no en Hz.cancelAndHoldAtTime retiene el valor exacto cuando llega un nuevo destino. Un fallback reconstruye matemáticamente la posición de la rampa en motores antiguos.Continuidad de valor en la señal programada y un barrido Libre estrictamente monótono para una entrada monótona. No garantiza pendiente C1 ni elimina irregularidades de una detección visual errática.
| Escala | Intervalos | Respuesta |
|---|---|---|
| Libre | — | Identidad exacta; factor de atracción = 0. |
| Cromática | 0…11 | Atrae al semitono más próximo al detenerse. |
| Pentatónica mayor | 0, 2, 4, 7, 9 | Atrae a cinco grados por octava. |
| Mayor | 0, 2, 4, 5, 7, 9, 11 | Siete grados relativos a la tónica. |
| Menor natural | 0, 2, 3, 5, 7, 8, 10 | Siete grados relativos a la tónica. |
Velocidad ≥1,6 unidades normalizadas/s produce factor libre; ≤0,25 produce atracción completa. Entre ambos se interpola. El factor usa constante temporal de 45 ms y la frecuencia final se mezcla geométricamente hacia la nota de temperamento igual, La4=440 Hz.
Modifica el grave y la extensión para visualizar Do sucesivos. El cálculo limita el agudo a 5000 Hz, como la app.
| Perfil | Mínimo | Máximo | Octavas | Uso |
|---|---|---|---|---|
| Concierto completo | 32,70319566 Hz · Do1 | 2093,004522 Hz · Do7 | 6 | Extremo medido del instrumento Rockmore restaurado. |
| RCA 1929 | 123,47 Hz · ≈Si2 | 1396,91 Hz · Fa6 | ≈3,5 | Especificación histórica aproximada. |
| Rockmore estable | 65,41 Hz · Do2 | 2093 Hz · Do7 | 5 | Registro de concierto prudente. |
| Webcam cómoda | 130,81 Hz · Do3 | 1046,5 Hz · Do6 | 3 | Mayor resolución espacial por semitono. |
| Referencia | Registro aproximado | Relación con Theremin Web |
|---|---|---|
| Piano de 88 teclas | La0–Do8 | Do1–Do7 cubre 72 semitonos: omite La0–Si0 y la última octava superior. |
| Contrabajo | ≈Mi1–Do5 sonando | La zona grave del theremin solapa su fundamental, pero no su ataque ni caja. |
| Violonchelo | Do2 hacia registros agudos | Do2 es su cuerda grave; la riqueza RCA baja puede recordarlo perceptualmente. |
| Voces humanas | Conjunto aproximado Mi2–Do6 | El medio Rockmore puede sugerir una voz sostenida, sin formantes articulados ni texto. |
| Violín | Sol3 hacia ≈La7 | Gran solapamiento superior; el theremin carece de arco, cuerda y resonancia de madera. |
| Flauta de concierto | Do4–Do7 y algo más | Los agudos casi sinusoidales pueden evocar flauta o silbido, no simular su columna de aire. |
| Órgano | Mucho más amplio según registros | Órbita puede resultar organístico por parciales estables; no modela tubos ni recinto. |
El motor genera 32,7 Hz con sus armónicos; un teléfono o portátil puede dejar audible solo la estructura superior. La documentación de rango describe la señal, no la respuesta de tu altavoz.
frequency: a-rate, 16–5000 Hz.detune: a-rate, −100…+100 cents.timbreAmplitude: k-rate, 0…1; modula riqueza en perfiles históricos.Si AudioWorklet no está disponible o su módulo no carga, se construyen OscillatorNode y PeriodicWave:
La tabla de WaveShaper tiene 4096 puntos, drives positivo/negativo 1,55/1,22 y nivel negativo 0,91, con oversampling 4×. Rockmore realza 720 Hz +2,5 dB y 1450 Hz +1,7 dB; RCA +1,8/+1,1 dB. El filtro de salida se cierra al subir:
max(2450, 5100 − 690 × octavas sobre Do2) Hz.max(2700, 5600 − 650 × octavas sobre Do2) Hz.Los graves históricos son ricos, asimétricos y comparables a un centro de violonchelo; al subir se pierden armónicos hasta una señal próxima a seno. “Comparable” describe percepción, no emulación de instrumento acústico.
Referencia sobre el entorno usado: AudioWorklet en MDN.
| Preset | Perfil | Cabinet | Vibrato | Glide | Reverb | Eco |
|---|---|---|---|---|---|---|
| RCA/Rockmore | rca | No | No | 12 ms | 4 % | 0 |
| Rockmore concierto | rockmore | Sí | No | 10 ms | 12 % | 0 |
| RCA + Cabinet 1929 | rca | Sí | No | 12 ms | 10 % | 0 |
| Ciencia ficción | scifi | No | 5,8 Hz · 34 ¢ | 65 ms | 34 % | 16 % |
| Órbita prismática | experimental | No | No | 36 ms | 30 % | 13 % |
Rockmore define ataque 12 ms y release 24 ms. Los demás usan la constante de ganancia del perfil: RCA 18 ms, Cabinet 22 ms, Sci‑Fi 45 ms, Experimental 30 ms. La configuración interpretativa puede sustituir la respuesta de la voz derecha en Clásico.
Solo Sci‑Fi lo activa: comienza después de 450 ms de sonido audible y entra con constante de 240 ms. Rockmore, RCA y Experimental dejan el vibrato íntegramente a la mano.
X mezcla de 0 a 1 hacia el perfil Experimental. Y añade hasta 0,42 de reverb y 0,18 de eco sobre la base; límites finales 0,72 y 0,34 respectivamente.
| Etapa | Valor | Función |
|---|---|---|
| Pasa-altos | 68 Hz · Q 0,72 | Limita excursión y subgrave. |
| Cuerpo | +3,1 dB · 215 Hz · Q 0,82 | Resonancia de caja/grave. |
| Voz | +2 dB · 860 Hz · Q 0,68 | Presencia media. |
| Pasa-bajos | 5000 Hz · Q 0,66 | Ancho de banda de altavoz antiguo. |
| Saturación | WaveShaper asimétrico · 4× | No linealidad moderada. |
| Compresión | −15 dB · 2,2:1 · 18/95 ms | Comportamiento mecánico aproximado. |
Al activarse, la ruta directa va a 0 y cabinet a 0,92 mediante una constante de 55 ms. Una IR cargada se inserta después de filtros/saturación/compresión y sustituye la rama modelada final mediante crossfade de 80 ms; por tanto es una IR complementaria, no un “seco → IR” puro.
1 − wet × 0,22.Sci‑Fi usa 158 ms / feedback 0,17; Experimental 243 ms / 0,27. El feedback pasa por LP 4800 Hz y el nivel visible se limita a 0,4. El compresor final actúa como limitador: umbral −1 dB, knee 1,5, ratio 20:1, ataque 2 ms, release 120 ms.
La sala y el Cabinet 1929 son modelos diseñados. La app acepta una IR externa, pero todavía no incorpora una captura validada de un altavoz RCA 106 ni comparación espectral automatizada.
Suma media espera de captura, media rampa de enlace y latencia de salida que introduzcas. No incluye inferencia ni compositor del sistema; no sustituye una medida física extremo a extremo.
baseLatency + outputLatency cuando el navegador los expone.En poca luz, la cámara puede alargar exposición y bajar FPS antes de que el código intervenga.
GPU suele mejorar cadencia; CPU es fallback funcional. Resolución, SoC y carga térmica importan.
latencyHint:"interactive" solicita baja latencia, pero el navegador y dispositivo eligen el buffer real.
Bluetooth puede añadir decenas o cientos de milisegundos fuera del control Web Audio.
Objetivo manual de QA: tracking estable ≥24 FPS en móvil medio y ≥30 FPS en escritorio; audio cableado por debajo de 50 ms declarados cuando el sistema lo permita. No se afirma como garantía universal.
Modo Clásico · Rockmore · Libre · Do · Concierto completo Do1–Do7 · reverb 0,12 · Cabinet activo · inercia 10 ms · volumen 18 ms.
Los ajustes se guardan en localStorage bajo theremin-web:settings:v5. Existe migración desde v4: conserva datos seguros, descarta calibración horizontal y valida el rango.
| Se guarda | No se guarda |
|---|---|
| Sonido, perfil, modo, escala, tónica | Posición de sliders XY |
| Reverb, cabinet, cámara, entrenamiento | Estado drone |
| Rango, octavas, inercia, volumen | Gestos en memoria |
| Calibración tono/volumen | IR externa cargada |
min(0,55, max(0,22, octavas × 0,075)).MediaStreamDestination recibe la mezcla después de efectos, limitador y master.MediaRecorder.isTypeSupported.El formato JSON versión 1 registra eventos {t, frequency, amplitude, preset}, muestreados como máximo a 30 Hz. La importación limita a 18 000 eventos. La reproducción automatiza la voz derecha con requestAnimationFrame.
No hay llamadas propias fetch/XHR/WebSocket, analítica ni telemetría. Los frames pasan de video al modelo local.
El módulo y WASM llegan de jsDelivr; el modelo float16, de Google Storage. Sin esos recursos previamente cacheados no hay arranque offline completo.
Preferencias y calibración no están cifradas. No contienen vídeo, pero cualquier script del mismo origen podría leerlas.
IR, JSON y grabación permanecen en memoria/local hasta descarga o compartir. No se envían automáticamente.
Permissions-Policy: camera=(self), microphone=()X-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originCache-Control: public, max-age=0, must-revalidateNo hay Content Security Policy, Subresource Integrity ni service worker. Añadir CSP requiere autorizar explícitamente jsDelivr, Google Storage, WebAssembly y las necesidades de MediaPipe.
getUserMedia y Web Audio.| Capacidad preferida | Fallback | Diferencia observable |
|---|---|---|
| MediaPipe GPU | CPU | Posible reducción de FPS / mayor consumo. |
| requestVideoFrameCallback | requestAnimationFrame | Menor sincronía con frames reales; se evita duplicación. |
| AudioWorklet | OscillatorNode + PeriodicWave | Timbre aproximado, no bit-idéntico. |
| cancelAndHoldAtTime | Reconstrucción de trayectoria | Misma intención continua en motores antiguos. |
| MediaRecorder WebM/Opus | WebM, Ogg o MP4 | Contenedor depende del navegador. |
| Conversión WAV | Archivo comprimido original | WAV puede no generarse si el códec no se decodifica. |
| Web Share | Descarga | Sin panel de compartir del sistema. |
Chrome y Edge en Windows; Firefox; Safari en macOS e iOS/iPadOS; Chrome en Android. La sintaxis y las pruebas unitarias no sustituyen una sesión HTTPS con cámara/audio real en cada plataforma.
RCA/Rockmore y Cabinet 1929 son modelos perceptivos basados en tendencias documentadas. No reproducen cada válvula, transformador, bobina, antena, distorsión del altavoz ni interacción eléctrica del cuerpo.
| Archivo | Conceptos clave |
|---|---|
src/config.js | Versiones, filtros, rangos, presets, escalas y referencia 440 Hz. |
src/handTracking.js | MediaPipe, cámara, landmarks, asociación y FPS. |
src/oneEuro.js | Filtro adaptativo de posición, apertura y velocidad. |
src/mapping.js | Normalización vertical, ecuación logarítmica y pinza. |
src/scale.js | Temperamento igual, nombres españoles y atracción dinámica. |
src/pitchTrajectory.js | Estimación de frame y automatización continua compatible. |
src/theremin-worklet.js | Fuente aditiva a-rate, perfiles y antialias gradual. |
src/thereminVoice.js | Fallback, filtros, saturación, VCA y vibrato. |
src/audioEngine.js | Cabinet, convolver, eco, limitador y salida. |
src/settings.js | Esquema v5, migración, validación y calibración. |
src/recorder.js | MediaRecorder, Blob y codificador WAV. |
Para el uso cotidiano vuelve al manual; para entender por qué estas decisiones importan consulta la historia documentada.