Stories of Web Audio by the Campfire



Stories of Web Audio by the Campfire

0 0


Webaudio-slides


On Github Oobert / Webaudio-slides

Stories of Web Audio by the Campfire

Created by Tony Gemoll

Turn power settings to performance.

Bio

Tony Gemoll - tony.gemoll@gmail.com Lead Application Developer at More Than Rewards Blog: http://geekwithopinions.com Twitter: @Oobert Organize Milwaukee JavaScript Meetup Slack: http://mke-slack.herokuapp.com/

Full disclosure, I am not an audiophile. So why the talk? -Started using Audio API and thought it was cool

The "Old" days of audio


					
					
										
						Background music
						Highly annoying! 
						Support was not consistent
					

Things got better

Flash came and things got better -got things like youtube, spotify, games Downsides is that it is flash, requires browsers plugins, and need to know another language

Then Came

New audio support in JavaScript! No plug-ins 2 new APIs: Web Audio API and Audio elements

Audio Element Support

New html element. Supported most everywhere Simply a audio player -suppoerts play, pause, seek, volume, loop, autoplay, and controls. Does give cross browser support for audio playing in the browser

Simple Audio Element

<audio src="loudpipes.mp3" controls>
	<source src="loudpipes.mp3" type="audio/mpeg" />
	<source src="loudpipes.ogg" type="audio/ogg"/>

	Your browser does not support the
	<code>audio</code> element.
</audio>
Demo

Audio Element via JS

var audio = new Audio('loudpipes.mp3');

function play(){
	audio.play();
}

function stop(){
	audio.pause();
}
					
Demo

Audio Codec Support

Use mp3 with a fall back for Linux IE is working WAV support.

Check Support in JS

var audio = new Audio();
var canPlay = audio.canPlayType("audio/mp3")
//"" - browser does not support this type.
//maybe - browser may support this type.
//probably - browser most likely supports this type
					
Best API in the world!

Web Audio API Support

New JS APIs Support is decent Cross browser support manipulating audio IE... sigh... Work has not started, only "Under Consideration"

How it works

Modular Graph Legos Different Threads Demo later

Sources

  • OscillatorNode
  • AudioBufferSourceNode
  • MediaElementAudioSourceNode
  • MediaStreamAudioSourceNode
OscillatorNode: Generate sounds based on a wave form AudioBufferSourceNode: Load audio from buffer MediaElementAudioSourceNode: Load audio from an audio element MediaStreamAudioSourceNode: Load audio from microphone Midi

Destinations

  • AudioDestinationNode
  • MediaStreamAudioDestinationNode
  • Recorder.js
AudioDestinationNode: Speakers MediaStreamAudioDestinationNode: WebRTC Recorder.js: save to a file

Filters/Effects

  • AnalyserNode
  • DelayNode
  • GainNode
  • ScriptProcessorNode
  • Plus others
AnalyserNode: analyse audio DelayNode: will delay audio playback for a site time GainNode: adjust the volume of the audio ScriptProcessorNode: allows for JS processing of the audio

Demo

Audio PlaygroundList of nodesExample of a node Audio Playground: show the lego like nature List of nodes: Show all the supported node types Example of a node: show example of a node

Load file via APIs

var source = audioContext.createBufferSource();
var audioContext = new (window.AudioContext || window.webkitAudioContext)();

function getData() {
	var request = new XMLHttpRequest();

	request.open('GET', 'loudpipes.mp3', true);
	request.responseType = 'arraybuffer';
	request.onload = function() {
		var audioData = request.response;

		audioContext.decodeAudioData(audioData, function(buffer) {
		    var myBuffer = buffer;
		    source.buffer = myBuffer;
		    source.connect(audioContext.destination);
		    source.loop = true;
	    }
    }

	request.send();
}


function play(){
	source.start(0);
}

function stop(){
	source.stop(0);
}

getData();
					
Demo AudioBufferSourceNode

Using audio nodes

HTML


					
JS
var audio = new Audio('loudpipes.mp3');
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
var sourceNode = audioContext.createMediaElementSource(audio)

var gainNode = audioContext.createGain();
gainNode.gain.value = .5;

sourceNode.connect( gainNode );
gainNode.connect( audioContext.destination );

audio.play();

volume.oninput = function(a){
	gainNode.gain.value = volume.value;
}
					
Demo MediaElementAudioSourceNode

JS Processing example

var audio = new Audio('test.mp3');
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
var sourceNode = audioContext.createMediaElementSource(audio)
var processor = audioContext.createScriptProcessor(2048, 1, 1);

sourceNode.connect(processor);
sourceNode.connect( audioContext.destination );
processor.connect(audioContext.destination)

var shot = false;
var shotCount = 0;
var shots = [];

processor.onaudioprocess = function(e){

    var input = e.inputBuffer.getChannelData(0);
    var total = 0;

    for (var index = 0; index < input.length; index++){
        total += Math.abs(input[index]);
    }

    var rms = Math.sqrt(total/input.length);
    var decibel = 20 * (Math.log(rms) / Math.log(10));

    if (decibel > -7 && !shot) {
        console.log('shot', shotCount);
        shotCount++;
        shot = true;
        shots.push(performance.now());
    }
    else if (decibel < -8 ){
        shot = false;
    }
};

audio.play();
					
Demo

Threading

audioContext.decodeAudioData(audioData, function(buffer) {
	var myBuffer = buffer;

	var frameCount = audioContext.sampleRate * (14/20);
	var numberOfChannels = myBuffer.numberOfChannels;
	var paddingBuffer = audioContext.createBuffer(1, frameCount, audioContext.sampleRate);
	for (var i=0; i < numberOfChannels; i++) {
		var clickData = paddingBuffer.getChannelData(i);
		clickData.set(myBuffer.getChannelData(i));
	};


	source.connect(audioContext.destination);
	source.buffer = paddingBuffer;
	source.loop = true;
}
Demo

Performance?

Touch!Plink! - http://goo.gl/tofSAF Plink? Join me! Multiple Audio samples need to be loaded if you want to play the same thing at the same time.

Uses?

Can still be annoying Think native

Record Audio

Demo
/*Get user media (mic access)*/
if (!navigator.getUserMedia)
    navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
if (!navigator.cancelAnimationFrame)
    navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
if (!navigator.requestAnimationFrame)
    navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

navigator.getUserMedia({audio:true}, gotStream, function(e) {
    alert('Error getting audio');
    console.log(e);
});

function gotStream(stream){
	var source = audioContext.createMediaStreamSource(stream);
	...
}
					
					
SourceRecorder.js

Visualisations

Visualisation!

Games!

Games! No Really Games! Trigger rally - audio uses web audio. Engine news made by changing frequencies of sound. Dungeon Defenders - ASM.js + web audio.

Notifications

Think native. Real time web. Examples: Messages, updates, feedback of errors or success, status that process is done Vibration api.

What about DRM?

Encrypted Media Extensions Support:
  • IE11 in Win8.1
  • Chrome (Desktop and mobile)
  • Safari 8 in OSX Yosemite

END

Tony Gemoll - tony.gemoll@gmail.com Blog: http://geekwithopinions.com Twitter: @Oobert Slack: http://mke-slack.herokuapp.com/

MORE INFO

https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_APIhttp://webaudiodemos.appspot.com/Demo source