<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Play Along</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <link rel="icon" type="image/png" sizes="174x174" href="./favicon.png"> <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2/webcomponents-bundle.js"></script> <script src="../build/Tone.js"></script> <script src="./js/tonejs-ui.js"></script> <style type="text/css"> tone-play-toggle { margin-bottom: 10px; } tone-slider { display: block; width: 100%; } </style> </head> <body> <tone-example> <tone-loader></tone-loader> <tone-explanation label="Play Along"> Touch/Mouse and drag to play along with the probabilistic backtrack. X = pitch, Y = modulation. </tone-explanation> <tone-content> <tone-play-toggle></tone-play-toggle> <tone-slider-2d></tone-slider-2d> </tone-content> <tone-drawer collapsed> <tone-compressor collapsed id="compressor" label="Drum Compressor"></tone-compressor> <tone-distortion collapsed id="distortion" label="HH/Snare Distortion"></tone-distortion> <tone-player collapsed id="hats" label="Hats"></tone-player> <tone-player collapsed id="snare" label="Snare"></tone-player> <tone-membrane-synth collapsed id="kick" label="Kick"></tone-membrane-synth> <tone-fm-synth collapsed id="bass" label="Bass"></tone-fm-synth> <tone-duo-synth collapsed id="lead" label="Lead"></tone-duo-synth> </tone-drawer> </tone-example> <script type="text/javascript"> //a compressor var drumCompress = new Tone.Compressor({ "threshold" : -30, "ratio" : 6, "attack" : 0.3, "release" : 0.1 }).toMaster(); var distortion = new Tone.Distortion({ "distortion" : 0.4, "wet" : 0.4 }); //hats var hats = new Tone.Player({ "url" : "./audio/505/hh.[mp3|ogg]", "volume" : -10, "fadeOut" : 0.05 }).chain(distortion, drumCompress); var hatsLoop = new Tone.Loop({ "callback" : function(time){ hats.start(time).stop(time + 0.05); }, "interval" : "16n", "probability" : 0.8 }).start("1m"); //SNARE PART var snare = new Tone.Player({ "url" : "./audio/505/snare.[mp3|ogg]", "fadeOut" : 0.1 }).chain(distortion, drumCompress); var snarePart = new Tone.Sequence(function(time, velocity){ snare.volume.value = Tone.gainToDb(velocity); snare.start(time).stop(time + 0.1); }, [null, 1, null, [1, 0.3]]).start(0); var kick = new Tone.MembraneSynth({ "pitchDecay" : 0.01, "octaves" : 6, "oscillator" : { "type" : "square4" }, "envelope" : { "attack" : 0.001, "decay" : 0.2, "sustain" : 0 } }).connect(drumCompress); var kickPart = new Tone.Sequence(function(time, probability){ if (Math.random() < probability){ kick.triggerAttack("C1", time); } }, [1, [1, [null, 0.3]], 1, [1, [null, 0.5]], 1, 1, 1, [1, [null, 0.8]]], "2n").start(0); // BASS var bass = new Tone.FMSynth({ "harmonicity" : 1, "modulationIndex" : 3.5, "carrier" : { "oscillator" : { "type" : "custom", "partials" : [0, 1, 0, 2] }, "envelope" : { "attack" : 0.08, "decay" : 0.3, "sustain" : 0, }, }, "modulator" : { "oscillator" : { "type" : "square" }, "envelope" : { "attack" : 0.1, "decay" : 0.2, "sustain" : 0.3, "release" : 0.01 }, } }).toMaster(); var bassPart = new Tone.Part(function(time, event){ if (Math.random() < event.prob){ bass.triggerAttackRelease(event.note, event.dur, time); } }, [{ time : "0:0", note : "C2", dur : "4n.", prob : 1 }, { time : "0:2", note : "C2", dur : "8n", prob : 0.6 }, { time : "0:2.6666", note : "C2", dur : "8n", prob : 0.4 }, { time : "0:3.33333", note : "C2", dur : "8n", prob : 0.9 }, { time : "1:0", note : "C2", dur : "4n.", prob : 1 }, { time : "1:2", note : "C2", dur : "8n", prob : 0.6 }, { time : "1:2.6666", note : "C2", dur : "8n", prob : 0.4 }, { time : "1:3.33333", note : "E2", dur : "8n", prob : 0.9 }, { time : "2:0", note : "F2", dur : "4n.", prob : 1 }, { time : "2:2", note : "F2", dur : "8n", prob : 0.6 }, { time : "2:2.6666", note : "F2", dur : "8n", prob : 0.4 }, { time : "2:3.33333", note : "F2", dur : "8n", prob : 0.9 }, { time : "3:0", note : "F2", dur : "4n.", prob : 1 }, { time : "3:2", note : "F2", dur : "8n", prob : 0.6 }, { time : "3:2.6666", note : "F2", dur : "8n", prob : 0.4 }, { time : "3:3.33333", note : "B1", dur : "8n", prob : 0.9 }]).start(0); bassPart.loop = true; bassPart.loopEnd = "4m"; //SYNTH var synth = new Tone.DuoSynth({ "vibratoAmount" : 0.5, "vibratoRate" : 5, "portamento" : 0.1, "harmonicity" : 1.005, "volume" : 5, "voice0" : { "volume" : -2, "oscillator" : { "type" : "sawtooth" }, "filter" : { "Q" : 1, "type" : "lowpass", "rolloff" : -24 }, "envelope" : { "attack" : 0.01, "decay" : 0.25, "sustain" : 0.4, "release" : 1.2 }, "filterEnvelope" : { "attack" : 0.001, "decay" : 0.05, "sustain" : 0.3, "release" : 2, "baseFrequency" : 100, "octaves" : 4 } }, "voice1" : { "volume" : -10, "oscillator" : { "type" : "sawtooth" }, "filter" : { "Q" : 2, "type" : "bandpass", "rolloff" : -12 }, "envelope" : { "attack" : 0.25, "decay" : 4, "sustain" : 0.1, "release" : 0.8 }, "filterEnvelope" : { "attack" : 0.05, "decay" : 0.05, "sustain" : 0.7, "release" : 2, "baseFrequency" : 5000, "octaves" : -1.5 } } }).toMaster(); var synthNotes = ["C2", "E2", "G2", "A2", "C3", "D3", "E3", "G3", "A3", "B3", "C4", "D4", "E4", "G4", "A4", "B4", "C5"]; Tone.Transport.bpm.value = 125; //bind the interface document.querySelector("tone-play-toggle").bind(Tone.Transport); document.querySelector("tone-slider-2d").addEventListener("change", e => { //use the x and y values to set the note and vibrato const note = synthNotes[Math.round(e.detail.x * (synthNotes.length-1))]; synth.setNote(note); synth.vibratoAmount.value = e.detail.y * 3; }); document.querySelector("tone-slider-2d").addEventListener("mousedown", e => { const note = synthNotes[Math.round(e.detail.x * (synthNotes.length-1))]; synth.vibratoAmount.value = e.detail.y * 3; synth.triggerAttack(note); }); document.querySelector("tone-slider-2d").addEventListener("mouseup", e => { synth.triggerRelease(); }); //bind the drawer interfaces document.querySelector("#hats").bind(hats); document.querySelector("#snare").bind(snare); document.querySelector("#kick").bind(kick); document.querySelector("#bass").bind(bass); document.querySelector("#distortion").bind(distortion); document.querySelector("#compressor").bind(drumCompress); document.querySelector("#lead").bind(synth); </script> </body> </html>