SynthstromAudible / DelugeFirmware

https://synthstromaudible.github.io/DelugeFirmware/
GNU General Public License v3.0
568 stars 98 forks source link

Alternate Tunings #25

Open dctucker opened 1 year ago

dctucker commented 1 year ago

Description

Some synths and electronic pianos have the ability to add user-defined scales that differ from 12-tone equal temperament (12TET). This is usually enabled by allowing the user to set an offset (in cents) for each of the twelve notes in an octave (N = 12), and additionally by sending SysEx messages to the instrument.

I suspect I'll mostly be taking the lead on implementing this, but feedback/advice is welcome.

Incorporating some of the feedback received, the acceptance criteria section has been updated.

Acceptance criteria

Stretch goals

Open questions

Examples

N = 12

Root note is C, offsets follow Pythagorean tuning.

Key Value
Root Note C
C +0.00
C# -9.78
D +3.91
D# -5.87
E +7.82
F -1.96
F# +11.73
G +1.96
G# -7.82
A +5.87
A# -3.91
B +9.78

When "Root Note" is changed, the note names in the left columns will rotate (e.g. D becomes 0.00, D# becomes -9.78 and so on), and the pitch adjustment will occur on the specified notes.

N != 12

For the case of N != 12 the note names will need to change. We could represent the note's name as a numerical index, or by the assigned MIDI note name (e.g. B 3, C 4, C#4, etc).

Long-term, this may grow to feel like a Scala file editor with the ability to input ratios as well as cent offsets.

dctucker commented 1 year ago

Menu structure

*Naming is hard :tm:... possible names for A440:

bfredl commented 1 year ago

Great ideas!

One thing I would add is to consider scales with more (or less) than 12 notes per octave. Even if not added to the initial goals this could be considered when designing the solution as to facilitate it as a later add on (without needing to fundamentally rework the pitch handling code once more).

samcar17 commented 1 year ago

LOVE that this is on the cards!! Forgive me if this was mentioned and I missed it, but I think Scala support would be a big requirement for a lot of people - already a big part of a lot of people's workflows etc... Plus it also allows people to use Khyam Allami's incredible Leimma tool to create tunings and then load from SD onto the Deluge.

"Microtuning" features are very important but also hard to get right. I'm gonna post a bunch of resources here for consideration, cos I've been reading about this a fair bit lately. Bear in mind that, while a lot of folks often think of microtuning as an esoteric feature for experimental users, it's actually a vital feature for anyone wanting to make music that's not based on western music of the last ~100 years (which is to say, a massive chunk of the world). That's not said to be discouraging, btw, but to emphasize that a thoughtful implementation that is able to acknowledge and reckon with the cultural and historical aspects of tuning systems has the potential to be a real game-changer. Tbh it might be worth reaching out to Khyam to chat about it - iirc his PhD was on this exact issue and he's got a lot of v good thoughts on it. Anyway, here's some great reading material to start with:

Ableton's implementation and the issues with it: https://cdm.link/2022/03/ableton-releases-free-microtuner-but-tuning-is-more-than-spaces-between-12-semitones/

Interesting interview: https://cdm.link/2021/03/escaping-tunings-restrictive-default-setting-a-conversation-with-khyam-allami/

Great Khyam Allami essay: https://www.ctm-festival.de/magazine/microtonality-and-the-struggle-for-fretlessness-in-the-digital-age

Leimma: https://isartum.net/leimma

The Surge Team's implementation: https://surge-synth-team.org/tuning-library/

If it's not clear already (lol), I'd love to be a part of this (and care a LOT about this one) but am currently traveling and away from my Deluge til August-ish. Hopefully once I'm reunited with it I can contribute something more technical but until then I'll be watching this thread with much excitement ❤

jamiefaye commented 1 year ago

Rohan has been interested in this sort of thing lately.

I am impressed by the quality of this issue description. An exemplar.

– Jamie

On Thu, Jun 8, 2023 at 5:09 AM samcar17 @.***> wrote:

LOVE that this is on the cards!! Forgive me if this was mentioned and I missed it, but I think Scala support would be a big requirement for a lot of people - already a big part of a lot of people's workflows etc... Plus it also allows people to use Khyam Allami's incredible Leimma https://isartum.net/leimma tool to create tunings and then load from SD onto the Deluge.

"Microtuning" features are very important but also hard to get right. I'm gonna post a bunch of resources here for consideration, cos I've been reading about this a fair bit lately. Bear in mind that, while a lot of folks folks often think of microtuning as an esoteric feature for experimental users, it's actually a vital feature for anyone wanting to make music that's not based on western music of the last ~100 years (which is to say, a massive chunk of the world). That's not said to be discouraging, btw, but to emphasize that a thoughtful implementation that is able to acknowledge and reckon with the cultural and historical aspects of tuning systems has the potential to be a real game-changer. Tbh it might be worth reaching out to Khyam to chat about it - iirc his PhD was on this exact issue and he's got a lot of v good thoughts on it. Anyway, here's some great reading material to start with:

Ableton's implementation and the issues with it: https://cdm.link/2022/03/ableton-releases-free-microtuner-but-tuning-is-more-than-spaces-between-12-semitones/

Interesting interview: https://cdm.link/2021/03/escaping-tunings-restrictive-default-setting-a-conversation-with-khyam-allami/

Great Khyam Allami essay: https://www.ctm-festival.de/magazine/microtonality-and-the-struggle-for-fretlessness-in-the-digital-age

Leimma: https://isartum.net/leimma

The Surge Team's implementation: https://surge-synth-team.org/tuning-library/

If it's not clear already (lol), I'd love to be a part of this (and care a LOT about this one) but am currently traveling and away from my Deluge til August-ish. Hopefully once I'm reunited with it I can contribute something more technical but until then I'll be watching this thread with much excitement ❤

— Reply to this email directly, view it on GitHub https://github.com/SynthstromAudible/DelugeFirmware/issues/25#issuecomment-1582286817, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACDOGKWM7GJDWZPIGNQGS6DXKGQEJANCNFSM6AAAAAAY6QNYUE . You are receiving this because you are subscribed to this thread.Message ID: @.***>

dctucker commented 1 year ago

One thing I would add is to consider scales with more (or less) than 12 notes per octave. Even if not added to the initial goals this could be considered when designing the solution as to facilitate it as a later add on (without needing to fundamentally rework the pitch handling code once more).

This feature would fall beyond scope of this issue, but there should be some discussion as to how this would be implemented. Currently, the internal synthesizer engine currently uses two lookup tables with 12 entries each (one entry for each note in the octave) and uses bit-shifting to divide the frequency down to the desired octave range. To enable tuning the full keyboard range, larger lookup tables will need to be used — one entry for each note in range (as many as 128 entries). This will also imply heavier modification of the pitch assignment code that deals with phase increments in the critical section. In the interest of minimizing the initial scope of changes as well as the risk of affecting runtime performance, I will begin looking at adding larger tables once the initially proposed functionality can be validated.

To facilitate configuration, changes to the menu structure may be needed, since having the user scrolling through over 100 notes and tuning them individually would probably be only slightly more convenient than manually tuning an acoustic piano. Some synths allow overriding of the pitch key-follow in the mod matrix, which works well for evenly-spaced tunings such as 19EDO, but may fall short for irregular octave divisions. I will be thinking about this.

"Microtuning" features are very important but also hard to get right.

Truth! Thank you for linking these materials. I'm mostly operating based on prior experience implementing this feature in my own soft-synth and in commercially available analog synths, so the additional perspective is appreciated.

While I do think there's much more Ableton could have done to provide a rich interface to their microtuning feature, I'm concerned that attempting to capture the nuances of every musical tradition entirely within the Deluge's minimalist interface could be considerably more difficult to achieve, even more so when considering 7SEG. Either way, full MTS SysEx message handling (e.g. adding KEY-BASED TUNING DUMP, SINGLE NOTE TUNING CHANGE) and Scala file import would likely meet the need for more advanced tuning configuration, since this would enable interoperability with tools that provide greater cultural context such as Leimma.

All that said, I do think the stretch goal of "Persist tuning banks to SD card to enable sharing between songs" should be more heavily prioritized. Regarding the Surge Team's implementation, I have a couple of concerns. First is licensing. GPL3 and MIT should be compatible, so using the library directly should be fine (legal advice is welcome). Second and more top-of-mind is whether it can be used verbatim. The Deluge firmware doesn't seem to use cstdlib other than referencing std::abs in a few places, strings and file streaming are both implemented from scratch, and floating-point calculations are more expensive.

samcar17 commented 1 year ago

As much as I think tunings with more/less than 12 divisions of the octave are just as important as every other tuning, from a technical perspective I can see the benefit in starting with 12 note tunings.

Yeah, I think MTS + Scala support seems like it gets a good chunk of the way there. You're very right that the Deluge interface itself probably won't allow for a lot of cultural nuances, but in combination with other tools/importing I think there's a good system in there somewhere.

Re: the Surge implementation, I think it's more interesting as a design example, rather than using their code. I haven't had a good chance to really dig into the Deluge code yet, so correct me if I'm wrong, but my assumption is that there'll be a fair bit of rolling our own libraries needed haha.

Very into to tuning banks on the SD card!

One question I have is whether tunings should be per-synth/track instead of per song? I think this might actually already be in your "Stretch Goals" section, so I'm wondering if there's a reason for not building with this in mind from the outset?

rohanhill commented 1 year ago

Thanks @dctucker for posting the idea, and everyone else for contributing thoughts too!

By complete coincidence, I had begun working on microtonal tunings for the Deluge several months ago! I got it working experimentally, even with some level of basic support for scales that had a non-12 number of notes.

I had even run up against those same two "open questions" - should scales be able to persist beyond a single song, and what about the fact that there's no song-level menu.

The code is in a completely unfinished state, but I'll dust it off and share it as a branch within the next day or so! It'd be great to see the community help flesh out this exciting and much needed feature!

bfredl commented 1 year ago

Some synths allow overriding of the pitch key-follow in the mod matrix, which works well for evenly-spaced tunings such as 19EDO, but may fall short for irregular octave divisions. I will be thinking about this.

The mod matrix EDO trick is definitely possible, just need more parameter resolution: #17

dctucker commented 1 year ago

I think this might actually already be in your "Stretch Goals" section, so I'm wondering if there's a reason for not building with this in mind from the outset?

A few reasons.

For me it mostly boils down to minimizing the scope of changes. I'm new to this project, and I realize there's a good deal of trust and coordination involved in accepting contributions, and fewer changes means code review is easier and we can have greater confidence that nothing gets broken along the way. Time is my most valuable asset, and I'm still discovering where things live since the code has been publicly available for less than a week 😆.

I also find that incremental progress is easier to achieve than a fully featured implementation, especially in an established codebase, and once it's working at the one level (song), it should become clearer how to get it working for lower levels (instrument). I could have decided to focus on the lower level first, but then the user must apply the tuning individually each time a new track is added, and while some musicians may wish to do this, I haven't found per-instrument tuning as useful when using my other synths that make this feature available as simply applying a tuning at a global level.

I'm glad folks are excited about this, and @rohanhill I'm looking forward to seeing your implementation.

rohanhill commented 1 year ago

Alright, my code's up! Check the "microtuning" branch.

This is only the barest beginning of an implementation. I don't have plans to contribute much more to it, which is why it's awesome to be able to share the code with everybody else who might like to!

To use the feature, you can start by entering a new song-level menu from song view by pressing the select encoder. There, you can set the global tuning (change it from A=440hz!) and also change the number of "semitones" in the "temperament". You'll need to restart playback to hear any change.

That last part is very errr temperamental and possibly shouldn't even be an exposed option at all due to all the things it will break, including:

And to sharpen or flatten a particular "semitone" (you don't need to do anything in the new song-level menu first if you don't want to), go into clip view, get out of "SCALE" mode, then hold down an audition pad, hold down the select encoder, then turn it. You'll see a popup indicaing the new number of cents by which that semitone is flattened of sharpened - and you'll need to re-press the audition pad to hear the new adjusted pitch.

sichtbeton commented 1 year ago

wouldn't it be good to convert this to a draft PR? Just for cleaning up the issues tab more...

Lugaseurop commented 1 year ago

Hi all - Thank you for all your work on this. This is a feature I've been very very excited for. My experience of coding is very limited so sorry! I just wanted to ask - to what extent would implementing these features exclusively to CV out bypass some of the issues created by the transpose and speed issues? It would be amazing to have the full feature realised eventually but I know that having the ability to load Scala files and use that when sending CV signals out would be an incredible feature in itself. Thanks in advance

KyleKirkpatrick commented 10 months ago

Reading through this, I think there is a bit of an oversight: There is no reason to assume a given tuning system uses octaves.

So far the discussion is based around dividing an octave into different intervals... either a certain number of tones of equal temperament or an unequal division of the octave by specifying a number of unequal intervals. But the base assumption that there will be an octave to divide up is limiting and prevents the use of many potential tunings, including historical ones.

Suppose a tuning system based around the just intonated interval of a Major 3rd (5/4 ratio) where we really want to have correctly-tuned major thirds repeating throughout the range of the tuning system. A just intonated Major 3rd would be approx 386 cents in 12-TET-based tuning. So stacks of just intonated Major 3rds would not equal an octave, and there would be no symmetry in this tuning that relates to the octave. You could not specify such a tuning system in relation to an octave.

There are two approaches that could facilitate this.

  1. (already mentioned) have an exhaustive table of all notes and allow the user to specify pitches in frequencies or cents.

  2. (not metioned, I think) Specify a base interval and a number of divisions of that base interval. 12 tone equal temperament would have a base interval of 2/1 (octave) and 12 equal divisions of that base interval. Pythagorean tuning would also use a base interval of 2/1 (octave), but you would need to specify unequal values for each division of the base interval (in cents: 0, 113.7, 203.9, 294.1, 407.8, 611.7, 702, 792.2, 905.9, 996.1, 1109.8, 1200). My hypothetical just-intonated Major 3rd based tuning would use a base interval of 5/4 and have n-divisions of that 3rd which would ensure that the Major 3rd interval is perfect throughout the note range, and the in-between notes would be specified in relation to that repeating 3rd interval.

Rohan's implementation is awesome in that it enables alternate equal temperaments like 19-TET or 31-TET. Seems it enables other octave-based tuning systems like Pythagorean. But it doesn't allow non-octave-based tunings.

As an aside, I find this as an invaluable resource for wrapping your head around just intonation and alternate tunings: https://www.kylegann.com/microtonality.html