Skip to content

Commit

Permalink
Merge pull request #17 from GuitarML/conditioned-models
Browse files Browse the repository at this point in the history
Conditioned models
  • Loading branch information
GuitarML authored Oct 31, 2021
2 parents ca1f413 + 8d2a204 commit 64e554d
Show file tree
Hide file tree
Showing 14 changed files with 192 additions and 34 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.15)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING "Minimum OS X deployment target")
project(NeuralPi VERSION 1.2.0)
project(NeuralPi VERSION 1.3.0)

set(CMAKE_CXX_STANDARD 17)

Expand Down
8 changes: 6 additions & 2 deletions NeuralPi.jucer
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>

<JUCERPROJECT name="NeuralPi" companyName="GuitarML" version="1.0.0" companyWebsite="https://guitarml.com"
<JUCERPROJECT name="NeuralPi" companyName="GuitarML" version="1.3.0" companyWebsite="https://guitarml.com"
defines="PIP_JUCE_EXAMPLES_DIRECTORY=L2hvbWUvaWxpYXMvd29ya3NwYWNlcy9KVUNFL2V4YW1wbGVz"
projectType="audioplug" pluginManufacturer="GuitarML" pluginAUIsSandboxSafe="1"
pluginFormats="buildStandalone,buildVST3" id="vXK47v" jucerFormatVersion="1"
displaySplashScreen="1">
displaySplashScreen="1" companyEmail="[email protected]">
<MAINGROUP id="zI9r2C" name="NeuralPi">
<GROUP id="{810D2D07-FCAC-0F25-F63F-DCF49FEE10C7}" name="Resources">
<FILE id="wKou0l" name="BluesJr.json" compile="0" resource="1" file="models/BluesJr.json"/>
<FILE id="hQ0vq1" name="BluesJR_FullD.json" compile="0" resource="1"
file="models/BluesJR_FullD.json"/>
<FILE id="YURBrY" name="HT40_Overdrive.json" compile="0" resource="1"
file="models/HT40_Overdrive.json"/>
<FILE id="JubKNX" name="npi_background.jpg" compile="0" resource="1"
file="resources/npi_background.jpg"/>
<FILE id="ZNutt3" name="TS9.json" compile="0" resource="1" file="models/TS9.json"/>
<FILE id="wH6oji" name="TS9_FullD.json" compile="0" resource="1" file="models/TS9_FullD.json"/>
</GROUP>
<GROUP id="{70CE292C-E9C5-C029-B95A-F7DF41E5F74C}" name="Source">
Expand Down
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ There are four main components to the guitar pedal:
4. NeuralPi VST3 plugin

![app](https://github.com/GuitarML/NeuralPi/blob/main/resources/neuralpi_pic.jpg)
<br>This is the normal plugin (v1.2.0), available for Windows (Standalone, VST3) and Mac (Standalone, AU, VST3). After connencting the Raspberry Pi and remote computer to the same local WiFi network, enter the RaspberryPi's IP address (keep the default ports) to enable control over WiFi. The Win/Mac plugins are fully functional guitar plugins that allow you to try out GuitarML's most advanced amp/pedal models without building the Raspberry Pi pedal.
<br>This is the normal plugin (v1.3.0), available for Windows (Standalone, VST3) and Mac (Standalone, AU, VST3). After connencting the Raspberry Pi and remote computer to the same local WiFi network, enter the RaspberryPi's IP address (keep the default ports) to enable control over WiFi. The Win/Mac plugins are fully functional guitar plugins that allow you to try out GuitarML's most advanced amp/pedal models without building the Raspberry Pi pedal.

Note: The plugin must be restarted after using the Import Tone button for changes to take effect.

Expand All @@ -33,6 +33,10 @@ Windows: C:/Users/<username>/Documents/GuitarML/NeuralPi/tones
Elk Audio OS: /home/mind/Documents/GuitarML/NeuralPi/tones
```

## Conditioned Models

Starting with version 1.3, NeuralPi can load tones conditioned on the Gain parameter. The three default tones included with NeuralPi are now conditioned models. This type of model uses a neural network for the full range of the Gain/Drive parameter, rather than just a snapshot model. When a conditioned model is loaded, the Gain knob will turn red.

## Adding New Models

Once your NeuralPi is set up, you can add new models from a remote computer using the following steps:
Expand All @@ -50,36 +54,34 @@ IMPORTANT: The plugin uses a sort() function to order the models alphabetically.

## MIDI control of NeuralPi parameters

The “config_neuralpi_MIDI.json” file contains MIDI mapping of NeuralPi parameters.
The “config_neuralpi_MIDI.json” file contains MIDI mapping of NeuralPi parameters.

The names of parameters are: "Gain", "Master", "Bass", "Mid", "Treble", "Presence", "Delay", "Reverb", "Model", "Ir".
In that json file, you can see that those parameters have been asigned to incoming MIDI CC# messages "1", "2", "3", "4, "5", "6", "7", "8", "9" and "10" respectively. But editing the file allows you to chose whatever CC# to whatever parameter, by just changing values in the “cc_number” and “parameter_name” commmands.
In that json file, you can see that those parameters have been asigned to incoming MIDI CC# messages "1", "2", "3", "4, "5", "6", "7", "8", "9" and "10" respectively. But editing the file allows you to chose whatever CC# to whatever parameter, by just changing values in the “cc_number” and “parameter_name” commmands.

Sushi will listen to incoming MIDI CC# messages, will normalize (0, 127) MIDI values range to (0, 1) Sushi range, and will set that value to correspondent parameter. For instance, if your MIDI controller sends a CC2 message with value "127", Sushi will receive that message and set "Master" parameter (“Master” is assigned to “CC2”) to be "1" (MIDI “127” value normalized to “1”).
Sushi will listen to incoming MIDI CC# messages, will normalize (0, 127) MIDI values range to (0, 1) Sushi range, and will set that value to correspondent parameter. For instance, if your MIDI controller sends a CC2 message with value "127", Sushi will receive that message and set "Master" parameter (“Master” is assigned to “CC2”) to be "1" (MIDI “127” value normalized to “1”).

You´ll need to copy the config file to the Raspberry, for instance through ssh over Wifi (login as root):
You´ll need to copy the config file to the Raspberry, for instance through ssh over Wifi (login as root):

scp -r config_neuralpi_MIDI.json root@<rpi-ip-address>:/home/mind/config_files/

For connecting a MIDI device:

1 - Plug your MIDI device into any Raspberry USB port.

2 - Login as “mind” user, “elk” password, and run Sushi with the MIDI config:
2 - Login as “mind” user, “elk” password, and run Sushi with the MIDI config:

sushi -r --multicore-processing=2 –c ~/config_files/config_neuralpi_MIDI.json &
sushi -r --multicore-processing=2 –c ~/config_files/config_neuralpi_MIDI.json &

3 – To list MIDI devices connected to the Raspberry, run:
3 – To list MIDI devices connected to the Raspberry, run:

aconnect –l
aconnect –l

4 – You can now connect your MIDI device to Sushi either by their listed ports, or by their names. Run:
4 – You can now connect your MIDI device to Sushi either by their listed ports, or by their names. Run:

aconnect "your-listed-device-name" "Sushi"

NOTE 1: Currentlly, "Model" and "Ir" parameters are a little tricky to control. NeuralPi asigns a value to each file saved in "tones" or "Ir" directory. It divides the (0, 1) range of values by the number of files available, so for instance, if you had just 2 tone files in the directory, one of them would respond to any value in the (0, 0.49) range, and the other would respond to any value in the (0.5, 1) range. When a lot of tones/IR files are stored in the directories, it´s difficult to guess which value corresponds to which tone/IR... so for the moment, if you need to control tones or IRs with MIDI, you´d have to work a little to find out values, or just reduce the number of tones/IRs in your directories to make the task easier.

NOTE 2: When NeuralPi is started, it seeks for tones in the directory. If it doesn´t find the default ones (“BluesJR_FullD.json” and “TS9_FullD.json” tones), it will create them again. So if you had only 2 tones because yo wanted to control them easily by MIDI, and neither of them are the BluesJr nor TS9, bear in mind that at Sushi startup, suddenly BluesJr and TS9 files will be created again in the directory, so there´ll be 4 models/files stored and the values assigned for each one might have changed. If you want only 2 models, you can cheat a little and rename your desired model files as “BluesJR_FullD.json” and “TS9_FullD.json” (make sure the name is identical). This way, NeuralPi thinks that default models are already in the directory and doesn´t add any files.
NOTE 1: Currentlly, "Model" and "Ir" parameters are a little tricky to control. NeuralPi asigns a value to each file saved in "tones" or "Ir" directory. It divides the (0, 1) range of values by the number of files available, so for instance, if you had just 2 tone files in the directory, one of them would respond to any value in the (0, 0.49) range, and the other would respond to any value in the (0.5, 1) range.

## To Do

Expand All @@ -93,6 +95,8 @@ The neural network is a re-creation of the LSTM inference model from [Real-Time
The [Automated-GuitarAmpModelling](https://github.com/Alec-Wright/Automated-GuitarAmpModelling) project was used to train the .json models.<br>
GuitarML maintains a [fork](https://github.com/GuitarML/Automated-GuitarAmpModelling) with a few extra helpful features, including a Colab training script.
IMPORTANT: When training models for NeuralPi, ensure that a LSTM size of 20 is used. NeuralPi is optimized to run models of this size, and other sizes are not currently compatible.

Note: The GuitarML fork of the Automated-GuitarAmpModelling code now contains helper scripts for training conditioned models, which are compatible with NeuralPi v1.3.

The plugin uses [RTNeural](https://github.com/jatinchowdhury18/RTNeural), which is a highly optimized neural net inference engine intended for audio applications.

Expand Down
54 changes: 51 additions & 3 deletions Source/PluginEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to

blueLookAndFeel.setColour(juce::Slider::thumbColourId, juce::Colours::aqua);
redLookAndFeel.setColour(juce::Slider::thumbColourId, juce::Colours::red);

//addAndMakeVisible(modelKnob);
//ampGainKnob.setLookAndFeel(&ampSilverKnobLAF);
modelKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
Expand Down Expand Up @@ -149,7 +152,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess


addAndMakeVisible(ampGainKnob);
//ampGainKnob.setLookAndFeel(&ampSilverKnobLAF);
ampGainKnob.setLookAndFeel(&blueLookAndFeel);
ampGainKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
ampGainKnob.setNumDecimalPlacesToDisplay(1);
ampGainKnob.addListener(this);
Expand Down Expand Up @@ -188,7 +191,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
};

addAndMakeVisible(ampMasterKnob);
//ampMasterKnob.setLookAndFeel(&ampSilverKnobLAF);
ampMasterKnob.setLookAndFeel(&blueLookAndFeel);
ampMasterKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
ampMasterKnob.setNumDecimalPlacesToDisplay(1);
ampMasterKnob.addListener(this);
Expand Down Expand Up @@ -230,6 +233,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess


addAndMakeVisible(ampBassKnob);
ampBassKnob.setLookAndFeel(&blueLookAndFeel);
ampBassKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
ampBassKnob.setNumDecimalPlacesToDisplay(1);
ampBassKnob.addListener(this);
Expand Down Expand Up @@ -268,6 +272,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
};

addAndMakeVisible(ampMidKnob);
ampMidKnob.setLookAndFeel(&blueLookAndFeel);
ampMidKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
ampMidKnob.setNumDecimalPlacesToDisplay(1);
ampMidKnob.addListener(this);
Expand Down Expand Up @@ -306,6 +311,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
};

addAndMakeVisible(ampTrebleKnob);
ampTrebleKnob.setLookAndFeel(&blueLookAndFeel);
ampTrebleKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
ampTrebleKnob.setNumDecimalPlacesToDisplay(1);
ampTrebleKnob.addListener(this);
Expand Down Expand Up @@ -344,6 +350,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
};

addAndMakeVisible(ampPresenceKnob);
ampPresenceKnob.setLookAndFeel(&blueLookAndFeel);
ampPresenceKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
ampPresenceKnob.setNumDecimalPlacesToDisplay(1);
ampPresenceKnob.addListener(this);
Expand Down Expand Up @@ -382,6 +389,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
};

addAndMakeVisible(ampDelayKnob);
ampDelayKnob.setLookAndFeel(&blueLookAndFeel);
ampDelayKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
ampDelayKnob.setNumDecimalPlacesToDisplay(1);
ampDelayKnob.addListener(this);
Expand Down Expand Up @@ -420,6 +428,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
};

addAndMakeVisible(ampReverbKnob);
ampReverbKnob.setLookAndFeel(&blueLookAndFeel);
ampReverbKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
ampReverbKnob.setNumDecimalPlacesToDisplay(1);
ampReverbKnob.addListener(this);
Expand Down Expand Up @@ -467,23 +476,39 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
addAndMakeVisible(BassLabel);
BassLabel.setText("Bass", juce::NotificationType::dontSendNotification);
BassLabel.setJustificationType(juce::Justification::centred);

addAndMakeVisible(MidLabel);
MidLabel.setText("Mid", juce::NotificationType::dontSendNotification);
MidLabel.setJustificationType(juce::Justification::centred);

addAndMakeVisible(TrebleLabel);
TrebleLabel.setText("Treble", juce::NotificationType::dontSendNotification);
TrebleLabel.setJustificationType(juce::Justification::centred);

addAndMakeVisible(PresenceLabel);
PresenceLabel.setText("Presence", juce::NotificationType::dontSendNotification);
PresenceLabel.setJustificationType(juce::Justification::centred);

addAndMakeVisible(DelayLabel);
DelayLabel.setText("Delay", juce::NotificationType::dontSendNotification);
DelayLabel.setJustificationType(juce::Justification::centred);

addAndMakeVisible(ReverbLabel);
ReverbLabel.setText("Reverb", juce::NotificationType::dontSendNotification);
ReverbLabel.setJustificationType(juce::Justification::centred);

addAndMakeVisible(toneDropDownLabel);
toneDropDownLabel.setText("Tone", juce::NotificationType::dontSendNotification);
toneDropDownLabel.setJustificationType(juce::Justification::centred);

addAndMakeVisible(irDropDownLabel);
irDropDownLabel.setText("IR", juce::NotificationType::dontSendNotification);
irDropDownLabel.setJustificationType(juce::Justification::centred);

addAndMakeVisible(versionLabel);
versionLabel.setText("v1.3.0", juce::NotificationType::dontSendNotification);
versionLabel.setJustificationType(juce::Justification::centred);

auto font = GainLabel.getFont();
float height = font.getHeight();
font.setHeight(height); // 0.75);
Expand All @@ -495,6 +520,10 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
PresenceLabel.setFont(font);
DelayLabel.setFont(font);
ReverbLabel.setFont(font);
toneDropDownLabel.setFont(font);
irDropDownLabel.setFont(font);
versionLabel.setFont(font);


// Name controls:
addAndMakeVisible(ampNameLabel);
Expand Down Expand Up @@ -542,6 +571,9 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess

// Size of plugin GUI
setSize(345, 455);

// Set gain knob color based on conditioned/snapshot model
setGainKnobColor();
}

NeuralPiAudioProcessorEditor::~NeuralPiAudioProcessorEditor()
Expand Down Expand Up @@ -592,10 +624,13 @@ void NeuralPiAudioProcessorEditor::resized()
MidLabel.setBounds(91, 238, 80, 10);
TrebleLabel.setBounds(178, 238, 80, 10);
PresenceLabel.setBounds(265, 238, 80, 10);

DelayLabel.setBounds(178, 108, 80, 10);
ReverbLabel.setBounds(265, 108, 80, 10);

toneDropDownLabel.setBounds(267, 16, 80, 10);
irDropDownLabel.setBounds(261, 48, 80, 10);
versionLabel.setBounds(268, 431, 80, 10);

addAndMakeVisible(ampNameLabel);
ampNameField.setEditable(true, true, true);
addAndMakeVisible(ampNameField);
Expand All @@ -622,6 +657,7 @@ void NeuralPiAudioProcessorEditor::modelSelectChanged()
}
auto newValue = static_cast<float>(processor.current_model_index / (processor.num_models - 1.0));
modelKnob.setValue(newValue);
setGainKnobColor();
}

void NeuralPiAudioProcessorEditor::irSelectChanged()
Expand Down Expand Up @@ -678,6 +714,7 @@ void NeuralPiAudioProcessorEditor::loadButtonClicked()
}
}
}
setGainKnobColor();
}

void NeuralPiAudioProcessorEditor::loadIRClicked()
Expand Down Expand Up @@ -1045,4 +1082,15 @@ void NeuralPiAudioProcessorEditor::setParameterValue(const String& paramId, floa
{
if (auto* param = getParameter(paramId))
param->setValueNotifyingHost(value);
}


void NeuralPiAudioProcessorEditor::setGainKnobColor()
{
if (processor.is_conditioned == false) {
ampGainKnob.setLookAndFeel(&blueLookAndFeel);
}
else {
ampGainKnob.setLookAndFeel(&redLookAndFeel);
}
}
7 changes: 7 additions & 0 deletions Source/PluginEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class NeuralPiAudioProcessorEditor : public AudioProcessorEditor,
Label PresenceLabel;
Label DelayLabel;
Label ReverbLabel;
Label toneDropDownLabel;
Label irDropDownLabel;
Label versionLabel;

File test_file;
File model_folder;
Expand All @@ -105,6 +108,9 @@ class NeuralPiAudioProcessorEditor : public AudioProcessorEditor,
TextButton loadIR;
ToggleButton irButton;
ToggleButton lstmButton;

juce::LookAndFeel_V4 blueLookAndFeel;
juce::LookAndFeel_V4 redLookAndFeel;

juce::String fname;
virtual void buttonClicked(Button* button) override;
Expand Down Expand Up @@ -169,6 +175,7 @@ class NeuralPiAudioProcessorEditor : public AudioProcessorEditor,

float getParameterValue(const String& paramId);
void setParameterValue(const String& paramId, float value);
void setGainKnobColor();

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralPiAudioProcessorEditor)
};
Loading

0 comments on commit 64e554d

Please sign in to comment.