Ir al contenido

Unidad 6

En esta unidad vas a continuar el trabajo arquitectónico de las unidades 4 y 5, pero esta vez la fuente de datos ya no será un dispositivo físico conectado por serial. En lugar de eso, vas a integrar una segunda aplicación web que genera eventos musicales en tiempo real usando Strudel.

El reto ya no consiste solamente en lograr que “dos cosas se comuniquen”. El reto real es mantener una arquitectura desacoplada, clara y explicable, en la que cada capa conserve su responsabilidad: una aplicación genera eventos, un adapter los traduce a un contrato estable, bridgeServer.js los transporta, y el frontend los interpreta y los convierte en una respuesta visual sincronizada en el tiempo.


Criterio (peso)Cumple plenamente (5.0)Se cumple medianamente (4.0)Problemas importantes (3.0)Falta comprensión básica (2.0)No hay evidencia (0.0)
1. Aplicación + bitácora (40%)La app se ejecuta sin fallos en el entorno acordado. La sincronización es consistente y la bitácora permite reconstruir el flujo completo del sistema. Todo es consistente con lo mostrado en la demo.La app funciona y logra la comunicación básica entre Strudel y la visual. La bitácora permite verificar lo esencial, aunque hay 1–2 vacíos menores.La app funciona parcialmente, la sincronización es inestable o la arquitectura no está claramente documentada. La bitácora tiene vacíos importantes.La app no corre o no demuestra lo requerido. La bitácora no permite verificar cómo se implementó la solución.No se entregaron evidencias o no se puede acceder a ellas
Evaluación
2. Sustentación (60%)Responde con precisión conectando: (a) los eventos musicales que se generan, (b) cómo viajan por el sistema, y (c) cómo se convierten en imagen sincronizada. Justifica decisiones y reconoce límites.Responde correctamente pero con imprecisiones menores o con una justificación superficial de algunas decisiones.Explica parcialmente qué sucede, pero le cuesta describir con claridad la arquitectura, el uso del tiempo o la separación de responsabilidades entre capas.No logra explicar de forma coherente el flujo de datos o mezcla conceptos sin relación clara con lo implementado.No se entregaron evidencias o no se puede acceder a ellas
Evaluación


En esta actividad vamos a estudiar un caso de integración entre dos aplicaciones que viven en el navegador y cuyo repositorio es este:

  1. Una app musical que genera eventos con Strudel.
  2. Una app visual que recibe esos eventos y los transforma en animación.

La meta no es copiar un experimento existente, sino analizarlo para entender qué problema arquitectónico resuelve y cómo se relaciona con lo que ya has trabajado en las unidades 4 y 5.

El experimento de referencia ya resuelve una parte importante del problema: la sincronización temporal. En ese caso de estudio, los eventos musicales no se ejecutan apenas llegan por WebSocket, sino cuando el reloj local alcanza el timestamp indicado por el mensaje.

Esto introduce una idea nueva para el curso:

  • En las unidades 4 y 5 el reto principal era parsear y validar datos.
  • En las unidades 4 y 5 esto se resolvía creando nuevos adapters sin romper el resto del sistema.
  • En esta unidad también debes programar cuándo ocurre la respuesta visual.

Paso 1: ¿Qué tipo de datos puede emitir Strudel?

Sección titulada «Paso 1: ¿Qué tipo de datos puede emitir Strudel?»

Para esta unidad vamos a usar Strudel como una aplicación generadora de eventos musicales. Un patrón como este:

setcps(0.5)
const pat = s("[bd*2 sd hh oh]").bank("tr909")
$: stack(
pat.gain('0.05'),
pat.osc()
)

puede producir mensajes con información como:

  • Qué sonido ocurrió;
  • Cuándo debería ocurrir;
  • Cuánto dura su ciclo rítmico;
  • Otros parámetros asociados al evento.

En vez de pensar en Strudel como “un sintetizador”, para esta unidad debes pensarlo como una fuente de eventos.

Supón que el bridge recibe este mensaje:

{
address: '/dirt/play',
args: [
'cps', 0.5,
'cycle', 15.25,
'delta', 0.5,
's', 'tr909sd',
'bank', 'tr909'
],
timestamp: 1774966984435.2805
}

Si la aplicación visual dispara la animación apenas llega el mensaje, el sistema queda amarrado a la latencia de red, al navegador y a la carga del computador.

Si en cambio la aplicación:

  1. recibe el mensaje;
  2. lo guarda en una cola;
  3. espera a que Date.now() alcance su timestamp;
  4. recién ahí activa la respuesta visual;

entonces la sincronización mejora y la arquitectura se vuelve más explícita.

Esto es importante porque permite distinguir dos capas conceptuales:

  • Transporte: mover el mensaje de una app a la otra;
  • Scheduling: ejecutar el evento en el instante correcto.

Aunque ahora no hay puerto serial ni micro:bit, la lógica de diseño sigue siendo la misma:

  1. Existe una fuente externa de datos;
  2. Esos datos deben traducirse a una forma comprensible por el sistema;
  3. Esa traducción debe encapsularse en un adapter;
  4. Hay una capa de transporte;
  5. Hay una capa de frontend que convierte eventos en estado y luego en imagen.

En otras palabras:

  • En la unidad 4 cambió el formato ASCII.
  • En la unidad 5 cambió el protocolo binario y apareció el framing.
  • En esta unidad cambia la naturaleza misma del evento: ahora es un evento musical con tiempo programado.

Un equipo de diseño sonoro ha creado una aplicación en Strudel que genera música en el navegador. Tu tarea es integrar esa aplicación a un sistema visual ya existente, pero debes hacerlo sin romper la arquitectura desacoplada que vienes desarrollando desde las unidades anteriores.

La documentación funcional del sistema es esta:

  • La aplicación de Strudel corre en el navegador.
  • Strudel envía eventos por WebSocket al puerto 8080.
  • Cada evento contiene información musical y una marca temporal timestamp.
  • Un Adapter debe recibir estos mensajes, normalizarlos y entregarlos a bridgeServer.js.
  • El bridge debe reenviarlos a la aplicación visual.
  • La aplicación visual debe responder de forma sincronizada con el tiempo indicado por el evento.

Ejemplo de mensaje de entrada al bridge:

{
address: '/dirt/play',
args: [
'cps', 0.5,
'cycle', 15.25,
'delta', 0.5,
's', 'tr909sd',
'bank', 'tr909'
],
timestamp: 1774966984435.2805
}

Qué debes implementar:

  1. Integrar una configuración de Strudel que emita eventos musicales por WebSocket hacia el puerto 8080.

  2. Crear un nuevo Adapter para Strudel, por ejemplo StrudelAdapter.js, que:

    • Reciba los eventos entrantes desde Strudel;
    • Los normalice a un formato claro para el sistema;
    • Los entregue a bridgeServer.js sin decidir cómo se dibujan.
  3. Registrar ese Adapter en bridgeServer.js sin convertir el bridge en el lugar donde vive la lógica de dominio.

  4. Adaptar bridgeClient.js para que:

    • Reciba los eventos reenviados;
    • Dispare el evento correspondiente hacia la capa de frontend.
  5. Implementar en el frontend una lógica que:

    • Reciba eventos musicales;
    • Los almacene en una cola;
    • Los active cuando llegue su timestamp;
    • Traduzca esos eventos en una respuesta visual coherente.

Arquitectura del frontend: guía de integración

Sección titulada «Arquitectura del frontend: guía de integración»

En esta unidad no basta con “hacer que algo se vea”. Debes respetar la arquitectura del frontend que ya vienes trabajando.

  1. bridgeClient.js

    • Recibe el mensaje normalizado reenviado por bridgeServer.js;
    • Inspecciona msg.type;
    • Dispara el evento correspondiente hacia la FSM.
  2. FSMTask

    • Recibe eventos ya normalizados;
    • No debe parsear mensajes crudos de Strudel;
    • Coordina la actualización de estado y la ejecución del render.
  3. updateLogic

    • Aquí aterrizan los datos del evento musical;
    • Aquí debes actualizar la cola de eventos temporizados;
    • Aquí debes traducir el mensaje a variables de estado visual.
  4. drawRunning

    • Aquí no debes parsear mensajes de red;
    • Aquí no debes decidir cómo interpretar msg.type;
    • Aquí solo debes leer el estado ya calculado y dibujar.

En otras palabras: bridgeClient.js recibe, FSMTask organiza, updateLogic actualiza estado y drawRunning dibuja.

Contrato mínimo sugerido para el evento normalizado:

{
type: "strudel",
timestamp: 1710000000000,
payload: {
eventType: "noteEvent",
s: "tr909bd",
delta: 0.25
}
}

No es obligatorio usar exactamente este contrato, pero tu sistema debe tener un formato estable, explícito y fácil de explicar en la sustentación.

Requisito mínimo funcional

Tu sistema debe soportar al menos estos sonidos:

  • bd
  • sd o cp
  • hh

y debe usar al menos estos parámetros:

  • tipo de sonido;
  • timestamp;
  • delta o alguna duración equivalente.

Exploración opcional

Si quieres llevar tu propuesta más lejos, puedes integrar:

  • Líneas de bajo;
  • Melodías;
  • Escalas;
  • Color por familia sonora;
  • Duración visual dependiente de delta;
  • Múltiples capas visuales simultáneas.

Pista de implementación

En las unidades 4 y 5 aprendiste que no conviene mezclar la lectura del protocolo con la lógica visual. Aquí ocurre lo mismo:

  • El Adapter debe traducir y normalizar el mensaje de Strudel;
  • bridgeServer.js no debe decidir colores, formas o composiciones;
  • El frontend no debería interpretar mensajes WebSocket desordenados o ambiguos;
  • La capa de estado debe convertir el evento musical en variables visuales y luego el render debe limitarse a dibujar.

Reflect: Consolidación y metacognición 🤔

Sección titulada «Reflect: Consolidación y metacognición 🤔»