Interface between Web Audio API and streams. Send AudioBuffer/Buffer/ArrayBuffer/FloatArray data to Web Audio API (writable mode) or connect any AudioNode to stream (readable mode). There are three types of connection available: as plain functions, as streams or pull-streams.
const context = require('audio-context')
const Generator = require('audio-generator')
const {Readable, Writable} = require('web-audio-stream/stream')
let oscillator = context.createOscillator()
oscillator.type = 'sawtooth'
oscillator.frequency.value = 440
oscillator.start()
//pipe oscillator audio data to stream
Readable(oscillator).on('data', (audioBuffer) => {
console.log(audioBuffer.getChannelData(0))
})
//pipe generator stream to audio destination
Generator(time => Math.sin(Math.PI * 2 * time * 440))
.pipe(Writable(context.destination))
Get Web-Audio-API reader or writer constructors. They can be required separately:
const createReader = require('web-audio-stream/read')
const createWriter = require('web-audio-stream/write')
Create function writing to web-audio-API AudioNode with the following signature: write(audioBuffer, (err) => {})
. To end stream properly, call write(null)
.
options
parameter is optional and may provide the following:
mode
− 0 or 1, defines buffer or script mode of feeding data, may affect performance insignificantly.context
− audio context, defaults to audio-context module.samplesPerFrame
andchannels
define audio buffer params.
const Writer = require('web-audio-stream/write')
const Generate = require('audio-generator')
const util = require('audio-buffer-utils')
let write = Writer(context.destination, {
samplesPerFrame: 1024
})
let generate = Generate(t => Math.sin(440 * t * Math.PI * 2))
//add stopper
let isStopped = 0
setTimeout(() => {
isStopped = 1
}, 500)
function gen (err) {
if (err) throw err
if (isStopped) {
write(null)
return
}
//generate new audio buffer
let aBuf = generate(util.create(frame))
//send audio buffer to audio node
write(aBuf, gen)
}
gen()
Writer is smart enough to recognize any type of data placed into it: AudioBuffer, AudioBufferList, ArrayBuffer, FloatArray, Buffer, Array. Make sure only that passed buffer format complies with passed options, ie. samplerPerFrame
, channels
etc.
Note on performance. Internally writer uses audio-buffer-list to manage memory efficiently, providing pretty low latency.
Create reader from web AudioNode with signature read((err, audioBuffer) => {})
, returning audio frames data. To end reading, pass read(null)
.
const Reader = require('web-audio-stream/read')
let oscNode = context.createOscillator()
oscNode.type = 'sawtooth'
oscNode.frequency.value = 440
oscNode.start()
let read = Reader(oscNode)
let count = 0
read(function getData(err, audioBuffer) {
//output audioBuffer here or whatever
if (count++ >= 5) {
//end after 5th frame
read(null)
}
else {
read(getData)
}
})
Get readable or writable stream to pipe data from stream to web-audio directly.
//web-audio → stream
const Readable = require('web-audio-stream/readable')
//stream → web-audio
const Writable = require('web-audio-stream/writable')
Create writer to web audio node, possibly based on options. Pipe any stream to writable, or write data directly to it, basically it implements Writable stream class.
const Writable = require('web-audio-stream/writable')
const context = require('audio-context')
//options or single properties are optional
let writable = Writable(context.destination, {
context: context,
channels: 2,
sampleRate: context.sampleRate,
//BUFFER_MODE, SCRIPT_MODE, WORKER_MODE (pending web-audio-workers)
mode: Writable.BUFFER_MODE,
//disconnect node if input stream ends
autoend: true
})
const Generator = require('audio-generator')
let src = Generator(function (time) {
return Math.sin(Math.PI * 2 * time * 440)
})
src.pipe(writable)
//or simply send data to web-audio
let chunk = new Float32Array(1024)
for (let i = 0; i < 1024; i++) {
chunk[i] = Math.random()
}
writable.write(chunk)
setTimeout(writable.end, 1000)
Readable stream to read data from web-audio-API.
const Readable = require('web-audio-stream/readable')
let readable = Readable(myNode)
readable.on('data', buffer => {
console.log('Got audio buffer')
})
Pull-stream interfaces internally use plain reader and writer and can be used in the same fashion.
const Sink = require('web-audio-stream/sink')
const Source = require('web-audio-stream/source')
- audio-speaker — node/browser speaker stream.
- audio-through — universal audio stream class.