disco.js

meet.js / Wrocław
DZIEŃ DOBRY
(wieczór)
DZIEŃ DOBRY
(wieczór)
MÓWIĄ NA MNIE KORSAN
KORSAN






















3.4%
54.4%


32.4%

4.8%

1.8%

2009

<audio src="sound.wav"></audio>
Audio Element
const audio = document.querySelector('.my-audio');
audio.play();
audio.pause();
audio.currentTime = 0;
...
Audio Element / JavaScript
WEB AUDIO API


WEB AUDIO API /
AUDIO CONTEXT
Audio Inputs
Audio Effects
Audio Destinations
Audio Context
WEB AUDIO API /
AUDIO INPUTS
- Oscillator
- DOM (<audio>, <video>)
- Stream (mikrofon, kamera)
- Buffer (pliki, dane)
WEB AUDIO API /
AUDIO EFFECTS
- Gain
- StereoPanner
- DynamicsCompressor
- i inne...
WEB AUDIO API /
AUDIO INPUTS // OSCILLATOR
const ac = new AudioContext(),
destination = ac.destination,
oscillator = ac.createOscillator(),
gainNode = ac.createGain();
gainNode.gain.setValueAtTime(0.2, ac.currentTime);
gainNode.connect(destination);
oscillator.type = 'square';
oscillator.frequency.value = 220;
oscillator.connect(gainNode);
oscillator.start();
WEB AUDIO API /
AUDIO INPUTS // OSCILLATOR
const ac = new AudioContext(),
destination = ac.destination,
oscillator = ac.createOscillator(),
gainNode = ac.createGain();
gainNode.gain.setValueAtTime(0.2, ac.currentTime);
gainNode.connect(destination);
oscillator.type = 'square';
oscillator.frequency.setValueAtTime(220, ac.currentTime);
oscillator.connect(gainNode);
oscillator.start();
audioNodeSource.connect(audioNodeDestination)
WEB AUDIO API /
AUDIO INPUTS // OSCILLATOR
const ac = new AudioContext(),
destination = ac.destination,
oscillator = ac.createOscillator(),
gainNode = ac.createGain();
gainNode.gain.setValueAtTime(0.2, ac.currentTime);
gainNode.connect(destination);
oscillator.type = 'square';
oscillator.frequency.setValueAtTime(220, ac.currentTime);
oscillator.connect(gainNode);
oscillator.start();
Oscillator
Gain
Destination

A tale of two clocks
setTimeout()
audioContext.currentTime

Philip Roberts: What the heck is the event loop anyway?
audioContext.currentTime
requestAnimationFrame()
WEB AUDIO API /
AUDIO CONTEXT CURRENT TIME
const NOTES = {
'A5': 440,
'A#5': 466.16,
'B5': 493.88,
'C5': 523.25,
'C#5': 554.37,
'D5': 587.33,
'D#5': 622.25,
'E5': 659.25,
'F5': 698.46,
'F#5': 739.99,
'G5': 783.99,
'G#5': 830.61,
'A6': 880.00,
'A#6': 932.33,
'B6': 987.77,
'C6': 1046.50,
'C#6': 1108.73,
'D6': 1174.66,
'D#6': 1244.51,
'E6': 1318.51
}
WEB AUDIO API /
AUDIO CONTEXT CURRENT TIME
const melody = [
{
note: 'C5',
startTime: 0,
duration: 1,
played: false,
},
{
note: 'D5',
startTime: 1,
duration: 1,
played: false,
},
{
note: 'E5',
startTime: 2,
duration: 1,
played: false,
},
.
.
.
]
WEB AUDIO API /
AUDIO CONTEXT CURRENT TIME
const tempo = 120,
beatDuration = tempo / 60;
startTime = ac.currentTime;
const playLoop = () => {
let currentTime = (ac.currentTime - startTime) * beatDuration;
for (let i = 0, len = melody.length; i < len; i++) {
let note = melody[i];
if (!note.played && currentTime > note.startTime) {
note.played = true;
let osc = ac.createOscillator();
osc.frequency.setValueAtTime(NOTES[note.note], ac.currentTime);
osc.type = 'square';
osc.connect(gain);
osc.start();
osc.stop(ac.currentTime + note.duration / beatDuration);
}
}
reqFrame = requestAnimationFrame(playLoop);
}
Analyser
WEB AUDIO API /
Analyser
Source
Gain
Destination
Destination
Analyser
MASZ:
<i></i> * 32
CO ROBISZ?
?
WEB AUDIO API
const ac = new AudioContext(),
destination = ac.destination,
analyser = ac.createAnalyser(),
frequencyData = new Uint8Array(512);
analyser.fftSize = 1024;
navigator.mediaDevices.getUserMedia({ audio: true })
.then(function(stream) {
let microphone = ac.createMediaStreamSource(stream),
micGain = ac.createGain();
micGain.gain.setValueAtTime(1, ac.currentTime);
microphone.connect(micGain);
micGain.connect(analyser);
});
WEB AUDIO API /
Analyser
function animate() {
analyser.getByteFrequencyData(frequencyData);
for (let i = 0; i < allEls.length; i++) {
allEls[i].style.backgroundColor = `hsla(${i*10}, 80%, 50%, 0.8)`;
allEls[i].style.height = `${Math.pow(frequencyData[i]/4,2)/40}%`;
header.style.transform = `scale(${frequencyData[6]/255/4+0.75})`;
}
requestAnimationFrame(animate);
}
animate();
WEB AUDIO API /
Analyser
frequencyData = [ 255, 192, 11, 0, 0, 0, 33, 52, ..., 99]
freq 0Hz » 20kHz
WEB MIDI API /
Inicjalizacja
navigator.requestMIDIAccess({
sysex: false
}).then(onMIDISuccess, onMIDIFailure);
function onMIDISuccess(midiAccess) {
midi = midiAccess;
var inputs = midi.inputs.values();
for (var input = inputs.next(); input && !input.done; input = inputs.next()) {
input.value.onmidimessage = onMIDIMessage;
}
}
function onMIDIMessage(message) {
data = message.data;
if (data[0] == 153 || data[0] == 176)
switch (data[1]) {
case 40:
samplesElements[0].currentTime = 0;
samplesElements[0].play();
.
.
.
WEB MIDI API /
MIDI data
[153, 39, 77]
TYP ZDARZENIA
WARTOŚĆ
ID ŹRÓDŁA
WEB MIDI API /
CO TU SIĘ...
for (let i=0; i<17; i++) {
let audio = document.createElement('audio');
audio.src = `/assets/daftpunk/${i+1}.wav`;
audio.classList.add(`sample-${i+1}`);
samplesElements.push(audio);
samples[i] = ac.createMediaElementSource(audio);
samples[i].connect(gain);
}
.
.
.
function onMIDIMessage(message) {
data = message.data;
if (data[0] == 153 || data[0] == 176)
switch (data[1]) {
case 48:
samplesElements[0].currentTime = 0;
samplesElements[0].play();
break;
case 41:
.
.
.

DŻEJES

Q&A
@maciejkorsan
Disco.js - slajdy 2018
By Maciej Korsan
Disco.js - slajdy 2018
- 816