Accurate Timing

This commit is contained in:
Adrien MALINGREY 2024-08-27 03:09:36 +02:00
parent a5285a10e2
commit 012161c4d6

44
app.js
View File

@ -1,7 +1,7 @@
const MAX_LEVEL = 3 const MAX_LEVEL = 3
const DRAW_PERIOD = 0.04 // s const DRAW_PERIOD = 0.04 // s
const UPDATE_PERIOD = 0.01 // s const UPDATE_PERIOD = 0.01 // s
const FLOOR = 400 // px const FLOOR = 386 // px
const FIRST_NOTE = 48 // C2 const FIRST_NOTE = 48 // C2
const LAST_NOTE = 73 // C4 const LAST_NOTE = 73 // C4
const FREQUENCIES = [ const FREQUENCIES = [
@ -180,8 +180,8 @@ class Note extends Sprite {
return new Sprite(this.canvasCtx, "tiny-explosion.png", this.x, this.y, 16, 16, 7) return new Sprite(this.canvasCtx, "tiny-explosion.png", this.x, this.y, 16, 16, 7)
} }
playNoise() { playNoise(time) {
playNoise(0.3, 0.4, 1400) playNoise(0.4, 1400, 0.3, time)
} }
} }
@ -213,8 +213,8 @@ class Quarter extends Note {
return new Sprite(this.canvasCtx, "little-explosion.png", this.x, this.y, 33, 33, 5) return new Sprite(this.canvasCtx, "little-explosion.png", this.x, this.y, 33, 33, 5)
} }
playNoise() { playNoise(time) {
playNoise(0.5, 0.5, 1000) playNoise(0.5, 1000, 0.5, time)
} }
} }
@ -233,8 +233,8 @@ class Whole extends Note {
return new Sprite(canvasCtx, "big-explosion.png", this.x, this.y, 48, 48, 8) return new Sprite(canvasCtx, "big-explosion.png", this.x, this.y, 48, 48, 8)
} }
playNoise() { playNoise(time) {
playNoise(0.8, 0.7, 400) playNoise(0.7, 400, 0.8, time)
} }
} }
@ -420,7 +420,7 @@ async function nextLevel() {
midiSong = await Midi.fromUrl(`midi/${level}.mid`) midiSong = await Midi.fromUrl(`midi/${level}.mid`)
levelTitle.innerText = `Niveau ${level}` levelTitle.innerText = `Niveau ${level}`
songNameTitle.innerText = midiSong.name songNameTitle.innerText = midiSong.name
speed = UPDATE_PERIOD * FLOOR / midiSong.header.tempos[0].bpm speed = 4 * UPDATE_PERIOD * FLOOR / midiSong.header.tempos[0].bpm
noteSprites = [] noteSprites = []
midiSong.tracks.forEach(track => { midiSong.tracks.forEach(track => {
//console.log(track.name) //console.log(track.name)
@ -456,7 +456,7 @@ function update(time) {
let explosionSprite = noteSprite.explose() let explosionSprite = noteSprite.explose()
explosionSprites.push(explosionSprite) explosionSprites.push(explosionSprite)
explosionSprite.play().then(() => explosionSprites.remove(explosionSprite)) explosionSprite.play().then(() => explosionSprites.remove(explosionSprite))
noteSprite.playNoise() noteSprite.playNoise(time)
}) })
noteSprites = noteSprites.filter(note => note.y < FLOOR) noteSprites = noteSprites.filter(note => note.y < FLOOR)
@ -464,7 +464,7 @@ function update(time) {
let noteSprite = noteSprites.find(noteSprite => noteSprite.note == cannonSprite.note) let noteSprite = noteSprites.find(noteSprite => noteSprite.note == cannonSprite.note)
if (noteSprite) { if (noteSprite) {
if (!noteSprite.shot) { if (!noteSprite.shot) {
playNote(noteSprite.note, noteSprite.velocity, time + noteSprite.duration) playNote(noteSprite.note, noteSprite.velocity, noteSprite.duration, time)
cannonSprite.impactY = noteSprite.y cannonSprite.impactY = noteSprite.y
noteSprite.shot = true noteSprite.shot = true
window.setTimeout(() => { window.setTimeout(() => {
@ -480,7 +480,7 @@ function update(time) {
}) })
} }
function playNote(note, velocity=0.7, stopAt=0) { function playNote(note, velocity=0.7, duration=0, time=0) {
if(oscillators[note]) return if(oscillators[note]) return
var oscillator = audioCtx.createOscillator() var oscillator = audioCtx.createOscillator()
@ -489,33 +489,33 @@ function playNote(note, velocity=0.7, stopAt=0) {
oscillator.velocity = audioCtx.createGain() oscillator.velocity = audioCtx.createGain()
oscillator.velocity.gain.value = 0 oscillator.velocity.gain.value = 0
oscillator.velocity.gain.linearRampToValueAtTime(velocity, audioCtx.currentTime + 0.05) oscillator.velocity.gain.linearRampToValueAtTime(velocity, time + 0.05)
oscillator.connect(oscillator.velocity) oscillator.connect(oscillator.velocity)
oscillator.start() oscillator.start()
oscillator.velocity.connect(volume) oscillator.velocity.connect(volume)
depth.connect(oscillator.detune) depth.connect(oscillator.detune)
if (stopAt) { if (duration) {
oscillator.velocity.gain.setValueCurveAtTime([velocity, velocity/10, velocity/20, 0], stopAt, 0.5) oscillator.velocity.gain.setValueCurveAtTime([velocity, velocity/10, velocity/20, 0], time + duration, 0.5)
oscillator.stop(stopAt + 0.5) oscillator.stop(time + duration + 0.5)
} else { } else {
oscillators[note] = oscillator oscillators[note] = oscillator
} }
} }
function stopNote(note, delay=0) { function stopNote(note, time=0) {
if(!oscillators[note]) return if(!oscillators[note]) return
velocity = oscillators[note].velocity.gain.value velocity = oscillators[note].velocity.gain.value
oscillators[note].velocity.gain.setValueCurveAtTime([velocity, velocity/10, velocity/20, 0], audioCtx.currentTime + delay + 0.1, 0.5) oscillators[note].velocity.gain.setValueCurveAtTime([velocity, velocity/10, velocity/20, 0], time, 0.5)
oscillators[note].stop(audioCtx.currentTime + delay + 0.6) oscillators[note].stop(time + 0.5)
delete(oscillators[note]) delete(oscillators[note])
} }
function playNoise(noiseDuration, startGain=0.5, bandHz=1000) { function playNoise(startGain=0.5, bandHz=1000, duration, time) {
const bufferSize = audioCtx.sampleRate * noiseDuration const bufferSize = audioCtx.sampleRate * duration
const noiseBuffer = new AudioBuffer({ const noiseBuffer = new AudioBuffer({
length: bufferSize, length: bufferSize,
sampleRate: audioCtx.sampleRate, sampleRate: audioCtx.sampleRate,
@ -532,10 +532,10 @@ function playNoise(noiseDuration, startGain=0.5, bandHz=1000) {
frequency: bandHz, frequency: bandHz,
}) })
const gain = new GainNode(audioCtx) const gain = new GainNode(audioCtx)
gain.gain.setValueCurveAtTime([startGain, startGain/5, 0], audioCtx.currentTime, noiseDuration) gain.gain.setValueCurveAtTime([startGain, startGain/5, 0], time, duration)
noise.connect(bandpass).connect(gain).connect(audioCtx.destination) noise.connect(bandpass).connect(gain).connect(audioCtx.destination)
noise.start() noise.start()
noise.stop(audioCtx.currentTime + noiseDuration) noise.stop(time + duration)
} }
document.onkeydown = function(event) { document.onkeydown = function(event) {