audiojs / contributing

Discussion and guidelines for contributing
2 stars 0 forks source link

Handling arrays directly #36

Open dy opened 7 years ago

dy commented 7 years ago

Pondering on audio-noise and audio-filter modules. What if we extend basic no-stream modules to work with float arrays and not force AudioBuffer type, while we have a chance #34?

+ that makes audio-* components first-class citizens, allowing for low-level processing and graceful readme examples + that lowers entry barrier for non-audio folks + that enables direct nodejs application of modules, out of @audiojs infrastructure

const noise = require('audio-noise/pink')()

let data = noise(new Float32Array(1024))

//vs

let buf = noise(new AudioBuffer({length: 1024}))
jamen commented 7 years ago

Agreed! We should do that where possible. It would also make it so subsequent stream packages can accept arrays, which would also be nice.

dy commented 7 years ago

Just thinking, take audio-filter for example. Ideal minimal low-level implementation would take care only of 1d arrays, like Array or FloatArray. How it is best to extend it to cover @audiojs demands − processing AudioBuffers? We also can think of some folks who may want to process ndsamples, ndarrays, nested arrays, buffers etc. So how should we organize code to meet all the requirements?

  1. Filters collection package like @audiojs/filter or dsp-filter for 1d arrays, and audio-filter wrapper for audio-buffers. :-1: doesn't bring plain arrays to @audiojs ecosystem and only AudioBuffer solution.
  2. Detecting data type inside of filter filter(array); filter(audioBuffer). :-1: slow and lots of code dup across filters.
  3. Providing data type in options alike streams createFilter({dataType: AudioBuffer}). :-1: a lot of dup code, non-low-level solution.
  4. getData optional param for custom data type, returning [ch1, ch2, ...] data, and also vectors for other params, eg.

    
    let filter = createFilter({
    //same value for all channels
    lambda: value,
    
    //own value for every channel
    y: [0, 0.1, 0.05],
    
    //optionally obtain multichannel data from any source, like audio-buffer, ndarray etc
    getData: src => [src.getChannelData(0), src.getChannelData(1), src.getChannelData(3)]
    })
    let buf = filter(AudioBuffer({channels: 2, length: 1000})

//default filter is 1d let filter2 = createFilter({lambda: λ}) let arr = filter2(Array(1024))


Upside − general nd-data processing, downside − no default _AudioBuffer_ processing and tax for obtaining data.

UPD. actually we can use 1st method, that seems the most obvious step - separating concerns to dsp filters and more robust audio filters.