surge-synthesizer / surge

Synthesizer plug-in (previously released as Vember Audio Surge)
https://surge-synthesizer.github.io/
GNU General Public License v3.0
3.13k stars 400 forks source link

Waveshaper flex tasks #1964

Closed mkruselj closed 3 years ago

mkruselj commented 4 years ago

Here are some thoughts on how we could improve the waveshaper, after 1.7 release, possibly!

Here's the work to do to close this

K0rrid0r commented 4 years ago

I would let the multi-switch stay and add a drop down meny after the DIGI somehow (smart design change required) because host automating between the waveshapes in the multi-switch is an amazing feature.

I'm going to do a design test right now. And I will update this comment also. hold on!

mkruselj commented 4 years ago

You could still host automate things I reckon - it'd just be a visual change. I am not a fan of the behavioral change that your suggestion is introducing.

K0rrid0r commented 4 years ago

How would you go on about host automating things in a dialog list?, it is not possible any wear in surge as of now? Or I'm missing something.

baconpaul commented 4 years ago

you can host automate the filter and that shows up in a menu (as well as a switch). if we turned off the ui element you could still host automate it.

K0rrid0r commented 4 years ago

use

That waveform curve under the drive slider could maybe be turned into a inverse gain compensation button, at least be used for something for saving space.

And while one is at it, also add host automation to the button.

mkruselj commented 4 years ago

That waveform curve icon has absolutely no visual clue that it would do gain compensation, so it's not a good idea. It needs to be designed properly, possibly a more elaborate skin modification.

Better suggestion: if we change the multi-switch to a menu, we have room to add a proper button with text, etc.

baconpaul commented 4 years ago

yeah making it a menu with a clear dropdown indicator is a good idea. it may also not be all that hard.

baconpaul commented 4 years ago

(gain compensation is tricky as I shared with evil on slack)

mkruselj commented 4 years ago

I mean the menu doesn't have to look like a menu, it could actually be an icon of the actual curve that is dropdownable/mousewheelable. Kinda like Osc FM/Filter config routing?

This would be far better than the multi-switch that is there now.

baconpaul commented 4 years ago

Oh yeah that's a good idea!

K0rrid0r commented 4 years ago

That indeed would be far better then the multi-switch, which indeed is limiting (kill your darlings)

viceverser commented 4 years ago

Just suggesting a possible more flexible solution to adding more wavashapers could be to make custom shapes?... https://pdesaulniers.github.io/wolf-shaper/

P.S... Evil said here was the place to post it.

magnetophon commented 3 years ago

Here's a simple but nice waveshaper from @zamaudio: https://github.com/zamaudio/zam-plugins/blob/master/plugins/ZamAutoSat/ZamAutoSatPlugin.cpp#L71

mkruselj commented 3 years ago

Another interesting thing we could try and do with the waveshaper is leveraging MSEG presets (converted to 1024 samples single cycle, as defined with waveshapers array in SurgeStorage) as waveshaper curves. We would need to have a dedicated array for this that is filled with appropriate values based on the selected MSEG preset at load time. How does that sound to you, @baconpaul? :)

baconpaul commented 3 years ago

Having a ‘custom’ waveshape per scene which is edited with a variant on the MSEG editor is a clever idea yes

magnetophon commented 3 years ago

Would a windowing function like in https://github.com/surge-synthesizer/surge/issues/3670 be feasible as a waveshaper? Probably not that implementation of it, but the general idea.

mkruselj commented 3 years ago

Windowing is not the same thing as waveshaping, AFAIK. Windowing is multiplication of the input waveform with some static function, whereas waveshaping is in-to-out remapping via a 2D transfer curve?

magnetophon commented 3 years ago

Yeah, it's def not the same thing: waveshapping is mapping, as you say, and windowing is basically multiplying the osc with an envelope that is triggered at each zero-crossing of the master osc.

I think it would be cool to have in that location in the signal path though!

baconpaul commented 3 years ago

So @mkruselj reading this issue: Seems like we are discussing putting 3 new sliders (gain, offset, hpf) here (and into the algos too). I know how to code those but before I do: Considering we aren't resizing the UI in XT 1.0 where would you put them?

Note if we develop a knob we could answer this question pretty easily. Happy to do so also.

mkruselj commented 3 years ago

@baconpaul The way I thought is just add new widget and waveshapers in XT 1.0, and add new parameters in the following release when we do the UI overhaul anyways.

baconpaul commented 3 years ago
Screen Shot 2021-07-03 at 2 01 14 PM

So OK if we are going to add more curves we need a better widget. I propose something like this mockup

Note we can also add a 'formula curve' which lets you write a transform with lua from [-10,10] -> [-1,1] as one of the curves

Of course RMB on the widget would pop up the standard menu with all the types enumerated. We could do the grouping thing if we get a lot

If we went with a graphic like that we would have 3 new PNGS (the background, the off buttons, the hover buttons) and some skin colors and properties

but is that the kind of thing we are thinking for XT 1.0? If not can we draw the kind of thing we are thinking?

Adding the shapers is easy.

mkruselj commented 3 years ago

Yeah that's pretty much how it should be, something like that. I think LMB should bring up the context menu, though.

mkruselj commented 3 years ago

@baconpaul We still have XT 2.0 checkboxes here so we should probably either reopen or move to a new issue. But materially 2.0 stuff is still waveshaper flex so to me it makes sense to leave this issue open?

baconpaul commented 3 years ago

Oh I typed closes instead of addresses in the git log by accident. Reopening

baconpaul commented 3 years ago

Here's a simple but nice waveshaper from @zamaudio: https://github.com/zamaudio/zam-plugins/blob/master/plugins/ZamAutoSat/ZamAutoSatPlugin.cpp#L71

Just reading this thread, that one is 2 |x| - 1, which independent of that code, I implemented in the rectifier section a bit ago :)

mkruselj commented 3 years ago

@baconpaul We forgot to add OJD waveshaper!!!

zamaudio commented 3 years ago

@baconpaul Are you sure? It's 2x - x |x|

baconpaul commented 3 years ago

@baconpaul Are you sure? It's 2x - x |x|

Oh right! I misread. Well I can add that also easily

baconpaul commented 3 years ago

OK added OJD and ZamAudio Saturator to the saturation section. The Zam one is like a warmer soft. The OJD is just cool.

mkruselj commented 3 years ago

@baconpaul Waveshapers to be used in distortion/rotary:

That's all.

mkruselj commented 3 years ago

UI-wise:

Example design for dark skin (classic would be pretty much the same, just different colors):

image

baconpaul commented 3 years ago

There’s some real technical problems with this plan in that it would be the first time we have 2 widgets bound to one parameter. So it basically implies a total rewrite of the sge data structures which I would sooner not do for xt1. But if I make the label and the display a single widget I can do it. The jog and preview are not parameter modifiers so they can indeed be handled specially

mkruselj commented 3 years ago

Darn it. I basically thought it'd be better to avoid situations like LFO display where there's too many things in a single widget, which puts some pretty bad constraints on skinability.

baconpaul commented 3 years ago

Yeah the basic rule of thumb is "anything which shows a value (as opposed to an action) has to be 1:1 widget to parameter right now".

The three places this come up which would need fixing are

  1. The skin engine assumes each parameter binds to one and only one connector. So SurgePatch needs to go to a vector of connectors and
  2. When things are created they are added to a 'IControlThingy * params[i]` array so that automation can find the widget to repaint. That would need to be vector valued. And then
  3. With those changes in place you need to change the skin creation loop from "for each param" to "for each param / for each subordinate widget"

big change

Actions which don't show display are different. They can use current scene and bodge it with custom code in SGEVC and a custom tag. Not ideal but we can do it.