Closed mkruselj closed 1 year ago
I guess the surge equivalent of that is have a user category called “midi” and just order them alphabetically for midi program changes. Then you just save your patches with the names you want to make the order and change messages send you to that folder if it exists for traversal. Agree?
Yes. But it should def support subfolders in there (one level of subfolders only), for having more than 128 presets available there for switching.
So Surge actually does support program change now in the AU and VST. The VST3 does not.
but it's not very useful.
Code wise, right now the AU and VST2 both send the program change method and call SurgeSynthesizer::programChange
. That implementation is
void SurgeSynthesizer::programChange(char channel, int value)
{
PCH = value;
// load_patch((CC0<<7) + PCH);
patchid_queue = (CC0 << 7) + PCH;
}
CC0 is the value of channel control 0. So you can address any of the patches by direct index as "CC0 * 128 + program_change". That's an odd API since the ordering in patch id space is dependent on the order on the file system. So not super duper useful. But stable-ish.
Seems a better approach would to use the convention that CC0 selects your category in sorted order and Program Change selects your patch inside that category.
Thoughts?
Seems a better approach would to use the convention that CC0 selects your category in sorted order and Program Change selects your patch inside that category.
I think that u-he method is still much better because it is deterministic. You get to sort the patches in the exact order that you want, and this cannot be inadvertly changed during a session if you store a preset somewhere in the folder that's already being traversed via program changes (stuff is preloaded into RAM only when plugin is instantiated, cache is created, and only that cache is used).
Oh that’s interesting. I had assumed if you had a folder you were traversing with patch a b c and you saved “aa” into it your program changes would shift in uhe. Not so?
In surge seems the obvious thing to do is to have program change do an ordered traverse of current category. Then it’s up to the user to order their patches. I don’t see where else we could store information but ordered traverse of current category is way better than the current system which is basically random program assignment.
Thanks!
@mkruselj and I chatted about this on slack this morning. There's lots we can do here but for a 1.6, since the current behavior is so random, here's the concrete proposal
At a later date we want to consider adding these features
When this issue is closed add those two items as future issues
@mkruselj agree?
2./3. Just to add clarity: if CC #0 is not sent, PC will use the root of MIDI Programs folder to choose which patch to load. If CC# 0 is sent, then it picks a sorted subfolder within MIDI Programs - and in that case PC will look in that folder, not root (obviously). Sorry if stating the obvious, but to me this reads more clearly.
Agree!
Yeah on 1 surge currently creates the documents folder if it isn’t there so we can just do this at the same spot!
Agree on all the others.
Per some slack conversation this might be a good one for @rghvdberg . Tagging you over here.
This is really important, I have to say! A must, I should add... Particularly for live performances, proper program change support - as stated by Mario above - is crucial.
Does anybody know if this feature is about to be implemented anytime soon? I´m considering this instrument for a live setup...
Not planned any time soon unfortunately.
But since you're a Reaper user, you can actually store Surge presets as Reaper presets and program change those instead :)
Yes, you´re right! The only thing that Reaper misses in my opinion (although I remember that, once, you disagreed with this) is a dedicated bank per plugin instance, as found in Fm8, Absynth, etc... I´ve more than once ended up with a looong, long list of presets of many different projects, all mixed and messsed up, which is rather annoying for my taste.
Since I´m also a Bidule user, I´ll get by with it, of course. I have been streamlining during these years a live Bidule setup which allows complex changes with a single button push, so I was evaluating the most simple way to include Surge in it. Anyway, I thought it was Ok to do some lobby for the program change support cause :) . It really helps a lot to streamline live setups; I hope it can be reconsidered by the devs...
Yeah unfortunately lately the devs have not been that big a group and as @mkruselj said this one just hasn’t made the cut, since most of us have workaround like config in reaper or main stage or whatever, and we have a bunch of bugs and feature requests where there’s no way to get an approximation of the feature.
However this is a great issue for a new dev to tackle. Since Surge is entirely open source and volunteer community driven, one way you could help is - well - tell all your friends who are devs that there’s a cool and friendly open source synth project out there where a person could help us implement a fairly neat and compact feature if they know a bit of C++ and have run a virtual synth. Happy to help someone get up to speed starting here.
But barring someone showing up and making this their priority, I think it’s still going to stay mid/bottom of list for the near future since, as you point out, we have workarounds, and things like a UI skinning engine and expanding/fixing the FM section of the DSP engine don’t have alternative solutions with external tools.
Well, that´s a fair reasoning for sure! Unfortunately, the few devs I personally know won´t ever get into the synth world at all, and learning C++ at this point would burn my head entirely. Anyway, there´s this open topic here with a good bunch of replies. Maybe at some point...
OK that’s great. I figure it always helps to ask, since we really would welcome developers to the project!
I guess the surge equivalent of that is have a user category called “midi” and just order them alphabetically for midi program changes. Then you just save your patches with the names you want to make the order and change messages send you to that folder if it exists for traversal. Agree?
Surely it's a workaround, but unfortunately, this is not ideal and brings other issues for the end-user.
I think the ideal situation is to have a list of presets assigned to Program Change Messages on each instance of the synth, so every instance can have its own list.
If you look this video on youtube you will see that's how Massive works, i believe FM8 is the same.
That's a more complicated way to go about it, it seems to me.
Going the regular folder route is very similar to how u-he does it, and the great thing about it is that it's not limited to 128 presets like Massive or FM8 are, since you can subfolder patches and use Bank Select message to point to a particular subfolder, essentially supporting over 16k patches through BS+PC messages...
IMHO it's a superior method of dealing with this sort of thing.
As far as my experience goes the latest Surge version already supports way more than 128 presets and you don't need a "midi folder".. Just send Program, Sub Bank and Bank messages to scroll through hundreds and hundreds of presets.
if you're comfortable with ordering your presets alphabetically in order to don't mess the Program Number then AFAIK you don't need anything to be done other than this issue I reported yesterday: https://github.com/surge-synthesizer/surge/issues/1601
I think having a Program List is the best way, because if you use a "midi folder" and you change something then the sequence of your live performances projects will break, sequences I do on my external hardware sequencer will break, etcs.
It's not a live-ready approach to have to assign Program Change numbers to your presets by alphabetically ordering them, if you change the order by accident, then you're done..
IMHO, Ideally every instance holds it's own preset list..
Also, you can have a Program List that supports more than 128 presets...
Also, ideally, you need each instance to hold it's own program list.
The Massive/FM8/Absynth way - which is the one I´m used to -, while not as comprehensive as the U-HE system in terms of quantity of available presets, is quite useful in itself and more than enough for a lot of live situations. The main thing about this is the ability to have a dedicated custom list of user presets per instance. Be it 128 or preferably more, a list per instance is in my opinion the way to go. It´s true that the subfolder system can easily wreck things if it´s used in a global context (for example, if a live set is highly dependent on the order of the subfolders used for different projects), as hems says, but of course nothing prevents from using the subfolders´system only in the context of each song/piece. I mean, subfolders can be used exclusively to extend the available programs for each project/instance. Any implementation, though, will be far better than the current system in my opinion...
Hey folks
Like I said this one isn’t top of my list but happy for folks to work on it. Thought it might be useful to just recap what surge does now and why it is inadequate
Right now at startup surge does a directory scan for presets which ends up with the presets in basically random order. For all the displays and stuff we sort
When we get a midi program change event we basically do 127*bank + patch and then see if that number is within the range of lists of presets in the unordered list (I think; I may have changed it to use the ordered list in the past but I don’t think so). It then loads that patch
This is obviously a bad solution. If you add a patch all your banks change
From reading your comments I rather like the idea of having patches be assigned virtual banks and programs rather than having to move things in folders, but I don’t use surge in this way and my next few months of work are on other bits of the synth. But if a person showed up and implemented either that or the uhe style solution I would be happy to help them walk the change through and so on.
Hope that helps!
https://github.com/surge-synthesizer/surge/blob/da96f74b1cc96f936192282e300d93cf65d16c58/src/common/SurgeSynthesizer.cpp#L813 And there’s the spot where the id gets set. Pretty clear how to add an indirection there into whatever data structure you have (and the fact that it sets the queue Id stops surge from crashing with a memory corruption but also what creates the tuning error in #1601 I bet. Probably need to send changes before notes with at least some buffer although 1601 is a different issue obviously)
Like I said this one isn’t top of my list but happy for folks to work on it. Thought it might be useful to just recap what surge does now and why it is inadequate
Thanks for the help!
Right now at startup surge does a directory scan for presets which ends up with the presets in basically random order. For all the displays and stuff we sort
In order for the approach I'm suggesting to work I believe the following steps would be necessary for a Proof of Concept:
My CPP is super rusty ( no pun intended ) and I don't even have Surge compiling on my current Machine. I would love to try set it up and try to draft a PR for that feature as it's super essential for me.
The main challenge for me would be #4 as i'm not aware of how this works. When does the DAW ask for the state of the plugin in order to save it on the project and where is the cpp code associated with that? I would assume the DAW already stores a state that contains more than simply the current preset ( i.e. all parameters of the plugin including the preset name ).
If @baconpaul or anyone else would be able to feedback on this approach it would be a cool challenge.
Thanks a lot!
Oh sure. Let me take 10 minutes later tonight and outline how you would do those steps. The only problem is you would store presets by name since they don’t have stable id so when you restore in step 4 it would be a bit of c++
We are planning a 1.6.6 release probably weds and after that we are going to be pushing quite a few changes into the synth. It would be a good time to do this one too and I appreciate your offer to help
Out of curiosity what is your os?
Oh and I like your simple design of being able to set up one bank in a session. May also want to think about ways to display it and share it later and I have a few ideas about that I will write up too
Oh sure. Let me take 10 minutes later tonight and outline how you would do those steps. The only problem is you would store presets by name since they don’t have stable id so when you restore in step 4 it would be a bit of c++
indeed that was the idea to either store the PRESET filename relative to the PRESETS PATH as a starting point.
I think there's anther problem that would emerge which is:
Because of that, I wonder:
We are planning a 1.6.6 release probably weds and after that we are going to be pushing quite a few changes into the synth.
amazing, I'm looking forward to checking that out. I love the new-ish micro tunning stuff
It would be a good time to do this one too and I appreciate your offer to help
As I said, don't expect much from me as a CPP guy, I do know how to code and google tough so if I'm lucky I would be able to do a half-presentable PR ( :
Out of curiosity what is your os?
OSX 10.12 my Ableton is 64 bits tough!
Oh and I like your simple design of being able to set up one bank in a session. May also want to think about ways to display it and share it later and I have a few ideas about that I will write up too
I remember seeing a very simple "pop up" when editing values somewhere, so i assume this functionality is already implemented somewhere and I could just copy that?
My idea here is basically to be able to implement this feature without having to implement nothing more than the saving a list on the DAW session, everything else should be made out of things that are already implemented.
Of course, it would be nice to have a GUI for the program list and a tesla delivered to my house, but that will need a lot more work : D
Yeah that’s right. But with one easy extra idea you can get a ui for free - namely make midi bank show up as a category in the menu so you can see what’s mapped there.
Lemme get home and I will write it all up including an answer to your questions in a way which is codavle if you can google and compile. I’m more than happy for you to get it working with some edges and I can help fix them up too. I just don’t want to dedicate a couple of days of dev to it when I’m in the middle of some very exciting tuning and skinning stuff
Oh and good you are on Mac. The build tools work super well there. You are running a version of live that loads the vst3 yeah? Building the vst2 is hard
Yeah that’s right. But with one easy extra idea you can get a ui for free - namely make midi bank show up as a category in the menu so you can see what’s mapped there.
yeah very good idea!
Lemme get home and I will write it all up including an answer to your questions in a way which is codavle if you can google and compile. I’m more than happy for you to get it working with some edges and I can help fix them up too. I just don’t want to dedicate a couple of days of dev to it when I’m in the middle of some very exciting tuning and skinning stuff
great! I also would love to get it building on my computer so i can hopefully do more contributions in the future.
Oh and good you are on Mac. The build tools work super well there.
It does require xCode though which is a bit inconvenient as i'm fighting with free space in my laptop and slow wifi as i'm abroad!
I'm now "in the process" of downloading Xcode. I was hoping i woul be able to edit in VSCode and build with command-line tools, but after reading the README I think that's not the case?
I can't actually officially donwload it from App Store as they require an earlier version of the system than the one i have now.
So I'll need to look into downloading an older version or some other alternative as I'm not willing to update my system as it generally breaks my music making setup.
You are running a version of live that loads the vst3 yeah?
I'm using the AU version, Ableton introduced VST3 kinda recently, so I did not get to try it yet..
I would be willing to give it a go if I build it locally!
Building the vst2 is hard
Not necessary for me at the moment as the AU works.
Ahh yeah you need Xcode; that's the way you get the compiler even if you don't use Xcode (I use emacs myself). Hmm. There may be a way you can brew install clang but that's hard.
Well look let me write up my notes quickly and then you or me or someone else can develop of them when we get an env that works and turn to it!
Data Structure to store the preset
int midiProgramBank[128]
as a member to SurgeStorage for ( i= 0; i < 128; ++i ) midiPrgramBank[i] = -1
add an 'add to program' menu
spawn_miniedit_text
. An example of this in a menu callback is the MPE Pitchbend Menu which is in SurgeGUIEditor.cpp (just search for mpePitchBendRange
auto m = createMenu( "Add to patch bank" )
m->setAction( [this](() {
char c[256];
snprintf(c, 256, "%d", synth->mpePitchBendRange);
spawn_miniedit_text(c, 16);
int newVal = ::atoi(c);
this->storage->patchthing[newval] = /* reference to current patch id */
} );
contextMenu->add(m)
Make the program change load the patch based on this index. That's pretty clear from above. If the value of the array is -1 just do nothing.
Save and retrieve it.
If you want to indicate on the preset UI two options
Add a streaming regtest. In src/headless/UnitTestsIO there are various places where we stream and upstream a surge after setting internal state. Test this there in a new test case
And that's the project complete!
Like I said if you can't install Xcode you probably won't be able to do this but I figured the notes were useful to some future one of us!
thanks, that’s very helpful! as a patch id i reckon we should use the relative file path.
another way of making unique ids for patches is to store a md5 of the actual patch preset so then even if the patch is renamed or moved in the folder structure it would have a unique id, that sounds ideal but would require an aditional md5 step when saving presets so they get a unique id and also perhaps md5 patches on load if they don’t have an md5 id so it would be backwards compatible.
yeah I've thought about things like: scanning all the patches into a sqlite database at startup so we could do things like tagging and hashing. but that's a way bigger project.
yeah I've thought about things like: scanning all the patches into a sqlite database at startup so we could do things like tagging and hashing. but that's a way bigger project.
yeah, my idea was to hash it and save it on the preset file, but indeed that would require saving a map on disk and updating it every time the preset is saved
Yup. And that's exactly the sort of problem that sqlite is for.
When we get a midi program change event we basically do 127*bank + patch and then see if that number is within the range of lists of presets in the unordered list (I think; I may have changed it to use the ordered list in the past but I don’t think so). It then loads that patch
I just gave it a shot - it IS using the ordered list!
But... only in VST2! Program changes are completely broken/not functioning in VST3 from what I can tell.
i remember when i tried PGM messages would work but if there was a NOTE at the same time the note would not sound or something among those lines
That was likely with VST2 then, because Surge VST3 program changes are completely nonfunctional as I said.
Surge does an all notes off before any action which loads a patch. It kinda has to because of the shared data structures in the patches. Midi Pgm change would be the same
I think the au supports it too. Although it’s not correctly implemented anywhere
I mean sure, the way it is currently implemented (in VST2 or AU) is not ideal. But even that non-ideal system is not at all working in VST3. Maybe it should?
Vst3 will require another fake param it seems. You don’t get the message you get midi interception just like cc. I can’t imagine bothering to do this myself but here’s a pointer
What a load of excrement VST3 is...
well we already make the 16*128 fake params. What's another 16 I guess? But it is code one would need to write.
OK after a bit of pondering today and a discussion with @K0rrid0r, I think I am leaning away from the u-he model (as good as it is and as much as I personally like it).
For Surge, here's what I envision regarding Program Change support:
This would be a really great implementation for Surge, methinks.
This would be a really great implementation for Surge, methinks.
sounds amazing
That does sound amazing. The bank manager basically
well i can say right now im hearing completely ridiculous things (sound wise) from the vst2!
example of what it looks like.
so that is a very fast midi program change, now imagine i slow it down to minutes etc. one can really build really big livesets and sound structures from very few surge instances in this way with some smart midi change programming! super neat!
so that is a very fast midi program change, now imagine i slow it down to minutes etc. one can really build really big livesets and sound structures from very few surge instances in this way with some smart midi change programming! super neat!
Indeed!
It would also be great on a future version to have interpolation between presets, like Camel Audio Alchemy
That one seems pretty darn difficult to do. (especially when you have non-continuous parameters that can't easily be morphed).
That one seems pretty darn difficult to do. (especially when you have non-continuous parameters that can't easily be morphed).
agreed, definitely very complicated
That one seems pretty darn difficult to do. (especially when you have non-continuous parameters that can't easily be morphed).
agreed, definitely very complicated
A non-efficient way of implementing is to have the 4 presets running at the same time ( 1 for each corner of the square ) and then just crossfade the outputs accordingly based on the X/Y position.
So in "morphing mode" it would be basically running 4 instances of the engine.
The code has bits and bobs of a scene morph kicking around in there for I think that reason. Basically a dual mode where the output is controlled by a macro. Although you could just map a macro to scene master volume and get the same thing (but it's a wee bit tricky ahead of mod mappers to make it sound OK)
Right now Surge doesn't respond at all to Program Change messages. Eventually this would be a great thing to have, especially for live performance.
I hold u-he plugins as the gold standard here. Here's an excerpt directly from the manual for one of their super-popular synths, Zebra 2:
"MIDI Programs As well as factory presets, ‘Local’ also contains a special folder called ‘MIDI Programs’. When the first instance of Zebra2 starts, all presets in that folder (up to 128) are loaded into memory so they can be selected via MIDI Program Change messages. It is best to rename them to be sorted by number e.g. ‘000 rest-of-name’ to ‘127 rest-of-name’. ‘MIDI Programs’ can contain up to 127 sub-folders, switchable via MIDI Bank Select messages (CC#0). Send Bank Select first, then Program Change. ‘MIDI Programs’ itself is bank 0, then sub-folders are addressed in alphabetical order starting with bank 1. Important - ‘MIDI Programs’ cannot be added, removed or renamed on the fly – any changes to that directory will only be updated after the host application is restarted."