mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 13:48:34 +00:00
add octaves control for arpeggios
This commit is contained in:
parent
d231ded7a2
commit
52b8d9d361
@ -579,6 +579,7 @@ const generic_params = [
|
||||
['dictionary', 'dict'], // which dictionary to use for the voicings
|
||||
['anchor'], // the top note to align the voicing to, defaults to c5
|
||||
['offset'], // how the voicing is offset from the anchored position
|
||||
['octaves'], // how many octaves are voicing steps spread apart, defaults to 1
|
||||
[['mode', 'anchor']], // below = anchor note will be removed from the voicing, useful for melody harmonization
|
||||
|
||||
/**
|
||||
|
||||
@ -76,11 +76,11 @@ export const midi2note = (midi, sharp = false) => {
|
||||
return pc + oct;
|
||||
};
|
||||
|
||||
export function scaleStep(notes, offset) {
|
||||
export function scaleStep(notes, offset, octaves = 1) {
|
||||
notes = notes.map((note) => (typeof note === 'string' ? noteToMidi(note) : note));
|
||||
const octOffset = Math.floor(offset / notes.length) * 12;
|
||||
offset = _mod(offset, 12);
|
||||
return notes[offset % notes.length] + octOffset;
|
||||
const octOffset = Math.floor(offset / notes.length) * octaves * 12;
|
||||
offset = _mod(offset, notes.length);
|
||||
return notes[offset] + octOffset;
|
||||
}
|
||||
|
||||
// different ways to resolve the note to compare the anchor to (see renderVoicing)
|
||||
@ -90,7 +90,7 @@ let modeTarget = {
|
||||
above: (v) => v[0],
|
||||
};
|
||||
|
||||
export function renderVoicing({ chord, dictionary, offset = 0, n, mode = 'below', anchor = 'c5' }) {
|
||||
export function renderVoicing({ chord, dictionary, offset = 0, n, mode = 'below', anchor = 'c5', octaves = 1 }) {
|
||||
const [root, symbol] = tokenizeChord(chord);
|
||||
const rootChroma = pc2chroma(root);
|
||||
anchor = anchor?.note || anchor;
|
||||
@ -124,7 +124,7 @@ export function renderVoicing({ chord, dictionary, offset = 0, n, mode = 'below'
|
||||
notes = notes.filter((_, i) => voicingMidi[i] !== noteToMidi(anchor));
|
||||
}
|
||||
if (n !== undefined) {
|
||||
return [scaleStep(notes, n)];
|
||||
return [scaleStep(notes, n, octaves)];
|
||||
}
|
||||
return notes;
|
||||
}
|
||||
|
||||
@ -196,10 +196,10 @@ export const voicing = register('voicing', function (pat) {
|
||||
.fmap((value) => {
|
||||
// destructure voicing controls out
|
||||
value = typeof value === 'string' ? { chord: value } : value;
|
||||
let { dictionary = 'default', chord, anchor, offset, mode, n, ...rest } = value;
|
||||
let { dictionary = 'default', chord, anchor, offset, mode, n, octaves, ...rest } = value;
|
||||
dictionary =
|
||||
typeof dictionary === 'string' ? voicingRegistry[dictionary] : { dictionary, mode: 'below', anchor: 'c5' };
|
||||
let notes = renderVoicing({ ...dictionary, chord, anchor, offset, mode, n });
|
||||
let notes = renderVoicing({ ...dictionary, chord, anchor, offset, mode, n, octaves });
|
||||
|
||||
return stack(...notes)
|
||||
.note()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user