Git Product home page Git Product logo

audio-buffer-utils's Introduction

Utility functions for Audio Buffers. See @audiojs/audio-buffer-utils.

Usage

$ npm install audio-buffer-utils

var utils = require('audio-buffer-utils');

//Create a new buffer from any argument.
//Data can be a length, an array with channels' data, an other buffer or plain array.
utils.create(channels?, data, sampleRate?);

//Create a new buffer with the same characteristics as `buffer`,
//contents are undefined.
utils.shallow(buffer);

//Create a new buffer with the same characteristics as `buffer`,
//fill it with a copy of `buffer`'s data, and return it.
utils.clone(buffer);

//Copy the data from one buffer to another, with optional offset
utils.copy(fromBuffer, result, offset?);

//Reverse `buffer`. Place data to `result` buffer, if any, otherwise modify `buffer` in-place.
utils.reverse(buffer, result?);

//Invert `buffer`. Place data to `result` buffer, if any, otherwise modify `buffer` in-place.
utils.invert(buffer, result?);

//Zero all of `buffer`'s channel data. `buffer` is modified in-place.
utils.zero(buffer);

//Fill `buffer` with random data. `buffer` is modified in-place.
utils.noise(buffer);

//Test whether the content of N buffers is the same.
utils.equal(bufferA, bufferB, ...);

//Fill `buffer` with provided function or value.
//Place data to `result` buffer, if any, otherwise modify `buffer` in-place.
//Pass optional `start` and `end` indexes.
utils.fill(buffer, result?, value|function (sample, idx, channel) {
	return sample / 2;
}, start?, end?);

//Create a new buffer by mapping the samples of the current one.
utils.map(buffer, function (sample, idx, channel) {
	return sample / 2;
});

//Create a new buffer by slicing the current one.
utils.slice(buffer, start?, end?);

//Create a new buffer by concatting passed buffers.
//Channels are extended to the buffer with maximum number.
//Sample rate is changed to the maximum within the buffers.
utils.concat(buffer1, buffer2, buffer3, ...);

//Return new buffer based on the passed one, with shortened/extended length.
//Initial data is whether sliced or filled with zeros.
//Useful to change duration: `util.resize(buffer, duration * buffer.sampleRate);`
utils.resize(buffer, length);

//Right/left-pad buffer to the length, filling with value
utils.pad(buffer, length, value?);
utils.pad(length, buffer, value?);

//Shift signal in the time domain by `offset` samples, filling with zeros.
//Modify `buffer` in-place.
utils.shift(buffer, offset);

//Shift signal in the time domain by `offset` samples, in circular fashion.
//Modify `buffer` in-place.
utils.rotate(buffer, offset);

//Fold buffer into a single value. Useful to generate metrics, like loudness, average, etc.
utils.reduce(buffer, function (previousValue, currendValue, idx, channel, channelData) {
	return previousValue + currentValue;
}, startValue?);

//Normalize buffer by the max value, limit to the -1..+1 range.
//Place data to `result` buffer, if any, otherwise modify `buffer` in-place.
utils.normalize(buffer, result?, start?, end?);

//Create buffer with trimmed zeros from the start and/or end, by the threshold.
utils.trim(buffer, threshold?);
utils.trimStart(buffer, threshold?);
utils.trimEnd(buffer, threshold?)

//Mix second buffer into the first one. Pass optional weight value or mixing function.
util.mix(bufferA, bufferB, ratio|fn(valA, valB, idx, channel)?, offset?);

//Return buffer size, in bytes. Use pretty-bytes package to format bytes to a string, if needed.
utils.size(buffer);

//Get channels' data in array. Pass existing array to transfer the data to it.
//Useful in audio-workers to transfer buffer to output.
utils.data(buffer, data?);

Related

audio-buffer — audio data container, both for node/browser.
pcm-util — utils for low-level pcm buffers, like audio formats etc.
scijs — DSP utils, like fft, resample, scale etc.

audio-buffer-utils's People

Contributors

dy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

audio-buffer-utils's Issues

Padding

Quite useful for situations where we need to ensure buffer of specific length.

//ensure buffer is left-padded to length 1024
buf = util.padLeft(buf, 1024);

//ensure buffer is right-padded to length 1024
buf = util.padRight(buf, 1024);

//ensure buffer is left-padded to length 1024, fill space with 1
buf = util.padRight(buf, 1024, 1);

//OR maybe make syntax following:
util.pad(1024, buf); //pad left
util.pad(buf, 1024); //pad right
//positional args are quite intuitive, no need to guess/recall which is the order of args

Ah, I forgot, resize here is for that.
Maybe make pad method through resize and shift?

API ideas

String/other libs inspired:

  • repeat
  • padStart, padEnd
  • sampleAt
  • reduce (for average/max/min/bars calculation)

Safari

Hey, thanks for making this! It has been useful to me.

I just found out that Safari doesn't support any of the normal array methods on Float32Array (unless I am confused, not super familiar with typed arrays). How do you deal with this? Or have you ignored Safari for now?

Thanks

Transfer to audiojs

Hi @jaz303!

How do you feel about transfering this repo to @audio-lab?
All redirects will be saved, just package will be easier to search within the similar ones.

Ability to mix two buffers with offset and make length the union?

It seems that right now, if you mix two buffers together and the second one ends before the first one, the buffer will not extend to accomodate this. A great feature would be to have a mixLongest function or something, where the total length of the resulting buffer would then be where bufferB ends, provided it ends after bufferA with the offset taken into account.

Is this something you could look into adding? Thanks!

Swap channel/index arguments order in fill and related methods

In usual practical cases, like planar buffer layout, channels are represented by y-coordinate.
According to ubiquitous convention for dimensions, arguments follow in x, y, z, w order: like ndarray.get/set, webgl-textures, imageData, glsl lang, etc.
Here walking through samples have inverse order of agrs: channel first, index second.
That contradicts to common convention(s) and unintuitive. User rarely need knowing something further that index of a sample, also index is naturally synonymic to x coord notion.

I suggest swapping coords in fill to:

utils.fill(buffer, function (sample, idx,←→ channel?) {
    return sample / 2;
});

TOC

With such grown up API now it is troublesome to seek methods in readme.
Is there a sense to create Table of Contents with per-method description?

BTW after the release of 1.0.0 I’m going to switch to PR-workflow not to cluster multiple commits together and be able to discuss solutions. Sorry about that mess in master now, that is really an issue of rapid grow)

clone()'d buffers share backing array with source buffer

Cloning a buffer and then modifying data in the original buffer causes data in the clone to change also. This is due to the backing arrays being shared. Cloned buffers should be completely distinct from their source buffers.

Failing test case: 97cc5fb

This is a result of behaviour in audio-buffer (not sure if intentional), which assigns a shallow copy to new derived buffers:

https://github.com/audio-lab/buffer/blob/master/buffer.js#L43-L52

Cloning API

Now there are 3 methods doing similarly the same:

  • .slice - returns cloned buffer of any length ≤ initial length,
  • .clone - returns cloned buffer of the same length,
  • .makeCompatible - returns shallow clone, same as fill(clone(buffer))(0) (btw how do you think maybe the name is a bit unwieldy to type?).
    So maybe there is a sense to just make clone method with deep argument, which will create a deep copy, but the shallow copy otherwise? Now clone method is lacking of use.
    In the manner of node.cloneNode(deep) and npm clone.

Validate AudioBuffer argument?

A couple of times I got into a situation where utils did something to an argument, which was not AudioBuffer, but for example, Buffer, or Float32Array, and silently returned something. And that led to confusion.
Validating the argument instanceof AudioBuffer would be handy for dev process, and that is de-facto practice, but will affect performance, a tiny bit. Should we add that @jaz303?

pad loses channels

util.pad(util.create(1, buf), 44100*10);

Returns stereo, which is wrong

AudioWorker

We should consider the case of using utils in AudioWorker, in future. It takes not buffers, but arrays of channel data, like [channel1data, channel2data, ...]. So maybe we should detect that data, or be able to process Float32Arrays.
Actually this is also a case when we need to apply processing to a single channel.

create method

Just to delegate all the work with buffers to the lib.

util.create(); //create minimal valid instance
util.create([ch1array, ch2array, ...]); //for the case of audio-worker in issue #8
util.create(2,2,44100); //wrapper over new AudioBuffer(ch, len, rate) or ctx.createBuffer() or whatever
util.create(otherBuffer); //clone
util.create(arrayBuffer); //from specific data
...

Possible names:

  • util.new()
  • util.create()
  • util.from()

@jaz303 which one is better? .from is conventional, like Array.from, but .create is unambiguous.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.