Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Microtuning? #12

Open
unremarkablegarden opened this issue Jun 29, 2021 · 10 comments
Open

Microtuning? #12

unremarkablegarden opened this issue Jun 29, 2021 · 10 comments
Labels
enhancement New feature or request

Comments

@unremarkablegarden
Copy link

Would it be possible to implement support for microtuning?

@alcomposer
Copy link

May I suggest to go straight to scala, possibly using a library like: https://github.com/surge-synthesizer/tuning-library

@greatest-ape greatest-ape added the enhancement New feature or request label Jul 1, 2021
@greatest-ape
Copy link
Owner

greatest-ape commented Jul 1, 2021

Yes, that's an interesting idea. I think going for scl/kbm support immediately is a great idea.

A few thoughts:

  • Ideally, the master frequency parameter wouldn't have to be disabled for custom tunings. If we use the surge tuning library, we could probably use frequencyForMidiNoteScaledByMidi0 to get a frequency factor for the lowest midi note. It would then be multipled with the master frequency. Since the master frequency refers to midi note 69, this value would in turn need to be multiplied with a constant factor (8.18 / 440.0 ?).
  • We need file dialog (and/or file dropping) support in baseview/iced, which may or may not exist yet. Making it work across platforms might be time consuming.
  • We need to make sure that the surge tuning library can be reliably compiled and linked to across platforms. cxx might be the way to go. I'm not too fond of linking to C/C++ code, so porting the parts we need to Rust is an option. There isn't that much code.
  • Tunings and keyboard mapping needs to be stored in presets, either in raw or in parsed form. If they are stored in parsed form, the data representation should be independent from the one used in the surge tuning library.

Some links that could be useful:

@Woyten
Copy link

Woyten commented Jul 3, 2021

I wrote a library with full SCL and KBM support. Please try it out: https://github.com/Woyten/tune 😃

@Woyten
Copy link

Woyten commented Jul 3, 2021

@alcomposer If you are interested in Rust microtunings in general, have a look at my list: https://github.com/Woyten/microtonal-rust

@alcomposer
Copy link

It's best to target all use case at once with scala.

Which means:

  • Root key note
  • Tuning key note
  • Tuning key note Hz value

And possibly link both tuning variables, (the one in settings & in main interface).

Alternatively, have all three values on main interface? However I think for 99.9% of the time, having all tuning in a settings dialog would suffice.

We also need to think about publishing the Pitch Bend value (up/down). With the Surge scala lib pitch bend is integrated at a very low level.

@Andreya-Autumn
Copy link

Hello! :)

Yes, you'll need an import option, that's true. But I don't know if you need to save tunings with patches. By far the most common use case is to have patches tuning-agnostic and load tunings specifically per project. So I'd say best practice is to make tuning independent from patch loading. Imagine trying out different patches, and having to load the scl for the current project over and over? Not good. :)

You could make it optional to save tunings with patches, for the occassional patch that's been designed around a particular tuning. That is a thing, so it's a nice thing to do. Surge does that. But it's not first order of business.

A master pitch param can certainly be combined with the Surge tuning library. Binding to frequencyForMidiNoteScaledBy0 and making your master pitch create offsets from there seems like the right idea. Keep in mind that Scl/kbm files can change both the reference frequency and which MIDI note the reference frequency refers to. So you can't assume MIDI note 69 = 440 as your fixed point of reference. Looking at master_frequency.rs, it seems like you do, so I believe some refactoring might be necessary to make it work.

You could look at how it's implemented in Surge, but there's some additional complexity there since we allow the user to choose between two pitch modulation behaviors, and also all our pitch sliders have an absolute mode (for linear Hz offsets instead of log2 hz offsets), which makes things a lot more involved: https://github.com/surge-synthesizer/surge/blob/19dec72044b6858db52d8c838b547a05c20d4e7f/src/common/dsp/SurgeVoice.h#L111

You're very welcome to come by the Surge Synth Team Discord server, to bounce questions like these around. The folks who authored the tuning library (not me btw!) are around and are usually always happy to help with implementation.

The library should compile/link just fine cross-platform, that's important to us. And there's at least one resident Rust afficionado aboard who could maybe advice on that front.

@Andreya-Autumn
Copy link

Another comment, on the pitch bend thing. One reason that's implemented so deeply in the tuning lib is that when you use alternate tunings, there's two different ways you can calculate pitch modulation, which have very different user-facing results.

Basically either you do (ref freqkey) + modulation, or you do ref freq(key + modulation).
In the first case, pitch bend of 2 always bends a standard equal-tempered whole tone.
In the second, pitch bend of 2 always bends two steps up in the current scale.

In the standard 12-equal case that makes no difference. But if you load an unequal scale, you get different pitch bend amounts depending on which note you played. And if you load, for example, 34 equal divisions of an octave, a pitch bend of two is much smaller than in 12-equal.

Both behaviors are good for different things. Pitch bends always landing on an in-scale note is sweet, but if you have two oscillators tuned a fifth apart, you'll want that relationship to be the same for every note.

And it can affect parameters too, not just modulation. In Surge, if you choose the in-scale behavior, setting oscillator pitch to +1 always sets it to one step up in the selected scale no matter how big or small that step is.

If you want to settle for one of the two, I think it's fair to say (ref freq*key) + modulation is the safer bet. Especially if you UI lets the user set pitch bend amounts in cents or some other fine value.

@Andreya-Autumn
Copy link

I also have to mention, there is a newer approach to microtuning software which is found here: https://github.com/ODDSound/MTS-ESP

Implementation works similarly to the Surge Tuning Library. It's minimal and cross-platform and liberally licenced.

The difference is, the older scl/kbm workflow is per-instance and fixed. This means you have to load tuning files into each instrument in a project, and the tuning effectively can't change during playback.

MTS-ESP is global and dynamic, all compatible instruments connect to a single source behind the scenes and automatically retune themselves as specified by the source. This saves us the repetitive work of loading scale files over and over. And also, the tuning can change during playback, which is enormously useful for many microtuning scenarios.

It is my opinion that MTS-ESP is the superior solution. Its main weakness is in the (relatively niche) use case of loading different tunings at the same time in different instruments. However, many people used scl/kbm for years and built up their workflow around that, and so still prefer it.

Devs who implements both of these get the biggest kudos from the community generally.

Again, feel free to drop by the Surge server if you like. :)

@unremarkablegarden
Copy link
Author

unremarkablegarden commented Apr 24, 2023

I wrote this Python script to convert Scala to MIDI sysex... If that is at all partially useful.
Has functions for parsing Scala and converting to frequencies etc.
https://github.com/unremarkablegarden/scala2mts

@greatest-ape
Copy link
Owner

Thanks, that’s a lot of useful info :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants