Home

Awesome

web-audio-stream Build Status Greenkeeper badge stable

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.

Usage

npm install web-audio-stream

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))

API

const {Read, Write} = require('web-audio-stream')

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')

let write = Write(destNode, options?)

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:

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.

let read = Read(sourceNode, options?)

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)
	}
})

Stream API

const {Readable, Writable} = require('web-audio-stream/stream')

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')

let writable = Writable(destNode, options?)

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)

let readable = Readable(audioNode, options?)

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 API

Pull-stream interfaces internally use plain reader and writer and can be used in the same fashion.

const {sink, source} = require('web-audio-stream/pull')

const Sink = require('web-audio-stream/sink')
const Source = require('web-audio-stream/source')

let sink = Sink(destNode, options?)

let source = Source(srcNode, options?)

Related