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
JavaScript utility to chop an audio buffer, inspired from youpy/scissor
✂️ Demo
✂️ Documents
✂️ Installation
$ npm install ciseauxdownloads:
✂️ API
Ciseaux.context = AudioContextCiseaux.from(src: string): Promise<Tape>Ciseaux.silence(duration: number): TapeCiseaux.concat(...tapes: Tape): TapeCiseaux.mix(...tapes: Tape, [method='silence']): Tape
Instance attributes
sampleRate: numberreadonlylength: numberreadonlyduration: numberreadonlynumberOfChannelsreadonlynumberOfTracksreadonly
Instance methods
gain(gain: number = 1): Tapepan(pan: number = 0): Tapereverse(): Tapepitch(rate: number = 1): Tapestretch(rate: number = 1): Tape- not implemented (Pull Request please)
concat(...tapes: Tape): Tapeslice(startTime: number = 0, duration: number = inf): Tapeloop(n: number = 2): Tapefill(duration: number): Tapereplace(startTime: number = 0, duration: number = 0, tape: Tape = null): Tapesplit(n: number = 2): Tape[]mix(...tapes: Tape, [method = 'silence']): Taperender(): Promise<AudioBuffer>dispose(): void
Ciseaux.Sequence
Utility class for creating a sequence tape that is concatenated tapes
constructor(...args: any)pattern: stringdurationPerStep: number|number[]instruments: object
Instance methods
apply(...args: any): Tapepattern: stringdurationPerStep: number|number[]instruments: object
✂️ 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);
});✂️ 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);✂️ 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
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature - Commit your changes:
git commit -am 'Add some feature' - Push to the branch:
git push origin my-new-feature - Submit a pull request :D