From 0b3a8a5f657e465fa0015aba931cb48076a28178 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 11 Jul 2023 22:49:34 +0200 Subject: [PATCH] - make dictionary a control - standalone voicing function - simplify voicing control names --- packages/core/controls.mjs | 13 +++++++------ packages/tonal/tonleiter.mjs | 9 +++++++++ packages/tonal/voicings.mjs | 16 ++++++++-------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 88cf0afb..10f0dcd4 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -509,7 +509,7 @@ const generic_params = [ * @superDirtOnly */ ['octave'], - ['offset'], // TODO: what is this? not found in tidal doc + // ['ophatdecay'], // TODO: example /** @@ -574,11 +574,12 @@ const generic_params = [ // ['velocity'], ['voice'], // TODO: synth param - // voicings - ['chord'], // https://github.com/tidalcycles/strudel/issues/506 - ['voiceBelow', 'voicebelow'], // https://github.com/tidalcycles/strudel/issues/506 - ['voiceMax', 'voicemax'], // https://github.com/tidalcycles/strudel/issues/506 - ['voiceOffset', 'voiceoffset'], // https://github.com/tidalcycles/strudel/issues/506 + // voicings // https://github.com/tidalcycles/strudel/issues/506 + ['chord'], // chord to voice, like C Eb Fm7 G7. the symbols can be defined via addVoicings + ['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 + ['mode'], // below = anchor note will be removed from the voicing, useful for melody harmonization /** * Sets the level of reverb. diff --git a/packages/tonal/tonleiter.mjs b/packages/tonal/tonleiter.mjs index c628847e..d2be75ca 100644 --- a/packages/tonal/tonleiter.mjs +++ b/packages/tonal/tonleiter.mjs @@ -54,6 +54,15 @@ export const x2chroma = (x) => { } }; +export const x2midi = (x) => { + if (typeof x === 'number') { + return x; + } + if (typeof x === 'string') { + return note2midi(x); + } +}; + // duplicate: util.mjs (does not support sharp flag) export const midi2note = (midi, sharp = false) => { const oct = Math.floor(midi / 12) - 1; diff --git a/packages/tonal/voicings.mjs b/packages/tonal/voicings.mjs index 28a4c949..c40d7193 100644 --- a/packages/tonal/voicings.mjs +++ b/packages/tonal/voicings.mjs @@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th */ import { stack, register } from '@strudel.cycles/core'; -import { voiceBelow, note2midi } from './tonleiter.mjs'; +import { voiceBelow, note2midi, x2midi } from './tonleiter.mjs'; import _voicings from 'chord-voicings'; const { dictionaryVoicing, minTopNoteDiff } = _voicings.default || _voicings; // parcel module resolution fuckup @@ -136,18 +136,18 @@ export const rootNotes = register('rootNotes', function (octave, pat) { }); }); -export const voicing = register('voicing', function (dictionary, pat) { +export const voicing = register('voicing', function (pat) { return pat .fmap((value) => { - let { voiceMax: max, voiceBelow: below, voiceOffset: offset, chord, n, ...rest } = value; - let top = max || below; - top = top?.note || top || 'c5'; + // TODO: default dictionary? + let { anchor, mode, offset, chord, n, dictionary, ...rest } = value; + anchor = anchor?.note || anchor || 'c5'; if (typeof dictionary === 'string') { dictionary = voicingRegistry[dictionary]?.dictionary; } - let notes = voiceBelow(top, chord, dictionary, offset, n); - if (below) { - notes = notes.filter((n) => note2midi(n) !== note2midi(top)); + let notes = voiceBelow(anchor, chord, dictionary, offset, n); + if (mode === 'below') { + notes = notes.filter((n) => x2midi(n) !== note2midi(anchor)); } return stack(...notes) .note()