PluginProcessor.cpp (12930B)
1 /* 2 ============================================================================== 3 4 This file was auto-generated! 5 6 It contains the basic framework code for a JUCE plugin processor. 7 8 ============================================================================== 9 */ 10 11 #include "PluginProcessor.h" 12 #include "PluginEditor.h" 13 14 //============================================================================== 15 ProteusAudioProcessor::ProteusAudioProcessor() 16 #ifndef JucePlugin_PreferredChannelConfigurations 17 : AudioProcessor(BusesProperties() 18 #if ! JucePlugin_IsMidiEffect 19 #if ! JucePlugin_IsSynth 20 .withInput("Input", AudioChannelSet::stereo(), true) 21 #endif 22 .withOutput("Output", AudioChannelSet::stereo(), true) 23 #endif 24 ), 25 26 treeState(*this, nullptr, "PARAMETER", { std::make_unique<AudioParameterFloat>(GAIN_ID, GAIN_NAME, NormalisableRange<float>(0.0f, 1.0f, 0.01f), 0.5f), 27 std::make_unique<AudioParameterFloat>(BASS_ID, BASS_NAME, NormalisableRange<float>(-8.0f, 8.0f, 0.01f), 0.0f), 28 std::make_unique<AudioParameterFloat>(MID_ID, MID_NAME, NormalisableRange<float>(-8.0f, 8.0f, 0.01f), 0.0f), 29 std::make_unique<AudioParameterFloat>(TREBLE_ID, TREBLE_NAME, NormalisableRange<float>(-8.0f, 8.0f, 0.01f), 0.0f), 30 std::make_unique<AudioParameterFloat>(MASTER_ID, MASTER_NAME, NormalisableRange<float>(0.0f, 1.0f, 0.01f), 0.5) }) 31 32 33 #endif 34 { 35 driveParam = treeState.getRawParameterValue (GAIN_ID); 36 masterParam = treeState.getRawParameterValue (MASTER_ID); 37 bassParam = treeState.getRawParameterValue (BASS_ID); 38 midParam = treeState.getRawParameterValue (MID_ID); 39 trebleParam = treeState.getRawParameterValue (TREBLE_ID); 40 41 auto bassValue = static_cast<float> (bassParam->load()); 42 auto midValue = static_cast<float> (midParam->load()); 43 auto trebleValue = static_cast<float> (trebleParam->load()); 44 45 eq4band.setParameters(bassValue, midValue, trebleValue, 0.0); 46 eq4band2.setParameters(bassValue, midValue, trebleValue, 0.0); 47 48 pauseVolume = 3; 49 50 cabSimIRa.load(BinaryData::default_ir_wav, BinaryData::default_ir_wavSize); 51 52 } 53 54 ProteusAudioProcessor::~ProteusAudioProcessor() 55 { 56 } 57 58 //============================================================================== 59 const String ProteusAudioProcessor::getName() const 60 { 61 return JucePlugin_Name; 62 } 63 64 bool ProteusAudioProcessor::acceptsMidi() const 65 { 66 #if JucePlugin_WantsMidiInput 67 return true; 68 #else 69 return false; 70 #endif 71 } 72 73 bool ProteusAudioProcessor::producesMidi() const 74 { 75 #if JucePlugin_ProducesMidiOutput 76 return true; 77 #else 78 return false; 79 #endif 80 } 81 82 bool ProteusAudioProcessor::isMidiEffect() const 83 { 84 #if JucePlugin_IsMidiEffect 85 return true; 86 #else 87 return false; 88 #endif 89 } 90 91 double ProteusAudioProcessor::getTailLengthSeconds() const 92 { 93 return 0.0; 94 } 95 96 int ProteusAudioProcessor::getNumPrograms() 97 { 98 return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs, 99 // so this should be at least 1, even if you're not really implementing programs. 100 } 101 102 int ProteusAudioProcessor::getCurrentProgram() 103 { 104 return 0; 105 } 106 107 void ProteusAudioProcessor::setCurrentProgram (int index) 108 { 109 } 110 111 const String ProteusAudioProcessor::getProgramName (int index) 112 { 113 return {}; 114 } 115 116 void ProteusAudioProcessor::changeProgramName (int index, const String& newName) 117 { 118 } 119 120 //============================================================================== 121 void ProteusAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) 122 { 123 // Use this method as the place to do any pre-playback 124 // initialisation that you need.. 125 126 *dcBlocker.state = *dsp::IIR::Coefficients<float>::makeHighPass (sampleRate, 35.0f); 127 128 // prepare resampler for target sample rate: 44.1 kHz 129 constexpr double targetSampleRate = 44100.0; 130 //resampler.prepareWithTargetSampleRate ({ sampleRate, (uint32) samplesPerBlock, 1 }, targetSampleRate); 131 resampler.prepareWithTargetSampleRate({ sampleRate, (uint32)samplesPerBlock, 2 }, targetSampleRate); 132 133 134 dsp::ProcessSpec specMono { sampleRate, static_cast<uint32> (samplesPerBlock), 1 }; 135 dsp::ProcessSpec spec{ sampleRate, static_cast<uint32> (samplesPerBlock), 2 }; 136 137 dcBlocker.prepare (spec); 138 139 LSTM.reset(); 140 LSTM2.reset(); 141 142 // Set up IR 143 cabSimIRa.prepare(spec); 144 145 } 146 147 void ProteusAudioProcessor::releaseResources() 148 { 149 // When playback stops, you can use this as an opportunity to free up any 150 // spare memory, etc. 151 } 152 153 #ifndef JucePlugin_PreferredChannelConfigurations 154 bool ProteusAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const 155 { 156 #if JucePlugin_IsMidiEffect 157 ignoreUnused (layouts); 158 return true; 159 #else 160 // This is the place where you check if the layout is supported. 161 // In this template code we only support mono or stereo. 162 if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono() 163 && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo()) 164 return false; 165 166 // This checks if the input layout matches the output layout 167 #if ! JucePlugin_IsSynth 168 if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet()) 169 return false; 170 #endif 171 172 return true; 173 #endif 174 } 175 #endif 176 177 178 void ProteusAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages) 179 { 180 ScopedNoDenormals noDenormals; 181 182 auto driveValue = static_cast<float> (driveParam->load()); 183 auto masterValue = static_cast<float> (masterParam->load()); 184 auto bassValue = static_cast<float> (bassParam->load()); 185 auto midValue = static_cast<float> (midParam->load()); 186 auto trebleValue = static_cast<float> (trebleParam->load()); 187 188 // Setup Audio Data 189 const int numSamples = buffer.getNumSamples(); 190 const int numInputChannels = getTotalNumInputChannels(); 191 const int sampleRate = getSampleRate(); 192 193 dsp::AudioBlock<float> block(buffer); 194 dsp::ProcessContextReplacing<float> context(block); 195 196 // Overdrive Pedal ================================================================== 197 if (fw_state == 1 && model_loaded == true) { 198 199 if (conditioned == false) { 200 // Apply ramped changes for gain smoothing 201 if (driveValue == previousDriveValue) 202 { 203 buffer.applyGain(driveValue*2.5); 204 } 205 else { 206 buffer.applyGainRamp(0, (int) buffer.getNumSamples(), previousDriveValue * 2.5, driveValue * 2.5); 207 previousDriveValue = driveValue; 208 } 209 auto block44k = resampler.processIn(block); 210 for (int ch = 0; ch < buffer.getNumChannels(); ++ch) 211 { 212 // Apply LSTM model 213 if (ch == 0) { 214 LSTM.process(block44k.getChannelPointer(0), block44k.getChannelPointer(0), (int)block44k.getNumSamples()); 215 } 216 else if (ch == 1) { 217 LSTM2.process(block44k.getChannelPointer(1), block44k.getChannelPointer(1), (int)block44k.getNumSamples()); 218 } 219 } 220 resampler.processOut(block44k, block); 221 } else { 222 buffer.applyGain(1.5); // Apply default boost to help sound 223 // resample to target sample rate 224 225 auto block44k = resampler.processIn(block); 226 for (int ch = 0; ch < buffer.getNumChannels(); ++ch) 227 { 228 // Apply LSTM model 229 if (ch == 0) { 230 LSTM.process(block44k.getChannelPointer(0), driveValue, block44k.getChannelPointer(0), (int)block44k.getNumSamples()); 231 } 232 else if (ch == 1) { 233 LSTM2.process(block44k.getChannelPointer(1), driveValue, block44k.getChannelPointer(1), (int)block44k.getNumSamples()); 234 } 235 } 236 resampler.processOut(block44k, block); 237 } 238 239 dcBlocker.process(context); 240 241 for (int ch = 0; ch < buffer.getNumChannels(); ++ch) 242 { 243 // Apply EQ 244 if (ch == 0) { 245 eq4band.process(buffer.getReadPointer(0), buffer.getWritePointer(0), midiMessages, numSamples, numInputChannels, sampleRate); 246 247 } 248 else if (ch == 1) { 249 eq4band2.process(buffer.getReadPointer(1), buffer.getWritePointer(1), midiMessages, numSamples, numInputChannels, sampleRate); 250 } 251 } 252 253 if (cab_state == 1) { 254 cabSimIRa.process(context); // Process IR a on channel 0 255 buffer.applyGain(2.0); 256 //} else { 257 // buffer.applyGain(0.7); 258 } 259 260 // Master Volume 261 // Apply ramped changes for gain smoothing 262 if (masterValue == previousMasterValue) 263 { 264 buffer.applyGain(masterValue); 265 } 266 else { 267 buffer.applyGainRamp(0, (int) buffer.getNumSamples(), previousMasterValue, masterValue); 268 previousMasterValue = masterValue; 269 } 270 271 // Smooth pop sound when changing models 272 if (pauseVolume > 0) { 273 if (pauseVolume > 2) 274 buffer.applyGain(0.0); 275 else if (pauseVolume == 2) 276 buffer.applyGainRamp(0, (int)buffer.getNumSamples(), 0, masterValue / 2); 277 else 278 buffer.applyGainRamp(0, (int)buffer.getNumSamples(), masterValue / 2, masterValue); 279 pauseVolume -= 1; 280 } 281 } 282 } 283 284 //============================================================================== 285 bool ProteusAudioProcessor::hasEditor() const 286 { 287 return true; // (change this to false if you choose to not supply an editor) 288 } 289 290 AudioProcessorEditor* ProteusAudioProcessor::createEditor() 291 { 292 return new ProteusAudioProcessorEditor (*this); 293 } 294 295 //============================================================================== 296 void ProteusAudioProcessor::getStateInformation (MemoryBlock& destData) 297 { 298 // You should use this method to store your parameters in the memory block. 299 // You could do that either as raw data, or use the XML or ValueTree classes 300 // as intermediaries to make it easy to save and load complex data. 301 302 auto state = treeState.copyState(); 303 std::unique_ptr<XmlElement> xml (state.createXml()); 304 xml->setAttribute ("fw_state", fw_state); 305 xml->setAttribute("folder", folder.getFullPathName().toStdString()); 306 xml->setAttribute("saved_model", saved_model.getFullPathName().toStdString()); 307 xml->setAttribute("current_model_index", current_model_index); 308 xml->setAttribute ("cab_state", cab_state); 309 copyXmlToBinary (*xml, destData); 310 311 } 312 313 void ProteusAudioProcessor::setStateInformation (const void* data, int sizeInBytes) 314 { 315 // You should use this method to restore your parameters from this memory block, 316 // whose contents will have been created by the getStateInformation() call. 317 318 std::unique_ptr<juce::XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes)); 319 320 if (xmlState.get() != nullptr) 321 { 322 if (xmlState->hasTagName (treeState.state.getType())) 323 { 324 treeState.replaceState (juce::ValueTree::fromXml (*xmlState)); 325 fw_state = xmlState->getBoolAttribute ("fw_state"); 326 File temp_saved_model = xmlState->getStringAttribute("saved_model"); 327 saved_model = temp_saved_model; 328 cab_state = xmlState->getBoolAttribute ("cab_state"); 329 330 current_model_index = xmlState->getIntAttribute("current_model_index"); 331 File temp = xmlState->getStringAttribute("folder"); 332 folder = temp; 333 if (auto* editor = dynamic_cast<ProteusAudioProcessorEditor*> (getActiveEditor())) 334 editor->resetImages(); 335 336 if (saved_model.existsAsFile()) { 337 loadConfig(saved_model); 338 } 339 340 } 341 } 342 } 343 344 void ProteusAudioProcessor::set_ampEQ(float bass_slider, float mid_slider, float treble_slider) 345 { 346 eq4band.setParameters(bass_slider, mid_slider, treble_slider, 0.0f); 347 eq4band2.setParameters(bass_slider, mid_slider, treble_slider, 0.0f); 348 } 349 350 void ProteusAudioProcessor::loadConfig(File configFile) 351 { 352 this->suspendProcessing(true); 353 pauseVolume = 3; 354 String path = configFile.getFullPathName(); 355 char_filename = path.toUTF8(); 356 357 LSTM.reset(); 358 LSTM2.reset(); 359 360 LSTM.load_json(char_filename); 361 LSTM2.load_json(char_filename); 362 363 if (LSTM.input_size == 1) { 364 conditioned = false; 365 } else { 366 conditioned = true; 367 } 368 369 //saved_model = configFile; 370 model_loaded = true; 371 this->suspendProcessing(false); 372 } 373 374 375 376 //============================================================================== 377 // This creates new instances of the plugin.. 378 AudioProcessor* JUCE_CALLTYPE createPluginFilter() 379 { 380 return new ProteusAudioProcessor(); 381 }