0.4.0 • Published 9 years ago

ciseaux v0.4.0

Weekly downloads
13
License
MIT
Repository
github
Last release
9 years ago

ciseaux

Build Status NPM Version Coverage Status License

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

:scissors: Demo

:scissors: Documents

:scissors: Installation

$ npm install ciseaux

downloads:

:scissors: 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

:scissors: Usage

browser

const Ciseaux = require("ciseaux/browser");

Ciseaux.context = new AudioContext();

// create a tape instance from the url
Ciseaux.from("/path/to/audio.wav").then((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((audioBuffer) => {
  play(audioBuffer);
});

node.js

const fs = require("fs");
const Ciseaux = require("ciseaux/node");

// create a tape instance from the filepath
Ciseaux.from("/path/to/audio.wav").then((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((buffer) => {
  fs.writeFile("/path/to/ciseauxed.wav", buffer);
});

:scissors: 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, tape => tape.reverse());

gain

tape = Ciseaux.concat(
  tape1.split(25).map((tape, i) => tape.gain(i / 25))
);

pan

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

pitch

tape = Ciseaux.concat(
  tape1.split(25).map((tape, i) => 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(tape => tape.loop(4).pitch(1.5))
).fill(30);

phase

tape = Ciseaux.mix([ 1, 0.95 ].map(rate => tape2.pitch(rate).fill(30)));

lace

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

concrete

tape = Ciseaux.mix([ -12, -10, -7, -3, 0 ].map((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(x => x * 0.3)).fill(30);

:scissors: Architecture

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

:scissors: 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

:scissors: 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

:scissors: License

MIT

0.4.0

9 years ago

0.3.0

10 years ago

0.2.0

10 years ago

0.1.9

10 years ago

0.1.8

10 years ago

0.1.7

10 years ago

0.1.6

10 years ago

0.1.5

10 years ago

0.1.4

10 years ago

0.1.3

10 years ago

0.1.2

10 years ago

0.1.1

10 years ago

0.1.0

10 years ago