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

  • 745