diff --git a/repl/package-lock.json b/repl/package-lock.json index e6ab44ab..460f0e86 100644 --- a/repl/package-lock.json +++ b/repl/package-lock.json @@ -6,6 +6,7 @@ "": { "dependencies": { "@tonaljs/tonal": "^4.6.5", + "chord-voicings": "^0.0.1", "codemirror": "^5.65.1", "estraverse": "^5.3.0", "multimap": "^1.1.0", @@ -2759,6 +2760,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/chord-voicings": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/chord-voicings/-/chord-voicings-0.0.1.tgz", + "integrity": "sha512-SutgB/4ynkkuiK6qdQ/k3QvCFcH0Vj8Ch4t6LbRyRQbVzP/TOztiCk3kvXd516UZ6fqk7ijDRELEFcKN+6V8sA==", + "dependencies": { + "@tonaljs/tonal": "^4.6.5" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -10966,6 +10975,14 @@ "readdirp": "~3.6.0" } }, + "chord-voicings": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/chord-voicings/-/chord-voicings-0.0.1.tgz", + "integrity": "sha512-SutgB/4ynkkuiK6qdQ/k3QvCFcH0Vj8Ch4t6LbRyRQbVzP/TOztiCk3kvXd516UZ6fqk7ijDRELEFcKN+6V8sA==", + "requires": { + "@tonaljs/tonal": "^4.6.5" + } + }, "chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", diff --git a/repl/package.json b/repl/package.json index 27414e0f..4a669878 100644 --- a/repl/package.json +++ b/repl/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@tonaljs/tonal": "^4.6.5", + "chord-voicings": "^0.0.1", "codemirror": "^5.65.1", "estraverse": "^5.3.0", "multimap": "^1.1.0", diff --git a/repl/src/parse.ts b/repl/src/parse.ts index 6564eb96..02b6ba8e 100644 --- a/repl/src/parse.ts +++ b/repl/src/parse.ts @@ -3,6 +3,7 @@ import * as strudel from '../../strudel.mjs'; import { Scale, Note, Interval } from '@tonaljs/tonal'; import './tone'; import './midi'; +import './voicings'; import * as toneStuff from './tone'; import shapeshifter from './shapeshifter'; diff --git a/repl/src/voicings.ts b/repl/src/voicings.ts new file mode 100644 index 00000000..9aca4cfa --- /dev/null +++ b/repl/src/voicings.ts @@ -0,0 +1,28 @@ +import { Pattern as _Pattern, stack, TimeSpan, Hap } from '../../strudel.mjs'; +import voicings from 'chord-voicings'; +const { dictionaryVoicing, minTopNoteDiff, lefthand } = voicings; + +const getVoicing = (chord, lastVoicing, range = ['F3', 'A4']) => + dictionaryVoicing({ + chord, + dictionary: lefthand, + range, + picker: minTopNoteDiff, + lastVoicing, + }); + +const Pattern = _Pattern as any; + +Pattern.prototype.voicings = function (range = ['F3', 'A4']) { + let lastVoicing; + return new Pattern((span) => + this.query(span) + .map((event) => { + lastVoicing = getVoicing(event.value, lastVoicing, range); + return stack(...lastVoicing) + .query(span) + .map((hap) => new Hap(event.whole, event.part, hap.value)); + }) + .flat() + ); +};