•
•
•
Visualized: webaudioplayground.appspot.com
•
•
var request = new XMLHttpRequest();
request.open('GET', myURL, true);
request.responseType = 'arraybuffer‘;
request.onload = requestLoad;
request.send();
function requestLoad() {
// yay, finally done loading
_audioContext.decodeAudioData(request.response, doneDecoding);
}
function doneDecoding(buffer) {
// yay, finally done decoding
playBuffer(buffer);
}
function playBuffer(buffer) {
var bufferSourceNode = _audioContext.createBufferSource();
bufferSourceNode.buffer = buffer;
buffer.connect(_audioContext.destination); // connect to output
buffer.start(0); //play
}
// create an HTML Audio Element, or use an existing one
var audio = new Audio(myURL);
// Audio Element will let us know when it's buffered enough
audio.addEventListener('canplaythrough', function(e) {
var mediaSourceNode = _audioContext.createMediaElementSource(audio);
mediaSourceNode.connect(_audioContext.destination); // connect to output
audio.play(); // play
});
•
•
–
•
–
–
<body ng-app="Page" ng-controller="PageController">
<div class="songs">
<span ng-repeat="song in songs">
<input type="radio" ng-model="$parent.currentSong" ng-value="song" />
<label>{{song.name+' ('+song.band+')'}}</label>
</span>
</div>
<div class="controls" ng-show="currentSong“>
<h2>{{currentSong.name}}</h2>
<button ng-show="!playing" ng-click="playTracks()">Play</button>
<button ng-show="playing" ng-click="stopTracks()">Stop</button>
</div>
<div class="track-container">
<div ng-controller="TrackController" class="track" ng-class="{loading:loading==true}"
ng-repeat="(key, track) in currentSong.tracks">
<input type="range" ng-model="trackVolume" />
<canvas></canvas>
<span class="spinner" ng-show="loading"></span>
</div>
</div>
</body>
<body ng-app="Page" ng-controller="PageController">
<div class="songs">
<span ng-repeat="song in songs">
<input type="radio" ng-model="$parent.currentSong" ng-value="song" />
<label>{{song.name+' ('+song.band+')'}}</label>
</span>
</div>
<div class="controls" ng-show="currentSong“>
<h2>{{currentSong.name}}</h2>
<button ng-show="!playing" ng-click="playTracks()">Play</button>
<button ng-show="playing" ng-click="stopTracks()">Stop</button>
</div>
<div class="track-container">
<div ng-controller="TrackController" class="track" ng-class="{loading:loading==true}"
ng-repeat="(key, track) in currentSong.tracks">
<input type="range" ng-model="trackVolume" />
<canvas></canvas>
<span class="spinner" ng-show="loading"></span>
</div>
</div>
</body>
_page.controller('PageController', function($scope) {
...
$scope.playTracks = function(tracks) {
angular.forEach(tracks, function(track, key) {
track.play();
});
$scope.playing = true;
};
function tick() {
angular.forEach($scope.currentSong.tracks, function(track, key) {
if (track.analyser) {
_drawStuff(track.cCtx, track.analyser);
}
});
window.requestAnimationFrame(tick);
}
...
});
_page.controller('TrackController', function($scope, $element) {
$scope.trackVolume = 100;
$scope.canvas = $element[0].getElementsByTagName('canvas')[0];
$scope.track.play = function() {
$scope.track.audio.play();
};
$scope.track.stop = function() {
$scope.track.audio.pause();
};
$scope.$watch('trackVolume', function(value) {
value = value / 100;
if ($scope.track.gainNode) {
$scope.track.gainNode.gain.value = value;
}
});
});
var analyser = _aCtx.createAnalyser();
analyser.smoothingTimeConstant = 0.6;
analyser.fftSize = 256;
// Each frame:
var byteFreqArr = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(byteFreqArr);
var timeDomainArr = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteTimeDomainData(timeDomainArr);
canvasContext.clearRect(0, 0, _cWidth, _cHeight);
canvasContext.beginPath();
for (var i=0,iLen=byteFreqArr.length; i<iLen; i++) {
canvasContext.fillRect(i*_freqDrawWidth, _cHeight - (byteFreqArr[i] / 256 *
_cHeight), (_freqDrawWidth - 2), _cHeight);
var percent = timeDomainArr[i] / 256;
var offset = _cHeight - (percent * _cHeight) - 1;
canvasContext.lineTo(i*_timeDrawWidth, offset);
}
canvasContext.stroke();
Web Audio API + AngularJS

Web Audio API + AngularJS

  • 2.
  • 4.
  • 5.
    var request =new XMLHttpRequest(); request.open('GET', myURL, true); request.responseType = 'arraybuffer‘; request.onload = requestLoad; request.send(); function requestLoad() { // yay, finally done loading _audioContext.decodeAudioData(request.response, doneDecoding); } function doneDecoding(buffer) { // yay, finally done decoding playBuffer(buffer); } function playBuffer(buffer) { var bufferSourceNode = _audioContext.createBufferSource(); bufferSourceNode.buffer = buffer; buffer.connect(_audioContext.destination); // connect to output buffer.start(0); //play }
  • 6.
    // create anHTML Audio Element, or use an existing one var audio = new Audio(myURL); // Audio Element will let us know when it's buffered enough audio.addEventListener('canplaythrough', function(e) { var mediaSourceNode = _audioContext.createMediaElementSource(audio); mediaSourceNode.connect(_audioContext.destination); // connect to output audio.play(); // play });
  • 7.
  • 8.
    <body ng-app="Page" ng-controller="PageController"> <divclass="songs"> <span ng-repeat="song in songs"> <input type="radio" ng-model="$parent.currentSong" ng-value="song" /> <label>{{song.name+' ('+song.band+')'}}</label> </span> </div> <div class="controls" ng-show="currentSong“> <h2>{{currentSong.name}}</h2> <button ng-show="!playing" ng-click="playTracks()">Play</button> <button ng-show="playing" ng-click="stopTracks()">Stop</button> </div> <div class="track-container"> <div ng-controller="TrackController" class="track" ng-class="{loading:loading==true}" ng-repeat="(key, track) in currentSong.tracks"> <input type="range" ng-model="trackVolume" /> <canvas></canvas> <span class="spinner" ng-show="loading"></span> </div> </div> </body>
  • 9.
    <body ng-app="Page" ng-controller="PageController"> <divclass="songs"> <span ng-repeat="song in songs"> <input type="radio" ng-model="$parent.currentSong" ng-value="song" /> <label>{{song.name+' ('+song.band+')'}}</label> </span> </div> <div class="controls" ng-show="currentSong“> <h2>{{currentSong.name}}</h2> <button ng-show="!playing" ng-click="playTracks()">Play</button> <button ng-show="playing" ng-click="stopTracks()">Stop</button> </div> <div class="track-container"> <div ng-controller="TrackController" class="track" ng-class="{loading:loading==true}" ng-repeat="(key, track) in currentSong.tracks"> <input type="range" ng-model="trackVolume" /> <canvas></canvas> <span class="spinner" ng-show="loading"></span> </div> </div> </body>
  • 10.
    _page.controller('PageController', function($scope) { ... $scope.playTracks= function(tracks) { angular.forEach(tracks, function(track, key) { track.play(); }); $scope.playing = true; }; function tick() { angular.forEach($scope.currentSong.tracks, function(track, key) { if (track.analyser) { _drawStuff(track.cCtx, track.analyser); } }); window.requestAnimationFrame(tick); } ... });
  • 11.
    _page.controller('TrackController', function($scope, $element){ $scope.trackVolume = 100; $scope.canvas = $element[0].getElementsByTagName('canvas')[0]; $scope.track.play = function() { $scope.track.audio.play(); }; $scope.track.stop = function() { $scope.track.audio.pause(); }; $scope.$watch('trackVolume', function(value) { value = value / 100; if ($scope.track.gainNode) { $scope.track.gainNode.gain.value = value; } }); });
  • 12.
    var analyser =_aCtx.createAnalyser(); analyser.smoothingTimeConstant = 0.6; analyser.fftSize = 256; // Each frame: var byteFreqArr = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(byteFreqArr); var timeDomainArr = new Uint8Array(analyser.frequencyBinCount); analyser.getByteTimeDomainData(timeDomainArr); canvasContext.clearRect(0, 0, _cWidth, _cHeight); canvasContext.beginPath(); for (var i=0,iLen=byteFreqArr.length; i<iLen; i++) { canvasContext.fillRect(i*_freqDrawWidth, _cHeight - (byteFreqArr[i] / 256 * _cHeight), (_freqDrawWidth - 2), _cHeight); var percent = timeDomainArr[i] / 256; var offset = _cHeight - (percent * _cHeight) - 1; canvasContext.lineTo(i*_timeDrawWidth, offset); } canvasContext.stroke();