JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q51056F

utility to chop an audio buffer

Package Exports

  • ciseaux
  • ciseaux/browser
  • ciseaux/lib/tape
  • ciseaux/node

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ciseaux) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

ciseaux

Build Status NPM Version Bower Coverage Status License

JavaScript utility to chop an audio buffer, inspired from youpy/scissor

✂️ Demo

✂️ Documents

✂️ Installation

bower:

bower install ciseaux

npm:

npm install ciseaux

downloads:

✂️ API

  • Ciseaux.context = AudioContext
  • Ciseaux.from(src: string): Promise<Tape>
  • Ciseaux.silence(duration: number): Tape
  • Ciseaux.concat(...tapes: Tape): Tape
  • Ciseaux.mix(...tapes: Tape, [method='silence']): Tape

Instance attributes

  • sampleRate: number readonly
  • length: number readonly
  • duration: number readonly
  • numberOfChannels readonly
  • numberOfTracks readonly

Instance methods

  • gain(gain: number = 1): Tape
  • pan(pan: number = 0): Tape
  • reverse(): Tape
  • pitch(rate: number = 1): Tape
  • stretch(rate: number = 1): Tape
    • not implemented (Pull Request please)
  • concat(...tapes: Tape): Tape
  • slice(startTime: number = 0, duration: number = inf): Tape
  • loop(n: number = 2): Tape
  • fill(duration: number): Tape
  • replace(startTime: number = 0, duration: number = 0, tape: Tape = null): Tape
  • split(n: number = 2): Tape[]
  • mix(...tapes: Tape, [method = 'silence']): Tape
  • render(): Promise<AudioBuffer>
  • dispose(): void

Ciseaux.Sequence

Utility class for creating a sequence tape that is concatenated tapes

  • constructor(...args: any)
    • pattern: string
    • durationPerStep: number|number[]
    • instruments: object

Instance methods

  • apply(...args: any): Tape
    • pattern: string
    • durationPerStep: number|number[]
    • instruments: object

✂️ Usage

browser

Ciseaux.context = new AudioContext();

// create a tape instance from the url
Ciseaux.from("/path/to/audio.wav").then(function(tape) {
  // edit tape
  tape = Ciseaux.concat([ tape.slice(10, 1), tape.slice(2, 3) ]).loop(4);

  // render the tape to an AudioBuffer
  return tape.render();
}).then(function(audioBuffer) {
  play(audioBuffer);
});

node.js

var fs = require("fs");
var Ciseaux = require("ciseaux");

// create a tape instance from the filepath
Ciseaux.from("/path/to/audio.wav").then(function(tape) {
  // edit tape
  tape = Ciseaux.concat([ tape.slice(10, 1), tape.slice(2, 3) ]).loop(4);

  // render the tape to Buffer (wav format)
  return tape.render();
}).then(function(buffer) {
  fs.writeFile("/path/to/ciseauxed.wav", buffer);
});

✂️ Examples

slice + concat

tape = tape2.slice(0, 1.5).concat(tape3.slice(0, 0.5), tape1.slice(-2));

slice + concat + loop

tape = tape3.slice(0, 0.5).concat(Ciseaux.silence(0.5)).loop(4);

replace + reverse

tape = tape1.replace(2, 3, function(tape) {
  return tape.reverse();
});

gain

tape = Ciseaux.concat(tape1.split(25).map(function(tape, i) {
  return tape.gain(i / 25);
}));

pan

tape = Ciseaux.concat(tape1.split(25).map(function(tape, i) {
  return tape.pan(i % 2 ? -0.85 : +0.85);
}));

pitch

tape = Ciseaux.concat(tape1.split(25).map(function(tape, i) {
  return tape.pitch(i / 50 + 0.75);
}));

mix

tape = tape1.mix(tape2.gain(0.5), "fill").fill(30);

stutter

tape = Ciseaux.concat(tape2.split(16).map(function(tape) {
  return tape.loop(4).pitch(1.5);
})).fill(30);

phase

tape = Ciseaux.mix([ 1, 0.95 ].map(function(rate) {
  return tape2.pitch(rate).fill(30);
}));

lace

tape = Ciseaux.concat(tape1.split(32).map(function(tape, index) {
  return index % 2 ? tape2.pitch(2).fill(tape.duration) : tape;
})).fill(30);

concrete

tape = Ciseaux.mix([ -12, -10, -7, -3, 0 ].map(function(midi) {
  return tape1.pitch(Math.pow(2, midi * 1/12));
}), "fill").gain(0.5).fill(30);

sequence

tape = new Ciseaux.Sequence("a bdacbba babfeg", 0.2, {
  a: tape1.split(16)[0],
  b: tape1.split(16)[1],
  c: tape1.split(16)[2],
  d: tape1.split(16)[3].gain(0.15),
  e: tape2.split(16)[4].pitch(0.25),
  f: tape2.split(16)[5].pitch(4).gain(0.1),
  g: tape3.pitch(32),
}).apply().fill(30);

shuffled sequence

tape = new Ciseaux.Sequence("a bdaabcaccbgabb", {
  a: tape1.split(16)[4],
  b: tape1.split(16)[1],
  c: tape1.split(16)[2],
  d: tape1.split(16)[3].gain(0.15),
  e: tape2.split(16)[4].pitch(0.25),
  f: tape2.split(16)[5].pitch(4).gain(0.1),
  g: tape3.pitch(32),
}).apply([ 2/3, 1/3 ].map(function(x) { return x * 0.3; })).fill(30);

✂️ Architecture

+---------------+     +----------------+                +-----------+
| new Tape()    | --> | Float32Array[] | -- transfer -> |           |
|               |     +----------------+                |           |
|               |                                       |           |
|               |     +----------------+                |           |
| Tape.render() | --> | JSON           | -- transfer -> | WebWorker |
+---------------+     +----------------+                |           |
                                                        |           |
+---------------+     +----------------+                |           |
| AudioData     | <-- | Float32Array[] | <- transfer -- |           |
+---------------+     +----------------+                +-----------+
  |
  +----------------+
  | browser        | node.js
  v                v
+-------------+  +---------------------+
| AudioBuffer |  | Buffer (wav format) |
+-------------+  +---------------------+

✂️ Developments

# Build : babel -> browserify -> uglify-js
npm run build

# Test : mocha + power-assert
npm run test

# Coverage : mocha + isparta
npm run cover

# Lint : eslint
npm run lint

✂️ Contributing

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

✂️ License

MIT