Capítulo de sonido de la guía de Neblla — Eco, el estudio de música y efectos de Creator, y cómo suena lo que sale de él en una app o en cualquier web: Opus o MP3 de Medios, el bucle sin salto y world.sound. El contrato base está en core.txt; el motor 3D, en mundo.txt; el portal y la tienda, en creator.txt.
Sonido: Eco y cómo suena en tu app
Eco (https://creator.neblla.com/eco) es el estudio de Creator para hacer música, efectos de juego, grabaciones e instrumentos. Lo usa una persona con cuenta de developer; tu agente no lo maneja, pero lo que exporta acaba en los Medios de la app («Mandar a mi app») y se usa con lo de este capítulo.
Lo que hace Eco
- Canción, Música de fondo (un bucle), Efectos, Grabar e Instrumento son las cinco maneras de empezar. La Partitura se escribe en una cuadrícula (o se lee como pentagrama); los instrumentos de la casa los sintetiza Eco con su propio código, sin muestras con licencia.
- Efectos de juego: salto, moneda, golpe, explosión, láser, poder y clic, con «Al azar» y «Variar». Salen en WAV o MP3.
- Grabar pide el micrófono solo al pulsar; lo grabado se vuelve un efecto, una pista de la canción o un instrumento grabado.
- Lo que se baja o se manda a la app: la canción en Opus (WebM) y en MP3, más un
.jsonal lado con lo que existe y los puntos del bucle. Los efectos, en WAV o MP3.
Tocar un fichero de Medios en cualquier web
El navegador no toca nada hasta que la persona toca la página una vez (en el iPhone, además, el interruptor de silencio apaga Web Audio). Tras ese primer toque:
const a = new Audio('/media/tema.mp3'); // sirve para sonar una vez
a.play();
Escoge el fichero más ligero que el aparato sepa tocar: new Audio().canPlayType('audio/webm; codecs=opus') distinto de '' → el .webm; si no, el .mp3.
El bucle sin salto
Un MP3 lleva un retardo del codificador (unas 1100 muestras al principio y relleno al final) que ni <audio loop> ni new Audio() corrigen: cada vuelta suena un salto. Un bucle bueno se toca con AudioBufferSourceNode y sus loopStart y loopEnd en segundos, que son exactos a la muestra. Esos dos números van en el .json que Eco escribe al lado (ya movidos por el retardo de cada formato):
{ "v": 1, "name": "bosque", "seconds": 12, "loop": { "fromSeconds": 2, "toSeconds": 10 },
"sources": [
{ "format": "opus", "file": "bosque.webm", "type": "audio/webm; codecs=opus", "delaySamples": 0, "loopStart": 2, "loopEnd": 10 },
{ "format": "mp3", "file": "bosque.mp3", "type": "audio/mpeg", "delaySamples": 1105, "loopStart": 2.023021, "loopEnd": 10.023021 } ] }
La intro (hasta loopStart) suena una vez y luego se repite lo que hay entre loopStart y loopEnd.
En un juego de Mundo: world.sound
world.sound(nombre | dirección | hoja.json, { at, follow, loop, loopStart, loopEnd, volume, rolloff }) (mundo.txt, «Efectos y sonido»). Con la hoja que Eco escribe, una sola dirección basta:
const musica = world.sound('/media/bosque.json', { loop: true }); // sin at ni follow: música, no tiene sitio
Mundo lee la hoja, escoge la fuente más ligera que el aparato sabe tocar (Opus antes que MP3, y el MP3 si el aparato no sabe Opus), la decodifica y la repite entre los puntos de esa fuente. Con una dirección suelta (/media/bosque.mp3) y los puntos a mano: world.sound(url, { loop: true, loopStart: 2.023, loopEnd: 10.023 }). loopStart y loopEnd son segundos del sonido y solo valen con loop: true; si no, world_bad_sound. El manejador que devuelve dice qué suena: musica.source (la dirección del fichero elegido) y musica.loopPoints ({ start, end } o null). world.audio.muted = true calla todo.
Un efecto corto (/media/salto.wav) va igual, sin loop. Para sonidos con sitio, at: [x, y, z] o follow: cosa.
Vender lo que haces
Desde Eco, Vender deja la canción (o el efecto, o el instrumento) como borrador en la tienda y abre la pantalla de autor (/author?product=<id>) para poner el precio. Solo vende quien tiene 18 años (se pregunta la fecha una vez). Lo que se vende:
sound: un MP3, WAV u Opus de hasta 15 MB y 10 minutos. Lleva una copia para escuchar de 30 s o menos en calidad baja, hecha por Eco en el navegador; el fichero entero se guarda en privado y solo lo recibe quien tiene la licencia de developer. Un solo tipo de licencia:dev.instrument: el JSON de un instrumento de Eco. Su ficha deja probarlo con el teclado con una versión más ligera (la cuarta parte de las muestras).art2dymove: los de Flat y Mundo (creator.txt).
Quien compra la licencia de developer baja el fichero entero con GET /api/store/download/:id (con su sesión; un enlace que caduca a los cinco minutos) y su app pide la dirección con GET /api/store/asset/:id?app=<appId> (el dueño de la app tiene que tener esa licencia), que le da un enlace de una hora para world.sound(url). Nadie puede registrar la pieza en sistemas de identificación de contenido para reclamar a quien la compró, ni revenderla suelta.