const socket = io() import { pick } from "./modules/utils.js" import { NOTE, SPACE, RECORDING } from "./settings.js" import { amsynth } from "./modules/instruments/amsynth.js" import { duosynth } from "./modules/instruments/duosynth.js" import { monosynth } from "./modules/instruments/monosynth.js" import { membranesynth } from "./modules/instruments/membranesynth.js" import { plucksynth } from "./modules/instruments/plucksynth.js" import { reverb } from "./modules/effects/reverb.js" // Pick an instrument const instrument = pick([amsynth, duosynth, monosynth, membranesynth, plucksynth]) // A channel to chain instruments and effects const channel = new Tone.Channel() // This is a hack to have something running, which makes the reverb work const pingpong = new Tone.PingPongDelay({delayTime : 2, feedback : 0, wet : 0}) // A filter const filter = new Tone.Filter({type:"lowpass", frequency:800}) // Chain the channel and effects to the master out channel.connect(pingpong) pingpong.connect(reverb) reverb.connect(Tone.Master) // Chain instrument to the channel instrument.connect(channel) const voice = new Tone.Player("/static/recordings/tts.mp3").connect(channel) voice.playbackRate = 0.65 voice.loop = true voice.autostart = false const noise = new Tone.Noise("brown") let playloop = undefined let schedule = undefined const pathway = pick([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) const play = () => { // Determine which of our patterns to play switch(pathway) { case 0: const autoFilter = new Tone.AutoFilter("3m", "200", 3.6).start() const cChord = ['C4', 'E4', 'G4', 'B4'] const dChord = ['D4', 'F4', 'A4', 'C5'] const gChord = ['B3', 'D4', 'E4', 'A4'] const piano = new Tone.PolySynth(Tone.Synth, { oscillator: { partials: [3, 2, 1] }, volume: -9 }).connect(autoFilter) autoFilter.connect(channel) const pianoPart = new Tone.Part({ callback: (time, chord) => { piano.triggerAttackRelease(chord, '8n', time) }, events: [ ['0:0:2', cChord], ['0:1', cChord], ['0:1:3', dChord], ['0:2:2', cChord], ['0:3', cChord], ['0:3:2', gChord] ], loop: false, }) const interval = pick(["5m", "6m", "7m"]) schedule = Tone.Transport.scheduleRepeat((time) => { pianoPart.stop() pianoPart.start() }, interval, "0") break case 1: playloop = new Tone.Player("/static/recordings/" + RECORDING).connect(channel) playloop.loop = true playloop.autostart = true break case 2: playloop = new Tone.Player("/static/recordings/" + RECORDING).connect(channel) playloop.loop = true playloop.autostart = true break case 3: playloop = new Tone.Player("/static/recordings/" + RECORDING).connect(channel) playloop.loop = true playloop.autostart = true break case 4: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "16n") }, SPACE).start(0) break case 5: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "16n") }, SPACE).start(0) break case 6: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "16n") }, SPACE).start(0) break case 7: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "8n") }, SPACE).start(0) break case 8: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "8n") }, SPACE).start(0) break case 9: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "8n") }, SPACE).start(0) break case 10: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "6n") }, SPACE).start(0) break case 11: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "6n") }, SPACE).start(0) break case 12: playloop = new Tone.Loop((time) => { instrument.triggerAttackRelease(NOTE, "6n") }, SPACE).start(0) break default: // Defaulting } } (function() { socket.on('all_action', () => { voice.start() }) socket.on('all_noise', () => { voice.stop() channel.disconnect(pingpong) noise.connect(Tone.Master) noise.start() }) socket.on('all_stop', () => { channel.disconnect(pingpong) noise.stop() }) const flowers = ["🌼", "🌸", "💮", "🌺", "🪷", "🏵️"] const playbutton = document.getElementById('play') playbutton.addEventListener('click', () => { if (playbutton.className == 'paused') { playbutton.className = 'playing' playbutton.innerHTML = pick(flowers) Tone.context.resume().then(() => { Tone.start() Tone.Transport.start("+0.1") }).then( play() ) } }) })()