import keys from './lib/keys'
import color from './lib/color'
import kalimba from './lib/kalimba'
import life from './lib/life'
import organ from './lib/organ'
import { browser, requestAudioContext } from './lib/util'
let instrument = kalimba
let hash = window.location.hash || window.location.search
if (hash.match('sin') || hash.match('organ')) {
instrument = organ
}
const root = 440
const s = 50
const w = window.innerWidth
const h = window.innerHeight
const ws = w/s, hs = h/s
const add_on = 0
const mul_on = 1.0
const add_off = 0.1
const mul_off = 0.9
let dragging = false
let erasing = false
let lastFreq = 0
let notes = []
requestAudioContext( () => {
for (var i = 0; i < ws; i++) {
notes[i] = []
for (var j = 0; j < hs; j++) {
notes[i][j] = add(i, j)
}
}
life.init(notes, assign)
})
function play(freq) {
freq.playing = true
instrument.play(freq.frequency)
freq.div.classList.add('playing')
life.assign_item(freq, true)
}
function pause(freq) {
freq.playing = false
instrument.pause(freq.frequency)
freq.div.classList.remove('playing')
life.assign_item(freq, false)
}
function assign(freq, state) {
if (state) {
play(freq)
} else {
pause(freq)
}
}
function toggle(freq) {
assign(freq, freq.playing = !freq.playing)
}
function add (i, j) {
const a = i + 1
const b = j + 1
const div = document.createElement('div')
const frequency = root * a/b
let add = 0
let frac = Math.log2(a/b) % 1
div.style.left = (i * s) + 'px'
div.style.top = (j * s) + 'px'
div.innerHTML = `
${a}<\/div>
\/
${b}<\/div>`
const freq = { frequency, div, i, j, playing: false }
if (frac < 0) {
frac += 1
}
if (a < b) {
add = -Math.log(b/a) / 3.5
}
else {
add = Math.log(a/b) / 6
}
if ( frac === 0) {
div.style.fontWeight = '900'
div.style.left = (i * s) + 'px'
div.style.top = (j * s) + 'px'
}
div.style.backgroundColor = color(frac, add_off + add, mul_off)
if (browser.isDesktop) {
div.addEventListener('mousedown', function(){
div.style.backgroundColor = color(frac, add + add_on, mul_on)
toggle( freq )
erasing = !freq.playing
})
div.addEventListener('mouseenter', function(){
div.style.backgroundColor = color(frac, add + add_on, mul_on)
if (dragging) {
if (erasing) {
pause( freq )
} else {
toggle( freq )
}
}
})
div.addEventListener('mouseleave', function(){
div.style.backgroundColor = color(frac, add + add_off, mul_off)
})
}
else {
div.addEventListener('touchstart', function(e){
e.preventDefault()
toggle( freq )
erasing = !freq.playing
lastFreq = freq
})
}
document.body.appendChild(div)
return freq
}
if (browser.isDesktop) {
document.addEventListener('mousedown', () => { dragging = true })
document.addEventListener('mouseup', () => { dragging = false })
}
else {
document.addEventListener('touchstart', (e) => { e.preventDefault(); dragging = true })
document.addEventListener('touchmove', (e) => {
e.preventDefault()
const x = Math.floor( e.touches[0].pageX / s )
const y = Math.floor( e.touches[0].pageY / s )
if (! (x in notes) || ! (y in notes[x])) return
const freq = notes[x][y]
if (freq !== lastFreq) {
if (dragging) {
if (erasing) {
pause( freq )
} else {
toggle( freq )
}
}
lastFreq = freq
}
})
document.addEventListener('touchend', () => { dragging = false })
}
function swap_instrument(){
instrument = (instrument === kalimba) ? organ : kalimba
}
let life_bpm = 50
window.addEventListener("keydown", keydown, true)
function keydown(e){
// console.log(e.keyCode)
switch (e.keyCode){
case 32: // space
life.toggle()
break
case 38: // up
life_bpm += e.shiftKey ? 1 : 5
life_bpm = Math.max(1, life_bpm)
life.setTempo(life_bpm)
break
case 40: // down
life_bpm -= e.shiftKey ? 1 : 5
life.setTempo(life_bpm)
break
case 83: // s
swap_instrument()
break
}
}
keys.listen(function(index){
// const freq = scales.current().index(index)
// document.body.style.backgroundColor = color( index / scales.current().scale.length )
// instrument.toggle(freq)
})