A set of methods for the generation and transformation of number sequences useful in algorithmic composition
npm install total-serialismA Toolbox full of Algorithmic Composition methods
🙏 Support Total Serialism by becoming a Patron
Visit the Total Serialism Documentation for interactive examples.
total-serialism is a set of methods used for procedurally generating and transforming number sequences (mainly in the form of arrays). This library does not output anything else then numbers, but can therefore be nicely integrated with frameworks like P5js, ToneJS, Node4Max, Hydra and any other javascript based project you want to generate arrays for. For examples with P5 see In Action. This library focusses mainly on algorithmic composition of music, but is absolutely not limited to only that and will be useful for any project that involves generation and manipulation of arrays and numbers. The library is a result of my research in algorithmic composition, livecoding and electronic music and was first prototyped with Max/MSP in the Mercury livecoding environment. It is now also used in the web based Mercury Playground
This library is a work in progress. I'm always interested in receiving inspiration, suggestions, enhancements, literature and more. Feel free to file an issue here or make a pull request and I will gladly look into it!
- 👾 Newest Features
- 🚀 Install
- 🔭 Content
- 📟 Usage
- 📖 Documentation
- 🎮 In Action with p5js
- ✨ Inspiration & Bibliography
- 📄 License
Evaluate a function for all the possible combinations of the arguments provided up to the least common multiple of the list lengths. A very powerful feature to quickly calculate long generative pieces out of a single function.
``js
// 3x the euclidean algorithm, like:
// join(euclid(8, 5), euclid(8, 7), euclid(8, 3))
Util.multiEval(Algo.euclid, 8, [5, 7, 3])
// [
// 1, 0, 1, 1, 0, 1, 1, 0,
// 1, 1, 1, 1, 1, 1, 1, 0,
// 1, 0, 0, 1, 0, 0, 1, 0
// ]
// 6x the spread function, like:
// join(spread(5, 0, 12), spread(3, 0, 24), spread(8, 0, 12),
// spread(5, 0, 24), spread(3, 0, 12), spread(8, 0, 24))
Util.multiEval(Gen.spread, [5, 3, 8], 0, [12, 24])
// [
// 0, 2, 4, 7, 9, 0, 8, 16, 0,
// 1, 3, 4, 6, 7, 9, 10, 0, 4,
// 9, 14, 19, 0, 4, 8, 0, 3, 6,
// 9, 12, 15, 18, 21
// ]
`
Generative rhythmical patterns of 1's and 0's by converting a number to binary or using the integer value as spacing between onsets
`js
const Gen = require('total-serialism').Generative;
Gen.binary(358);
//=> [1, 0, 1, 1, 0, 0, 1, 1, 0]
Gen.space(2, 3, 2)
//=> [1, 0, 1, 0, 0, 1, 0]
`
This is an identical approach to the MarkovChain while also offering the possibility of training to create n-order chains. In theory, longer chains preserve the original structure of the model, but won't generate as diverse outputs. Thanks to James Bradbury
`js
const Rand = require('total-serialism').Stochastic;
let pattern = [1, 2, 3, 1, 2, 4, 1, 2, 5, 2, 3, 4];
// make a MarkovChain instance and optionally train with array
// an optional second argument sets the order of the markov (default=2)
let markov = new Rand.DeepMarkov(pattern, 2);
// view the transition table (stored as Map())
// Keys are stored as stringis derived via JSON.stringify()
console.log(markov.table);
// Map(7) {
// '[1,2]' => [ 3, 4, 5 ],
// '[2,3]' => [ 1, 4 ],
// '[3,1]' => [ 2 ],
// '[2,4]' => [ 1 ],
// '[4,1]' => [ 2 ],
// '[2,5]' => [ 2 ],
// '[5,2]' => [ 3 ]
// }
// set the state of the model used as initial value
markov.state([1, 2]);
// generate an array of 10 values
markov.chain(10);
// => [ 2, 3, 1, 2, 5, 2, 3, 4, 1, 2 ]
`
Generate chord progressions as 2d-array's of semitones from an array of Roman Numerals and an optional root note.
`js
const TL = require('total-serialism').Translate;
// Convert a chord progression from roman numerals to semitones
TL.chordsFromNumerals(['I', 'IIm', 'IVsus2', 'V7', 'VIm9'], 'c');
// => [[ 0, 4, 7 ],
// [ 2, 5, 9 ],
// [ 5, 7, 0 ],
// [ 7, 11, 2, 5 ],
// [ 9, 0, 4, 7, 11 ]]
`
Most of the transform, translate and utility functions now support calculations with n-dimensional arrays.
`js
const TL = require('total-serialism').Translate;
const Mod = require('total-serialism').Transform;
TL.noteToMidi(['c4', ['eb4', 'g4', 'a4'], ['a3', 'f4']]);
//=> [ 60, [ 63, 67, 69 ], [ 57, 65 ] ]
Mod.clone(['c', ['e', 'g']], ['4', '5', '#3']);
//=> [ 'c4', [ 'e4', 'g4' ], 'c5', [ 'e5', 'g5' ], 'c#3', [ 'e#3', 'g#3' ] ]
TL.relativeToMidi([[-12, -9, -5], [0, 4, 7], [2, 5, 9]], 'c4');
//=> [ [ 36, 39, 43 ], [ 48, 52, 55 ], [ 50, 53, 57 ] ]
Stat.compare(['c', ['e', 'g']], ['c', ['e', 'g']]);
//=> true
Mod.flatten([1, [2, 3, [ 4 ], 5], 6]);
//=> [ 1, 2, 3, 4, 5, 6 ]
Mod.lookup([0, [1, 1, [2, 3], 0], 2], ['c4', 'e4', 'f4', 'g4']);
//=> [ 'c4', [ 'e4', 'e4', [ 'f4', 'g4' ], 'c4' ], 'f4' ]
`
Generate an Elementary Cellular Automaton class. This is an one dimensional array (collection of cells) with states that are either dead or alive (0/1). By following a set of rules the next generation is calculated for every cell based on its neighbouring cells.
`js
const Algo = require('total-serialism').Algorithmic;
const Rand = require('total-serialism').Stochastic;
let ca = new Algo.Automaton();
// feed with 40 randomly generated values 0-1
ca.feed(Rand.coin(40));
// set the rule with a decimal representation
ca.rule(120);
// generate the next generation and store in array
let gen = ca.next();
// create multiple generations in a forloop
let gens = [];
for (let i=0; i<10; i++){
gens.push(ca.next());
}
Util.draw(gens);
// ██ ████ ████ █ ███ █ █ ██ █ ██
// ████ █ ███ ██ █ █ ██ █ █ ███ ███
// ██ █ █ ██ ███ █ ████ █ ██ ██ █
// ███ █ █████ ██ ██ ██ █ ██████ █
// █ ██ ██ ████████ ███ █ █ ██ █
// █ ███████ █ ███ ██ █ █ ███
// █ █ ██ █ █ █████ █ █ █ ██
// █ █ ███ █ ██ ██ █ █ ████
// █ █ █ ██ █ ███ ███ █ █ █ ██
// █ █ █ ████ █ █ ██ █ ██ █ █ █ ██
`
Use the new TL.Scala() class to import a .scl file (Scala tuning format) to work with custom tuning systems apart from the Western 12-TET (Equal Temperament) tuning or use one of the tunings from a database with over 5000 tunings from Stichting Huygens-Fokker.
`js
const { Scala } = require('total-serialism').Translate;
// Create an instance of a Scala class
let scl = new Scala();
scl.scalaToFreq([60, 63, 67, 69, 72, 81, 36, 48]);
//=> [ 261.63, 311.13, 392.00, 440.00, 523.25, 880.00, 65.41, 130.81 ]
// Get the entire list of names from the library
scl.names;
// [ '05-19',
// '05-22',
// '05-24',
// '06-41',
// '07-19',
// '07-31',
// '07-37',
// '08-11',
// '08-13',
// '08-19', ... and 5000 more]
`
Use the Rand.clave() to generate binary beats with clave patterns
`js
const { clave } = require('total-serialism').Stochastic;
clave(16, 4);
//=> [ 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1 ]
//=> █ █ █ █ █ █
clave(16, 3, 1);
//=> [ 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1 ]
//=> █ █ ██ █ █ █
`
``
$ npm install total-serialism
`js
// entire package
const Srl = require('total-serialism');
// subset of library
const Gen = require('total-serialism').Generative;
// specific methods
const { spread, fill } = require('total-serialism').Generative;
`
`js`
// entire package
const Srl = require('total-serialism/build/ts.es5.js');
// subset of library
const Algo = require('total-serialism/build/ts.es5.js').Algorithmic;
Include latest or specific version of bundled minified es5 through url in index.html
`html
`
Here are some alternatives to unpkg.com, in case of a server error:
https://cdn.staticdelivr.com/npm/total-serialism/build/ts.es5.min.js
or https://cdn.jsdelivr.net/npm/total-serialism/build/ts.es5.min.js
Use in a html