docs + rename under -> duck, quak quak
This commit is contained in:
parent
3d8724c90d
commit
e05f74cef1
7 changed files with 340 additions and 247 deletions
|
|
@ -127,18 +127,18 @@ export const scaleTranspose = register('scaleTranspose', function (offset /* : n
|
|||
*
|
||||
* The root note defaults to octave 3, if no octave number is given.
|
||||
*
|
||||
* @memberof Pattern
|
||||
* @name scale
|
||||
* @param {string} scale Name of scale
|
||||
* @returns Pattern
|
||||
* @example
|
||||
* "0 2 4 6 4 2".scale("C2:major").note()
|
||||
* n("0 2 4 6 4 2").scale("C:major")
|
||||
* @example
|
||||
* "0 2 4 6 4 2"
|
||||
* .scale("C2:<major minor>")
|
||||
* .note()
|
||||
* n("[0,7] 4 [2,7] 4")
|
||||
* .scale("C:<major minor>/2")
|
||||
* .s("piano")
|
||||
* @example
|
||||
* "0 1 2 3 4 5 6 7".rev().scale("C2:<major minor>").note()
|
||||
* n(rand.range(0,12).segment(8).round())
|
||||
* .scale("C:ritusen")
|
||||
* .s("folkharp")
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ export function scaleStep(notes, offset) {
|
|||
// different ways to resolve the note to compare the anchor to (see renderVoicing)
|
||||
let modeTarget = {
|
||||
below: (v) => v.slice(-1)[0],
|
||||
under: (v) => v.slice(-1)[0],
|
||||
duck: (v) => v.slice(-1)[0],
|
||||
above: (v) => v[0],
|
||||
};
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ export function renderVoicing({ chord, dictionary, offset = 0, n, mode = 'below'
|
|||
if (n !== undefined) {
|
||||
return [scaleStep(notes, n)];
|
||||
}
|
||||
if (mode === 'under') {
|
||||
if (mode === 'duck') {
|
||||
notes = notes.filter((n) => x2midi(n) !== noteToMidi(anchor));
|
||||
}
|
||||
return notes;
|
||||
|
|
|
|||
|
|
@ -50,10 +50,33 @@ const triads = {
|
|||
aug: ['1P 3m 5A', '3m 5A 8P', '5A 8P 10m'],
|
||||
};
|
||||
|
||||
const defaultDictionary = {
|
||||
// triads
|
||||
'': ['1P 3M 5P', '3M 5P 8P', '5P 8P 10M'],
|
||||
M: ['1P 3M 5P', '3M 5P 8P', '5P 8P 10M'],
|
||||
m: ['1P 3m 5P', '3m 5P 8P', '5P 8P 10m'],
|
||||
o: ['1P 3m 5d', '3m 5d 8P', '5d 8P 10m'],
|
||||
aug: ['1P 3m 5A', '3m 5A 8P', '5A 8P 10m'],
|
||||
// sevenths chords
|
||||
m7: ['3m 5P 7m 9M', '7m 9M 10m 12P'],
|
||||
7: ['3M 6M 7m 9M', '7m 9M 10M 13M'],
|
||||
'^7': ['3M 5P 7M 9M', '7M 9M 10M 12P'],
|
||||
69: ['3M 5P 6A 9M'],
|
||||
m7b5: ['3m 5d 7m 8P', '7m 8P 10m 12d'],
|
||||
'7b9': ['3M 6m 7m 9m', '7m 9m 10M 13m'],
|
||||
'7b13': ['3M 6m 7m 9m', '7m 9m 10M 13m'],
|
||||
o7: ['1P 3m 5d 6M', '5d 6M 8P 10m'],
|
||||
'7#11': ['7m 9M 11A 13A'],
|
||||
'7#9': ['3M 7m 9A'],
|
||||
mM7: ['3m 5P 7M 9M', '7M 9M 10m 12P'],
|
||||
m6: ['3m 5P 6M 9M', '6M 9M 10m 12P'],
|
||||
};
|
||||
|
||||
export const voicingRegistry = {
|
||||
lefthand: { dictionary: lefthand, range: ['F3', 'A4'], mode: 'below', anchor: 'a4' },
|
||||
triads: { dictionary: triads, mode: 'below', anchor: 'a4' },
|
||||
guidetones: { dictionary: guidetones, mode: 'above', anchor: 'a4' },
|
||||
default: { dictionary: defaultDictionary, mode: 'below', anchor: 'a4' },
|
||||
};
|
||||
export const setVoicingRange = (name, range) => addVoicings(name, voicingRegistry[name].dictionary, range);
|
||||
|
||||
|
|
@ -99,6 +122,7 @@ const getVoicing = (chord, dictionaryName, lastVoicing) => {
|
|||
};
|
||||
|
||||
/**
|
||||
* DEPRECATED: still works, but it is recommended you use .voicing instead (without s).
|
||||
* Turns chord symbols into voicings, using the smoothest voice leading possible.
|
||||
* Uses [chord-voicings package](https://github.com/felixroos/chord-voicings#chord-voicings).
|
||||
*
|
||||
|
|
@ -141,13 +165,35 @@ export const rootNotes = register('rootNotes', function (octave, pat) {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Turns chord symbols into voicings. You can use the following control params:
|
||||
*
|
||||
* - `chord`: Note, followed by chord symbol, e.g. C Am G7 Bb^7
|
||||
* - `dict`: voicing dictionary to use, falls back to default dictionary
|
||||
* - `anchor`: the note that is used to align the chord
|
||||
* - `mode`: how the voicing is aligned to the anchor
|
||||
* - `below`: top note <= anchor
|
||||
* - `duck`: top note <= anchor, anchor excluded
|
||||
* - `above`: bottom note >= anchor
|
||||
* - `offset`: whole number that shifts the voicing up or down to the next voicing
|
||||
* - `n`: if set, the voicing is played like a scale. Overshooting numbers will be octaved
|
||||
*
|
||||
* All of the above controls are optional, except `chord`
|
||||
*
|
||||
* @name voicing
|
||||
* @param {string} dictionary which voicing dictionary to use.
|
||||
* @returns Pattern
|
||||
* @example
|
||||
* chord("<C Am F G>").voicing()
|
||||
* @example
|
||||
* n("0 1 2 3 4 5 6 7").chord("<C Am F G>").voicing()
|
||||
*/
|
||||
export const voicing = register('voicing', function (pat) {
|
||||
return pat
|
||||
.fmap((value) => {
|
||||
let { dictionary, ...rest } = value;
|
||||
if (typeof dictionary === 'string') {
|
||||
dictionary = voicingRegistry[dictionary];
|
||||
}
|
||||
let { dictionary = 'default', ...rest } = value;
|
||||
dictionary =
|
||||
typeof dictionary === 'string' ? voicingRegistry[dictionary] : { dictionary, mode: 'below', anchor: 'c5' };
|
||||
let notes = renderVoicing({ ...dictionary, ...rest });
|
||||
|
||||
return stack(...notes)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue