web-audio-api
Version:
Node.js implementation of Web audio API
178 lines (148 loc) • 6.32 kB
JavaScript
var PRS$0 = (function(o,t){o["__proto__"]={"a":t};return o["a"]===t})({},{});var DP$0 = Object.defineProperty;var GOPD$0 = Object.getOwnPropertyDescriptor;var MIXIN$0 = function(t,s){for(var p in s){if(s.hasOwnProperty(p)){DP$0(t,p,GOPD$0(s,p));}}return t};var SP$0 = Object.setPrototypeOf||function(o,p){if(PRS$0){o["__proto__"]=p;}else {DP$0(o,"__proto__",{"value":p,"configurable":true,"enumerable":false,"writable":true});}return o};var OC$0 = Object.create;var _ = require('underscore')
, events = require('events')
, async = require('async')
, pcmUtils = require('pcm-boilerplate')
, utils = require('./utils')
, constants = require('./constants')
, BLOCK_SIZE = constants.BLOCK_SIZE
, AudioBuffer = require('./AudioBuffer')
, AudioDestinationNode = require('./AudioDestinationNode')
, AudioBufferSourceNode = require('./AudioBufferSourceNode')
, GainNode = require('./GainNode')
, ScriptProcessorNode = require('./ScriptProcessorNode')
var AudioContext = (function(super$0){"use strict";super$0=events.EventEmitter;if(!PRS$0)MIXIN$0(AudioContext, super$0);var proto$0={};
function AudioContext(opts) {var this$0 = this;
var outBuff
/*Object.defineProperty(this, 'currentTime', {
writable: false,
get: function() {}
})*/
Object.defineProperty(this, 'destination', {
writable: false,
value: new AudioDestinationNode(this)
})
//this.destination = new AudioDestinationNode(this)
/*Object.defineProperty(this, 'sampleRate', {
writable: false,
value: {} // TODO
})
Object.defineProperty(this, 'listener', {
writable: false,
value: {} // TODO
})*/
this.currentTime = 0
this.sampleRate = 44100
this.numberOfChannels = 2
this.bitDepth = 16
this.format = {
numberOfChannels: 2,
bitDepth: 16,
sampleRate: this.sampleRate
}
opts = opts || {}
if (opts.bufferSize) this.format.bufferSize = opts.bufferSize
if (opts.numBuffers) this.format.numBuffers = opts.numBuffers
this.outStream = null
this._encoder = pcmUtils.BufferEncoder(this.format)
this._frame = 0
this._playing = true
this._audioOutLoopRunning = false
// When a new connection is established, start to pull audio
this.destination._inputs[0].on('connection', function() {
if (this$0._audioOutLoopRunning) return
if (!this$0.outStream) throw new Error('you need to set outStream to send the audio somewhere')
this$0._audioOutLoopRunning = true
async.whilst(
function() {
return this$0._playing
},
function(next) {
outBuff = this$0.destination._tick()
// If there is space in the output stream's buffers, we write,
// otherwise we wait for 'drain'
this$0._frame += BLOCK_SIZE
this$0.currentTime = this$0._frame * 1 / this$0.sampleRate
// TODO setImmediate here is for cases where the outStream won't get
// full and we end up with call stack max size reached.
// But is it optimal?
if (this$0.outStream.write(this$0._encoder(outBuff._data)))
setImmediate(next)
else this$0.outStream.once('drain', next)
},
function(err) {
this$0._audioOutLoopRunning = false
if (err) return this$0.emit('error', err)
}
)
})
}if(super$0!==null)SP$0(AudioContext,super$0);AudioContext.prototype = OC$0(super$0!==null?super$0.prototype:null,{"constructor":{"value":AudioContext,"configurable":true,"writable":true}});DP$0(AudioContext,"prototype",{"configurable":false,"enumerable":false,"writable":false});
proto$0.createBuffer = function(numberOfChannels, length, sampleRate) {
return new AudioBuffer(numberOfChannels, length, sampleRate)
};
proto$0.decodeAudioData = function(audioData, successCallback, errorCallback) {
utils.decodeAudioData(audioData, function(err, audioBuffer) {
if (err) errorCallback(err)
else successCallback(audioBuffer)
})
};
proto$0.createBufferSource = function() {
return new AudioBufferSourceNode(this)
};
proto$0.createGain = function() {
return new GainNode(this)
};
proto$0.createScriptProcessor = function(bufferSize, numberOfInputChannels, numberOfOutputChannels) {
return new ScriptProcessorNode(this, bufferSize, numberOfInputChannels, numberOfOutputChannels)
};
/*
{
readonly attribute AudioDestinationNode destination
readonly attribute float sampleRate
readonly attribute double currentTime
readonly attribute AudioListener listener
// AudioNode creation
MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement)
MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream)
MediaStreamAudioDestinationNode createMediaStreamDestination()
AnalyserNode createAnalyser()
DelayNode createDelay(optional double maxDelayTime = 1.0)
BiquadFilterNode createBiquadFilter()
WaveShaperNode createWaveShaper()
PannerNode createPanner()
ConvolverNode createConvolver()
ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6)
ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6)
DynamicsCompressorNode createDynamicsCompressor()
OscillatorNode createOscillator()
PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag)
}
*/
proto$0._kill = function() {
this._playing = false
if (this.outStream) {
if (this.outStream.close) {
this.outStream.close()
} else {
this.outStream.end()
}
}
};
proto$0.collectNodes = function(node, allNodes) {var this$0 = this;
allNodes = allNodes || []
node = node || this.destination
_.chain(node._inputs)
.pluck('sources')
.reduce(function(all, sources) {
return all.concat(sources)
}, [])
.pluck('node').value()
.forEach(function(upstreamNode) {
if (!_.contains(allNodes, upstreamNode)) {
allNodes.push(upstreamNode)
this$0.collectNodes(upstreamNode, allNodes)
}
})
return allNodes
};
MIXIN$0(AudioContext.prototype,proto$0);proto$0=void 0;return AudioContext;})();
module.exports = AudioContext