The Next Generation

Electronic

Music

Why don't you recreate it?

Web ftw!

JSConf EU 2014

+

Server

+

+

LEDs

Node.js

Tessel 1

Adafruit NeoPixel

WebSocket

USB

Web Audio API

Wires

JSConf EU 2014: DEMO

Start again

The Next Generation

Notebook

Web Audio API

  • Play a song

  • Manipulate 

  • Analyse

MDN

// Create new AudioContext
var audio_context = new AudioContext();
// Create AnalyserNode
var audio_analyser = audio_context.createAnalyser();
// Set "Fast Fourier transform"-size 
audio_analyser.fftSize = 512;
// Save frequency data from the audio_analyser
var audio_frequencyData = 
    new Uint8Array(audio_analyser.frequencyBinCount);

Web Audio API

<audio id="player" controls preload src="song.mp3"></audio>

Web Audio API

// Get HTML audio element
var audio_element = document.getElementById('player');
// Set the audio_element as audio input
var audio_source = 
    audio_context.createMediaElementSource(audio_element);
// Connect the audio_source with the audio_analyser
audio_source.connect(audio_analyser);
// Connect the audio_analyser to the output (speaker etc.)
audio_analyser.connect(audio_context.destination);
// Get byte frequency data from the audio_analyser
audio_analyser.getByteFrequencyData(audio_frequencyData);

sub lows

lows

low mids

mids

high mids

highs

super highs

var NERDDISCO_audio = new ndAudio({



});
// Update & transform frequency data
NERDDISCO_audio.updateData();
// Get frequency data
NERDDISCO_audio.frequencyData;
// Get grouped frequency data
NERDDISCO_audio.groupedFrequencyData;

ndAudio

  audio_element : document.querySelector('.player'),
  fftSize : 512

ndAudio

DEMO

Notebook

MDN

Canvas API

  • Draw

  • Animate

  • Video processing

Canvas API

<canvas id="NERDDISCO" width="500" height="500"></canvas>
// Get the HTML canvas element
var canvas = document.getElementById('NERDDISCO');
// Get the canvas context
var ctx = canvas.getContext('2d');
// Set fill color
ctx.fillStyle = "rgb(200, 0, 0)";
// Draw a rectangle on the canvas
ctx.fillRect(10, 10, 55, 50);

Canvas API

function update() {












}
// Start animation loop
update();
  // Clear whole canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // Draw a rectangle
  // ...
  // Run at ~ 30 fps
  setTimeout(function() {



  }, 1000 / 30);
    // Call update (recursion)
    window.requestAnimationFrame(update);

ndVisualization

var NERDDISCO_visualization = new ndVisualization({


});
// Add visualization element to queue
NERDDISCO_visualization.addElement(









);
  ndAudio : NERDDISCO_audio
  new ndCircle({
    x : 0,             // x position
    y : 0,             // y position
    r : 120,           // radius



  })
    range : 'lowmid',  // frequency range
    trigger: 254       // min. frequency 

ndVisualization

function update() {








}
  // Update the audio data
  NERDDISCO_audio.updateData();
  // Draw every visualization element on canvas
  NERDDISCO_visualization.draw();
  // setTimeout + requestAnimationFrame
  // ...

ndVisualization

ndAudio

DEMO

Notebook

LEDs

  • Adafruit 

  • NeoPixel

  • NeoMatrix

nube 1

Adafruit NeoMatrix

var myLEDs = [ 

  



];
  255, 0,   0, // red
  0,   255, 0  // green

#1

#2

#3

  255, 255, 0  // yellow

Adafruit Fadecandy

Notebook

USB

Fadecandy Server

Node.js

Fadecandy Client

Socket

ndSelector

  • Select area on canvas

  • 1 ndSelector =
    1 NeoMatrix

Pixel to LED mapping

Pixel to LED mapping

Canvas API

// Get the pixel data for one NeoPixel
var pixel_data = ctx.getImageData(x, y, width, height)
[ 255, 0, 128, 1,
  55, 22, 73,  1,
  20, 34, 0,   1 ]
// Create array for the result
var result = [];
// Sum red / green / blue for every pixel
for (var i = 0; i < pixel_data.length; i++) {
  result[0] += pixel_data[i];     // red
  result[1] += pixel_data[i + 1]; // green
  result[2] += pixel_data[i + 2]; // blue

  i += 2; // Jump to next pixel
}

Canvas API

// Amount of pixel for one NeoPixel
var pixel_amount = (pixel_data.length + 1) / 4;
// Calculate average color for one NeoPixel
result[0] = Math.floor(result[0] / pixel_amount);
result[1] = Math.floor(result[1] / pixel_amount);
result[2] = Math.floor(result[2] / pixel_amount);

ndVisualization

// Transform pixel data to LED colors
NERDDISCO_visualization.getLEDs()

Notebook

USB

Fadecandy Server

Node.js

Fadecandy Client

Socket

WebSocket

ndVisualization

function update() {













}
  // Update the audio data
  NERDDISCO_audio.updateData();
  // Draw every visualization element on canvas
  NERDDISCO_visualization.draw();
  // setTimeout + requestAnimationFrame
  // ...
  // Calculate & send pixel data to the node.js server
  NERDDISCO_connector.sendLEDs(
    NERDDISCO_visualization.getLEDs()
  );

ndVisualization

ndAudio

DEMO

nube 1

Notebook

USB

Fadecandy Server

Node.js

Fadecandy Client

Socket

WebSocket

Web MIDI API

  • Control MIDI devices

  • No plugin required

W3C

Web MIDI API

// Get permission from user
navigator.permissions.query({ name: 'midi', sysex: true });
// Permission granted: Request access to the MIDI devices
navigator.requestMIDIAccess({ sysex: true }).then(










);
  // Got access
  function(access) {



  }, 
  // Handle failure
  function(failure) {}
    // Iterate over all access.inputs.values()
    // Listen to onmidimessage event

ndMidi

// Create instance of ndMidi
var NERDDISCO_midi = new ndMidi();
// Get permission for Web MIDI API & 
// connect to the attached MIDI devices
NERDDISCO_midi.connect();

KORG nanoPAD2

The Next Generation

Thank you!

NERD DISCO: The Next Generation - JSConfChina 2015

By Tim Pietrusky

NERD DISCO: The Next Generation - JSConfChina 2015

Music visualization in the browser (HTML canvas, Web Audio API, socket.io) and on LEDs (Adafruit NeoPixel, Adafruit Fadecandy).

  • 3,126