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

Surge-AU: GUI-less Parameter changing on macOS #66

Closed
17 of 68 tasks
esaruoho opened this issue Dec 12, 2018 · 10 comments
Closed
17 of 68 tasks

Surge-AU: GUI-less Parameter changing on macOS #66

esaruoho opened this issue Dec 12, 2018 · 10 comments

Comments

@esaruoho
Copy link
Collaborator

now that @baconpaul got the AudioUnit running, I spent a bit of time yesterday fooling around with the GUI-less Surge.

after loading VmbA > Surge and trying to move some sliders, I'm getting no effect on the audio by moving the following:

screenshot_12_12_2018__9_00

so Macro Parameters and Global / FX parameters do not seem to affect the sound.
Maybe this is a case of needing the UI to enable something, but there's a start.

Luckily, Logic Pro X lets me hide these two chunks of nonfunctional sliders, after which I'm presented with:

screenshot_12_12_2018__9_02

Now, these are more responsive. The following work

Scene A Common:

  • Pitch
  • Portamento
  • FM Depth
  • Noise Color
  • Volume
  • Pan
  • Width
  • FX1 Send
  • FX2 Send
  • Gain
  • Feedback
  • Filter Balance
  • High Pass
  • Waveshaper Drive

Scene A Osc:

  • Osc1 Pitch
  • Osc1 Shape
  • Osc1 Width
  • Osc1 Sub Width
  • Osc1 Sub Level
  • Osc1 Sync
  • Osc1 Uni Spread
  • Osc2 Pitch
  • Osc2 Shape
  • Osc2 Width
  • Osc2 Sub Width
  • Osc2 Sub Level
  • Osc2 Sync
  • Osc2 Uni Spread
  • Osc3 Pitch
  • Osc3 Shape
  • Osc3 Width
  • Osc3 Sub Width
  • Osc3 Sub Level
  • Osc3 Sync
  • Osc3 Uni Spread

.. That's one page more page down, more to go..

screenshot_12_12_2018__9_07

Out of these, a couple work:
Scene A Osc Mixer

  • Osc1 Level
  • Osc2 Level
  • Osc3 Level
  • Ring Level 1x2
  • Ring Level 2x3
  • Noise Level
  • Pre-Filter Gain

Scene A Filters:

  • F1 Cutoff
  • F1 Resonance
  • F1 Envmod
  • F2 Cutoff
  • F2 Resonance
  • F2 Envmod

Scene A Envelopes:

  • AEG Attack
  • AEG Decay
  • AEG Sustain
  • AEG Release
  • FEG Attack
  • FEG Decay
  • FEG Sustain
  • FEG Release

Scene A LFOs

  • LFO1 Rate
  • LFO1 Magnitude
  • LFO2 Rate
  • LFO2 Magnitude
  • LFO3 Rate
  • LFO3 Magnitude
  • LFO4 Rate
  • LFO4 Magnitude
  • LFO5 Rate
  • LFO5 Magnitude
  • LFO6 Rate
  • LFO6 Magnitude

and after that, we're left with these guys:
screenshot_12_12_2018__9_13

Looks like "Scene B" is MIA/DOA or needs some sort of button to enable.

Looking at these results, we're definitely on the way, but maybe there's something that needs to be toggled ON, for Filters, LFO, FX, Filter Envelopes, OSC2 & OSC3 to work.

Your thoughts, @kurasu ? Do most of these need to be "toggled ON" to work?

For the sake of my own memory, this is what Surge looks like:
kvr__surge_by_vember_audio_-_synth__hybrid__vst_plugin__audio_units_plugin_and_vst_3_plugin

@esaruoho
Copy link
Collaborator Author

And.. just in case the tickboxes get ticked by someone, or otherwise mutilated, on the 12th of December 2018 at 9.18am Finnish time (GMT+2), these worked:

Scene A Common
Pitch
Portamento
Volume
Pan
High Pass

Scene A Osc
Osc1 Pitch
Osc1 Shape
Osc1 Width
Osc1 Sub Width
Osc1 Sub Level
Osc1 Sync

Scene A Osc Mixer
Osc1 Level
Pre-Filter Gain


Scene A Envelopes
AEG Attack

AEG Decay
AEG Sustain
AEG Release

@baconpaul
Copy link
Collaborator

I had noticed scene b was empty also but I had never used surge when it was a commercial product so didn’t know how to read that. This is remarkably useful info!

I have a pretty good debug and log workflow in logic right now with my (flailing) work to get the ui rendering in a 64 bit nsview. But at least I can see a message right before I segv!! Perhaps I can find some time to bring that over to another branch looking at param flow to see if it helps.

I do know when I run auval on dexed it enumerates all the parameters and when I run it on surge it does not so I am assuming the port is not complete. Good to have that so clearly validated!

@baconpaul
Copy link
Collaborator

OK I did some instrumentation and the ones you indicate are actually sending changes to the host.

I'll compare AU host and VST host code sometime this week, but I do notice this comment in the code right after the moment where the parameter is passed on

	plugin_instance->setParameter01(plugin_instance->remapExternalApiToInternalId(inID),inValue,true);
	// TODO lägg till signalering från här -> editor om den är öppen
	// glöm inte att mappa om parametrarna ifall det är ableton live som är host
	// EDIT gör det hellre med en threadsafe buffer i sub3_synth

That's Finnish? Swedish? I apologize for speaking neither. Do you happen to know what that text means?

@esaruoho
Copy link
Collaborator Author

@baconpaul definitely Swedish. Google translate says:

TODO add signaling from here -> editor if it is open
// do not forget to mapping the parameters if it is ableton live as a host
// EDIT does it rather with a threadsafe buffer in sub3_synth

@baconpaul
Copy link
Collaborator

Thanks! That’s about as helpful as the original Swedish! Chuckle.

I have a theory on why all of scene b is empty. In the original surge were a and b just copies of most things which you could merge? I wonder if there is a name unique thing going on

Anyway I’m away from my computer for the rest of the day but I will dig around!

Fun software archaeology here! Good stuff

@baconpaul
Copy link
Collaborator

Breadcrumb recording.

Well my theories are mostly wrong. I'm having a super hard time figuring out the path between SurgeSynthesizer::setParameter01 and anything in the src/dsp land which is actually called at render time and it's almost impossible to attach a debugger to logic. I sort of feel like I need a command line version of an au-host-equivalent which does the various manipulations outside of an AU context.

Do we know if there's any documentation on the internal structure of the synth? I sort of feel like even a high level map of what's going on would be helpful. Maybe we should start MapToCode.md where we can put notes as we discover it.

But short version: I can replicate your problem, but I can also confirm that it is not a problem in the AU layer (at least for the filter cutoff). That generates a control change which gets passed to the synth.

The only thing I could think of is the problem is related to the Scene B. I did confirm that most parameters appear twice, presumably for Scene A and Scene B. For instance "F1 Resonance" appears with ID 201 and 472. Wiggling the knob adjusts 201 and I confirmed that 201 is also the one mapping to the Scene A clump. So for some reason calling setParameter01 with id 201 does not adjust the active resonance and I'm honestly not sure why yet.

@baconpaul
Copy link
Collaborator

OK some more breadcrumbs in case others want to read the code and try. Or in case I forget.

Here's the basic class structure I see in SurgeSynthesizer.

SurgeSynthesizer hasa SurgeStorage has a reference to SurgePatch

SurgePatch is a typed bundle of Parameters

A Parameter is basically a name, a value (which is a union of float bool and int) and some information about the control.

When in the AU you do a wiggle of a slider, it calls auval::SetParameter which calls SurgeSynthesizer::setParameter01 with an index.

That calls storage.getPatch().param_ptr[ index ]->set_value_f01

and that means the in memory parameter has the value from the slider. Then that's all that happens.

For a parameter like "F1 Resonance", the constructor for SurgePatch sets it up with code like this from SurgePatch.cpp

        a->push_back(scene[sc].filterunit[f].resonance.assign(
             p_id++, id_s++, "resonance", "Resonance", ct_percent, px, py, sc_id, cg_FILTER, f,

which initializes the SurgePath method scene[sc].filterunit[f].resonance to have an ID and name and so on (basically .assign takes the arguments which are akin to a Parameter constructor).

Now separately when you call ::process which actually renders the audio it traverses the DSP graph to basically do the synthesis. This renders using the SurgeVoice class. The SurgeVoice class has a copy of the Parameter pointers (called 'localcopy') and the constructor of a Voice goes and grabs the id from the patch. For instance in SurgeVoice.cpp

   id_resoa = scene->filterunit[0].resonance.param_id_in_scene;

then when the voice wants to understand the value of resonance the voice it just reads it off of the param, like the following from the filter block handler in SurgeVoice.cpp

      CM[0].MakeCoeffs(cutoffA, localcopy[id_resoa].f, scene->filterunit[0].type.val.i,
                       scene->filterunit[0].subtype.val.i);

which is reading the parameter value f.

Using "careful debugging" (printf) I see that right before that line the value of the resonance of the filter is being changed when I wiggle. So everything is plumbed through. For some other reason the filter is not being applied. From looking at the code after that, around 790 of SurgeVoice, perhaps the scene filterunilt type isn't being set properly, which would match the idea of us only having continuous controls and not having dropdown. I haven't found where that scene->filter unit[].type is set quite yet, but it just looks like a parameter so I'm sure it is traceable.

None of this explains why we don't see the scene B stuff. I really do think that's due to repeated names.

@baconpaul
Copy link
Collaborator

OK and finally I figured this out and learned a lot doing so.

Basically the filter.unit.type has a parameter (called, unsurprisingly, F1 Type) which has a constrained set of values. But the slider for this doesn't show up. The reason the slider doesn't show up is because the parameter is an "expert" parameter. Line 646 or so of aulayer.cpp surpasses the expert parameters from the ui by setting kAudioUnitParameterFlag_ExpertMode.

Now you can comment this out and get every parameter editable. But the cocoa UI is unusable. It just doesn't scale to the 700 odd parameters in Surge. Like pegged my decent quality MacBook.

But if I put in a special hack to turn on F2 Type (which is ID 204) I can edit that, and then the filter resonance works.

So I think the upshot of this is: The sliders depend on state which is not editable and which is defaulted to zero. As such they won't work unless you can uncover that state. And to do that you need a full UI, which we don't have.

Oh and also, every single scene b parameter is tagged "expert" which is why the whole thing doesn't show up.

Useful to know. But not really something which is we can "fix" without, well, getting the UI working on the tool! So back to that I guess!

@esaruoho
Copy link
Collaborator Author

Fixed by #69 - by testing with this branch, you can see that @baconpaul got the parameters working wonderfully. I don't feel I need to use the non-gui version of Surge at all to be honest.

@esaruoho
Copy link
Collaborator Author

Closed by #92

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

No branches or pull requests

2 participants