201 lines
5 KiB
JavaScript
201 lines
5 KiB
JavaScript
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()
|
|
)
|
|
}
|
|
})
|
|
})()
|