packages/oscillator/index.js
/**
* > Wavetable oscillators
*
* [![npm install dsp-oscillator](https://nodei.co/npm/dsp-oscillator.png?mini=true)](https://npmjs.org/package/dsp-oscillator/)
*
* This is part of [dsp-kit](https://github.com/oramics/dsp-kit)
*
* ### References
*
* - http://www.earlevel.com/main/2012/05/09/a-wavetable-oscillator%E2%80%94part-3/
* - http://www.earlevel.com/main/2012/05/25/a-wavetable-oscillator%E2%80%94the-code/
* - https://github.com/OpenDAWN/wavetable
*
* @example
* const oscillator = require('dsp-oscillator')
*
* @module oscillator
*/
import { zeros } from 'dsp-array'
const { round, PI, sin } = Math
const PI2 = 2 * PI
/*
* oscillator module TODO:
* - other generators
* - phase parameter
*/
const generators = {
sine: (x) => sin(PI2 * x),
saw: (x) => 2 * (x - Math.round(x))
}
/**
* Create an oscillator. Returns a function that generates the oscillator
* signal
* @param {Object} params - oscillator parameters:
*
* - type: one of 'sine'
* - sampleRate: 44100 by default
* - defaultSize: the length of the generated buffer
*/
export function oscillator ({ type = 'sine', sampleRate = 44100, defaultSize = 1024 } = {}) {
let frameCount = 0
let tableLen = 2048
let table = generateWaveTable(tableLen, generators[type], sampleRate)
/**
* Generate the oscillator data
*/
return function ({ frequency = 440, size = 0 } = {}, output) {
if (!output) output = zeros(size || defaultSize)
size = output.length
let frameOffset = frameCount * size
let step = tableLen * frequency / sampleRate
let offset
for (let i = 0; i < size; i++) {
offset = round((frameOffset + i) * step)
output[i] = table[offset % tableLen]
}
frameCount++
return output
}
}
function generateWaveTable (size, gen, sampleRate) {
let table = zeros(size)
var waveTableTime = size / sampleRate
var waveTableHz = 1 / waveTableTime
for (var i = 0; i < size; i++) {
table[i] = gen(i * waveTableHz / sampleRate)
}
return table
}