kushview / element

Element Audio Plugin Host
https://kushview.net/element/
1.08k stars 95 forks source link

Parameter MIDI control #479

Closed grimepoch closed 1 year ago

grimepoch commented 2 years ago

Fantastic Work on this environment!

I am using this host to try and solve a problem in Live with the limitations of it's MIDI mapping/recording/playback. Specifically, if a plugin does not have internal MIDI mapping, it is painful to drive those internal parameters, as the parameter mapping system is painful for MIDI (requires something send MIDI in, usually IAC bus on OSX.

So I testing with the controller mapping in Element and that works great, however, the parameter system you have at the bottom offers more flexibility for me I can see.

Basically, I want to create 8 tracks in Live and have each one have a default MIDI loop that just has automation on say 10-17 in track, and they all feed into another track with Element on it.

Now, if I could set each of the parameter knobs to listen to 10-17, I could freely map ANY parameter from the plugin to the parameter knobs which will always be mapped if I save it that way.

Long story short, I want to use MIDI clips as loop able patterns to drive parameters. Super flexible.

I downloaded the code to play with, but anything I do will be just hard coding and hacking up on my send to test the principle.

Thanks again for an amazing plugin!

mfisher31 commented 2 years ago

Thanks! So the midi tracks' MIDI output all go to one element instance on another track?

grimepoch commented 2 years ago

Yep! This gives me the flexibility in session view to create loops of different lengths that have my own drawn in CC waveforms.

To be specific, what I am trying to do is drive XO (drum synth), for instance the high hat pitch control has no internal LFO, and no MIDI map. I'd like to easily map from a second lane so I can leave the MIDI alone on the ELEMENT track. This way, I just use all the "Send To" to all drive Element.

I saw you were thinking about an internal sequencer as well, CC sequencing might be cool for this, as long as it is host syncable.

mfisher31 commented 2 years ago

Yep, eventually a sequencer will come along. MIDI should already be received by the collecting Element instance. And you're wanting the performance parameters to respond to MIDI CC ?

grimepoch commented 2 years ago

That is correct, basically I'd like to map a device and midi CC to each parameter knob at the bottom. So in my case of using it as a VST plugin, that would be the host. I would assign say CC10 through CC17 with the default set of knobs.

Now, I can assign those knobs to any parameter. I know right now it's just 1:1 assignment, but that is perfectly fine.

Then, when I route CC into Element from my DAW, CC10 ALWAYS controls the first knob, and I can freely change whatever parameter it is driving on any plugin I have loaded in element.

I'm going to try and hardcode it, I have Xcode downloaded and I am working on getting the plugin compiled that way (as opposed to waf which I did compile, but that doesn't build the VST). This will be just to test how well the concept works from the LIVE side of it.

Right now, I've tested by mapping a control to a CC through the controller mapping, however that isn't as easy to get the mapping to work. What I do is change the knob in the VST, then click map, then JUST play the CC that I want to control that. having to silence all other sending CC is a bit painful to swap them around as I have to silence everything else just so I can learn the exact CC to control mapping. BUT, it works! The knob idea that you've started, for me that is just awesome flexibility!

mfisher31 commented 2 years ago

Yeah, plugins can't compile with Waf yet. You should be able to hardcode something in src/plugins/PluginProcessor.cpp pretty easy. The PluginProcessor class owns the list of performance parameters in order you see them in the GUI.

Just insert some code that checks CC messages with the MidiBuffer in the PluginProcessor::processBlock callback

grimepoch commented 2 years ago

Thanks for the heads up on that! Currently having a nightmare trying to compile code with the removal of the VST2 headers, so still working on making this compile first. Then next step will be trying this out.

grimepoch commented 2 years ago

Is there a certain release tag of JUCE I should be using to compile this?

grimepoch commented 2 years ago

I found the VST2 headers, so I can enable that. What I don't understand is how this code compiles.

In Element/JuceLibraryCode/AppConfig. h, I see this call:

ifndef EL_REZ

include "../../Standalone/JuceLibraryCode/BinaryData.h"

endif

But if I go look in that folder, I do not see BinaryData.h

Not sure what EL_REZ is. I'll try commenting out.

(I realize I am out of scope of the original feature enhancement at this point, haha, so sorry for leading this thread down this path)

mfisher31 commented 2 years ago

You should use the JUCE version included in the codebase libs/JUCE it's a submodule so git submodule update --init

EL_REZ is defined when building the AudioUnit plugin.

binarydata.h - is generated by Projucer when the project is saved. You can build this yourself from the code, or download it from juce.com.

grimepoch commented 2 years ago

Weird, so I load up your project under 'Element' and I check the paths, and it is all pointing to the files in your lib area as you indicated. The projucer I am using is the one I downloaded, so maybe that is the problem. I see there is a projucer project in your lib, do I need to build that one? I don't see a binary in there

When I try to compile, I see it complaining about symbols like "Vst2::kSpeakerArrEmpty" not found.

grimepoch commented 2 years ago

So figured out first problem, this:

include "../../Standalone/JuceLibraryCode/BinaryData.h"

Doesn't exist yet if you try and build "Element" first, so I went and tried compiling it and now it finds that file.

The second problem is when it's building juce_VST_Common, for some reason it is not seeing the VST headers, and no errors, so I think something got configured wrong. I will try and determine which JUCE library in in the element repo and try with that projucer, I am thinking the files it generates, something is wrong with how it's defining the VST headers.

I verified it is pulling your included library, so it has to be projucer, unless I am starting things wrong.

grimepoch commented 2 years ago

Ended up building projucer that came with your release, didn't make a difference on the files it created, so really no clue. I'm on OSX 12.2 and Xcode 13.2.1.

So weird. Inside just_VSTComon.h, inside "vstArrangementTypeToChannelSet" it's trying to use the enum Vst2::kSpeakerArrEmpty, but for the life of me I am not seeing where the headers are getting loaded in the Vst2 namespace in the call stack to this header. Still digging through, a lot to go through.

grimepoch commented 2 years ago

OKAY!!

So, deleted everything and started over, something must have got mixed up between projucer versions, and the first time I used it I didn't have a VST2 SDK set. I'll worry about testing again with the new version, but what I did was:

This was just the stand-alone since I know the plugin version was looking for that file in the stand-alone area.

So now getting ready to built Element (plugins)

grimepoch commented 2 years ago

Success, I added this code to processBlock:

    for (const MidiMessageMetadata metadata : midi)
    {   const juce::MidiMessage midiMessage { metadata.getMessage() };
        if (midiMessage.isController())
        {   int cc  = midiMessage.getControllerNumber();
            if( cc>=10 && cc<18){
                float val = (float)midiMessage.getControllerValue();
                perfparams[cc-10]->setValue(val/127.0);
            }

        }

    }

Right now it doesn't update the knob position on the screen, still looking through the code to have it change that. In any case, thanks for your help on this!

grimepoch commented 2 years ago

Got it, just called updateValue() after the setting of the value. So cool!

mfisher31 commented 2 years ago

Nice work!

grimepoch commented 2 years ago

Interesting side note, Ableton Live 11 blocks certain CC on VST3 from being passed along. I verified inside Element that CC14 was in deed being created, and then I tested VST3 in Bitwig and saw no problem.

People have let Ableton know this problem exists, but so far no change. So I need to switch my code to CC64 and up for 8 because they can be change.

I just wanted to say I am SUPER impressed by Element. Just having the MIDI monitor in there was amazing for troubleshooting!