Is there any way to map note name (ex. GM Drums set)

Hello. I’m new in C++ and JUCE. I’m learning about coding C++ and how to use JUCE with watching Youtube tutorial.
I’m also interested building plug in effector and synthesizer but most I wanna achieve is making a mapper plugin like : https://schemafactor.com/midimapperx/

This is an Windows VST plugin that overrides MIDI data. Which have the feature that mapping piano roll note name.
I used this plugin very useful when using DAW in Windows but there is no alternative to this plugin on Mac…
So I decided build one. But I don’t know how to approach to that… I couldn’t notice any methods can handle it.
Is there any method to assign custom string to specific MIDI note?
If not, do I need to analyze the part where the DAW gets the note name and apply the code?

You can use a map for this–probably std::unordered_map. If you use MidiMessage as the key, then you can use it to retrieve the corresponding string.

This is just a piece of the puzzle–there is a lot more you’ll need to think through.

Thanks for replying.
By using std::unordered_map, can I make the plugin to announce to DAW which string is allocated to specific note?
But I think you might misunderstood what I want to do… I want to announce array of strings to note, not retrieving strings from note.
I found getMidiKeyName function from Steinberg’s VST3 sdk.

bool Vst2Wrapper::getMidiKeyName (VstInt32 channel, MidiKeyName* keyName)
{
UnitID unitId;
ProgramListID programListId;
if (mUnitInfo && getProgramListAndUnit (channel, unitId, programListId))
{
String128 string128 = {0};
if (mUnitInfo->getProgramPitchName (programListId, keyName->thisProgramIndex,
keyName->thisKeyNumber, string128))
{
String str (string128);
str.copyTo8 (keyName->keyName, 0, kVstMaxNameLen);
return true;
}
}
return false;
}

And draft code of MIDIMapperX’s naming function is

public override bool GetMidiKeyName(Jacobi.Vst.Core.VstMidiKeyName midiKeyName, int channel)
{
if (p.NoteMap.Contains((byte)midiKeyName.CurrentKeyNumber))
{
midiKeyName.Name = p.NoteMap[(byte)midiKeyName.CurrentKeyNumber].KeyName;
} else
{
midiKeyName.Name = “Note Map #” + midiKeyName.CurrentKeyNumber; // Or could return false here to use the default note name
}

return true;
}

(I copied this code from https://forum.image-line.com/viewtopic.php?f=100&t=101398&hilit=note+name+map#p739916

I found getMidiKeyName is used both, and I hope this to be a key making me happy…
But another problem is that I don’t know how to include SDK’s code to JUCE project… :frowning:

I would also like to do something very similar. Looking through the code (7.0.5) using a debugger and VS2022, I see the following methods in juce_VST3_Wrapper.cpp (in struct ProgramChangeParameter?). So JUCE can apparently call the necessary code in Steinberg. But I can’t trace any path in JUCE which gets to these methods… Maybe someone can shed light?

    tresult PLUGIN_API hasProgramPitchNames (Vst::ProgramListID listId, Steinberg::int32 programIndex) override
    {
        if (audioProcessor != nullptr)
            return audioProcessor->hasProgramPitchNames (listId, programIndex);

        jassertfalse;
        return kResultFalse;
    }

    tresult PLUGIN_API getProgramPitchName (Vst::ProgramListID listId, Steinberg::int32 programIndex,
                                            Steinberg::int16 midiPitch, Vst::String128 name) override
    {
        if (audioProcessor != nullptr)
            return audioProcessor->getProgramPitchName (listId, programIndex, midiPitch, name);

        jassertfalse;
        return kResultFalse;
    }

Update: In the same source juce_VST3_Wrapper.cpp I found:

tresult PLUGIN_API hasProgramPitchNames (Vst::ProgramListID, Steinberg::int32) override                                     { return kNotImplemented; }
tresult PLUGIN_API getProgramPitchName (Vst::ProgramListID, Steinberg::int32, Steinberg::int16, Vst::String128) override    { return kNotImplemented; }

which would obviously need to be changed/overridden.
Technically, this shouldn’t be difficult.
Legally, referring to the ISC/MPL license terms referred to in JUCE Readme.md, modifications would seem to be possible, requiring some access to modified source code. I am not a lawyer.
For “internal” test purposes, I plan on introducing some conditionals and trying it out.

Test success: crude test shows replacement methods being called in Cakewalk and Waveform Free. Waveform Free displays the note names that I generate.

I have an open feature request for this, please vote for it.

1 Like

I happily voted for the feature request.

Debugging this function is “interesting”.
a. AudioPluginHost doesn’t do anything with note names or try to fetch them (AFAIK). Obviously that could be added.
b. Cakewalk loads the note names every time a project (with the plugin) is opened. But it doesn’t display them or use them.
c. Waveform [Free] DOESN’T load the note names every time a project is opened.

  • It loads them when the plugin is inserted the first time
  • It reloads them when toggling a MIDI clip to step clip (or vice versa).

I was going a little crazy trying to debug my code. It seems to be working reasonably well.