Hace poco he ayudado a montar el CoderDojo de Carabanchel, que es un club de programación donde niños y niñas de entre 7 y 17 años aprenden a programar ayudados por mentores. Nos reunimos los sábados por la tarde, y yo intento ir siempre que puedo con mis dos hijas. Además, a veces preparo talleres. Al principio preparé un taller de p5js, que es una librería de JavaScript para crear arte interactivo en el navegador que gustó bastante, y ahora he preparado un taller de ToneJS una librería JavaScript para crear música interactiva en el navegador. Este último taller está muy relacionado con un artículo que escribí hace justo un año en dónde explicaba cómo programar la música de Star Wars con Gibber.
Tenéis todo el código y las librerías que necesitáis en un repositorio de mi GitHub.
Este es el código más básico para crear un botón que al pulsarlo haga sonar una nota, en este caso un DO, en el navegador:
<!DOCTYPE html> <html> <head> <title>ToneJS - 01 una nota</title> <script src="../lib/Tone.js"></script> </head> <body> <button id="do">UNA NOTA</button> </body> <script type="text/javascript"> const synth = new Tone.Synth().toMaster(); Tone.Transport.start(); document.querySelector("#do") .addEventListener("click", async () => { synth.triggerAttackRelease("C4", "4n"); }); </script> </html>El resultado es el siguiente (pulsa el botón para probar):
- DO=C
- RE=D
- MI=E
- FA=F
- SOL=G
- LA=A
- SI=B
A continuación, parte del código para hacer una especie de piano con botones:
<!DOCTYPE html> <html> <head> <title>ToneJS - 02 varias notas</title> <script src="../lib/Tone.js"></script> </head> <body> <button id="do">DO</button> <button id="re">RE</button> ... </body> <script type="text/javascript"> const synth = new Tone.Synth().toMaster(); Tone.Transport.start(); document.querySelector("#do") .addEventListener("click", async () => { synth.triggerAttackRelease("C4", "4n"); }); document.querySelector("#re") .addEventListener("click", async () => { synth.triggerAttackRelease("D4", "4n"); }); ... </script> </html>El resultado es el siguiente (pulsa los botones para probar):
<!DOCTYPE html> <html> <head> <title>ToneJS - 03 escala</title> <script src="../lib/Tone.js"></script> </head> <body> <button id="escala">ESCALA</button> </body> <script type="text/javascript"> const synth = new Tone.Synth().toMaster(); Tone.Transport.start(); document.querySelector("#escala") .addEventListener("click", async () => { synth.triggerAttackRelease("C4", "8n", 1); synth.triggerAttackRelease("D4", "8n", 2); synth.triggerAttackRelease("E4", "8n", 3); synth.triggerAttackRelease("F4", "8n", 4); synth.triggerAttackRelease("G4", "8n", 5); synth.triggerAttackRelease("A4", "8n", 6); synth.triggerAttackRelease("B4", "8n", 7); synth.triggerAttackRelease("C5", "8n", 8); }); </script> </html>El resultado es el siguiente (pulsa el botón para probar):
Aquí hay que remarcar que para los tiempos hay que tener en cuenta que:
- 1n hace referencia a una redonda (4 tiempos)
- 2n hace referencia a una blanca (2 tiempos)
- 4n hace referencia a una negra (1 tiempo)
- 8n hace referencia a una corchea (0,5 tiempos)
- 16n hace referencia a una semicorchea (0,25 tiempos)
<!DOCTYPE html> <html> <head> <title>ToneJS - 04 notas</title> <script src="../lib/Tone.js"></script> <script src="../lib/Rhythm.js"></script> </head> <body> <button id="notas">NOTAS</button> </body> <script type="text/javascript"> var synth = new Tone.Synth().toMaster(); document.querySelector("#notas").addEventListener("click", async () => { var notas = [ "C4","D4","E4","F4","G4","A4","B4","C5"]; var duraciones = [ "2n","4n","8n","16n","16n","8n","4n","2n"]; var cancion = Rhythm.mergeDurationsAndPitch(duraciones, notas); var part = new Tone.Part(function(time, value){ console.log(value.note + " " + value.duration); synth.triggerAttackRelease(value.note, value.duration, time); }, cancion ); part.start(0); Tone.Transport.start(); }); </script> </html>El resultado es el siguiente (pulsa el botón para probar):
Y la codificamos con ToneJS:
<!DOCTYPE html> <html> <head> <title>ToneJS - 05 cumpleaños feliz</title> <script src="../lib/Tone.js"></script> <script src="../lib/Rhythm.js"></script> </head> <body> <button id="notas">CUMPLEAÑOS FELIZ</button> </body> <script type="text/javascript"> var synth = new Tone.Synth().toMaster(); document.querySelector("#notas").addEventListener("click", async () => { var notas = [ "C4", "C4", "D4", "C4", "F4", "E4", "C4", "C4", "D4", "C4", "G4", "F4", "C4", "C4", "C5", "A4", "F4", "E4", "D4", "Bb4", "Bb4", "A4", "F4", "G4", "F4"]; var duraciones = [ "8n", "8n", "4n", "4n", "4n", "2n", "8n", "8n", "4n", "4n", "4n", "2n", "8n", "8n", "4n", "4n", "4n", "4n", "4n", "8n", "8n", "4n", "4n", "4n", "2n"]; var cancion = Rhythm.mergeDurationsAndPitch(duraciones, notas); var part = new Tone.Part(function(time, value){ console.log(time + " " + value.note + " " + value.duration); synth.triggerAttackRelease(value.note, value.duration, time); }, cancion ); part.start(0); Tone.Transport.start(); }); </script> </html>El resultado es el siguiente (pulsa el botón para probar):
Aquí hay que tener en cuenta que los trisillos se codifican con una t, en vez de con una n (ejemplo 8t). Y para los puntillos hay que disminuuir su número (ejemplo 3n).
<!DOCTYPE html> <html> <head> <title>ToneJS - 06 Star Wars</title> <script src="../lib/Tone.js"></script> <script src="../lib/Rhythm.js"></script> </head> <body> <button id="notas">Star Wars</button> </body> <script type="text/javascript"> var synth = new Tone.Synth().toMaster(); document.querySelector("#notas").addEventListener("click", async () => { var notas = [ "F3", "C4", "Bb3", "A3", "G3", "F4", "C4", "Bb3", "A3", "G3", "F4", "C4", "Bb3", "A3", "Bb3", "G3", "C3", "C3", "C3", "F3", "C4", "Bb3", "A3", "G3", "F4", "C4", "Bb3", "A3", "Bb3", "G3", "C3", "C3", "D3", "D3", "Bb3", "A3", "G3", "F3", "F3", "G3", "A3", "G3", "D3", "E3", "C3", "C3", "D3", "D3", "Bb3", "A3", "G3", "F3", "C4", "G3", "G3", "C3", "C3", "D3", "D3", "Bb3", "A3", "G3", "F3", "F3", "G3", "A3", "G3", "D3", "E3", "C4", "C4", "F4", "F3", "C4", "C3", "C3", "C3", "F3", "C4", "Bb3", "A3", "G3", "F4", "C4", "Bb3", "A3", "G3", "F4", "C4", "Bb3", "A3", "Bb3", "G3", "C3", "C3", "C3", "F3", "C4", "Bb3", "A3", "G3", "F4", "C4", "Bb3", "A3", "G3", "F4", "C4", "Bb3", "A3", "Bb3", "G3", "C3", "C3", "C3", "F4", "F4", "F4", "F4", "F4"]; var duraciones = [ "2n", "2n", "8t", "8t", "8t", "2n", "4n", "8t", "8t", "8t", "2n", "4n", "8t", "8t", "8t", "2n", "8t", "8t", "8t", "2n", "2n", "8t", "8t", "8t", "2n", "4n", "8t", "8t", "8t", "2n", "8n", "8n", "3n", "8n", "8n", "8n", "8n", "8n", "8t", "8t", "8t", "8n", "8n", "4n", "8n", "8n", "3n", "8n", "8n", "8n", "8n", "8n", "8n", "8n", "2n", "8n", "8n", "3n", "8n", "8n", "8n", "8n", "8n", "8t", "8t", "8t", "8n", "8n", "4n", "8n", "8n", "2n", "2n", "1n", "8t", "8t", "8t", "2n", "2n", "8t", "8t", "8t", "2n", "4n", "8t", "8t", "8t", "2n", "4n", "8t", "8t", "8t", "2n", "8t", "8t", "8t", "2n", "2n", "8t", "8t", "8t", "2n", "4n", "8t", "8t", "8t", "2n", "4n", "8t", "8t", "8t", "2n", "8t", "8t", "8t", "4n", "8t", "8t", "8t", "4n"]; var cancion = Rhythm.mergeDurationsAndPitch(duraciones, notas); var part = new Tone.Part(function(time, value){ console.log(time + " " + value.note + " " + value.duration); synth.triggerAttackRelease(value.note, value.duration, time); }, cancion ); part.start(0); Tone.Transport.start(); }); </script> </html>El resultado es el siguiente (pulsa el botón para probar):
0 comentarios:
Publicar un comentario