lib/index.js
'use strict'
/**
* Copy `len` bytes generated by a function to `array` starting at `pos`
*/
function copy (len, array, pos, fn) {
for (var i = 0; i < len; i++) {
array[pos + i] = fn(i)
}
}
function stretch (ac, input, scale, options) {
// OPTIONS
var opts = options || {}
// Processing sequence size (100 msec with 44100Hz sample rate)
var seqSize = opts.seqSize || 4410
// Overlapping size (20 msec)
var overlap = opts.overlap || 882
// Best overlap offset seeking window (15 msec)
// var seekWindow = opts.seekWindow || 662
// The theoretical start of the next sequence
var nextOffset = Math.round(seqSize / scale)
// Setup the buffers
var numSamples = input.length
var output = ac.createBuffer(1, numSamples * scale, input.sampleRate)
var inL = input.getChannelData(0)
var outL = output.getChannelData(0)
// STATE
// where to read then next sequence
var read = 0
// where to write the next sequence
var write = 0
// where to read the next fadeout
var readOverlap = 0
while (numSamples - read > seqSize) {
// write the first overlap
copy(overlap, outL, write, function (i) {
var fadeIn = i / overlap
var fadeOut = 1 - fadeIn
// Mix the begin of the new sequence with the tail of the sequence last
return (inL[read + i] * fadeIn + inL[readOverlap + i] * fadeOut) / 2
})
copy(seqSize - overlap, outL, write + overlap, function (i) {
// Copy the tail of the sequence
return inL[read + overlap + i]
})
// the next overlap is after this sequence
readOverlap += read + seqSize
// the next sequence is after the nextOffset
read += nextOffset
// we wrote a complete sequence
write += seqSize
}
return output
}
module.exports = { stretch: stretch }