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
bower:
bower install ciseauxnpm:
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
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
- 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