Super Compressor & Note Shaper for Y'all [Now with Scandalous Video]
-
Intro
The Note Expressor features provides complete, visual control for the user over every note. Unlike a compressor, this Effect triggers perfectly, and always has the correct gain.
Thank you, @Dominik-Mayer, for adding embedding so the video can be included; @Simon for the hosting; and @Christoph-Hart, @Matt_SF and @d-healey for technical assistance.
Snares Demo
In this clip, we'll use the Note Expressor to make a "perfect" Transient Shaper. Now it gets interesting…
Overview
If you think about it, is there really a need for so many different types of compressors and dynamics processors? Most of the variation comes from the fact that we don't know enough about the signal to do what we want (e.g. triggering, timing, gain precision).
But with MIDI and ARA, we can know everything. So why are we still building compressors?
The implementation in this example is for MIDI-triggered audio, and implemented in HISE. It's simple to implement in any environment (but requires a later version of JUCE for ARA).
It's been used on tracks by artists such as Marco Minnemann, Steve Morse and Peter Frampton.
Code
Scriptnode Network
HISEscript Code
Note, this is not a self-contained snippet; it employs Dynamic Contextual Interfaces. (Feel free to ask about anything.)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // // // MODEL MODULE - DYNAMICS PLAYGROUND [UI THREAD] // // // // // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////// TABLE UI CALLBACK /////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function DynPlayTableUI_Callback() { if ( (g_executionFlags.onInitComplete) && (PerformanceLoaded()) ){ if (IsDynPlaygroundTableClean()) { // Disable the knob. knob_MODEL_DynPlayground_UserMakeUpGain_GUI.set("enabled", false); // Disable the Network. UTILITY_SetEffectActivationState(fx_NODE_DynPlayground, false); } else { // Enable the knob. knob_MODEL_DynPlayground_UserMakeUpGain_GUI.set("enabled", true); // Enable the Network. UTILITY_SetEffectActivationState(fx_NODE_DynPlayground, true); // Compute the maximum dynamic gain, based on the new settings, and adjust the internal makeup gain. fx_NODE_DynPlayground.setAttribute (fx_NODE_DynPlayground.internalMakeupGain, ComputeDynamicRangeFactor(fx_NODE_DynPlayground)); } } } dynamicsPlaygroundTableObject.setContentCallback(DynPlayTableUI_Callback); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////// RESET TABLE FUNCTION /////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function ResetDynPlayTable () { // Erase all values. dynamicsPlaygroundTableObject.reset(); // Set it to the closest thing to unity. dynamicsPlaygroundTableObject.setTablePointsFromArray(DYN_PLAYGROUND_TABLE_INIT); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////// DETERMINE IF TABLE EDITED FUNCTION /////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function IsDynPlaygroundTableClean () { // ------------- Initialisation // Get an array of data points. local tableConfigurationArray = dynamicsPlaygroundTableObject.getTablePointsAsArray(); // Reset the table if it's fucked up. if (tableConfigurationArray.length < 2) { ResetDynPlayTable(); return true; } // ------------- Determining if Edited // If there are more than two points, then the table is dirty. if (tableConfigurationArray.length > 2) return false; // There's two points; compare with the default values. if ( tableConfigurationArray[0][0] == DYN_PLAYGROUND_TABLE_INIT[0][0] && tableConfigurationArray[0][1] == DYN_PLAYGROUND_TABLE_INIT[0][1] && tableConfigurationArray[0][2] == DYN_PLAYGROUND_TABLE_INIT[0][2] && tableConfigurationArray[1][0] == DYN_PLAYGROUND_TABLE_INIT[1][0] && tableConfigurationArray[1][1] == DYN_PLAYGROUND_TABLE_INIT[1][1] && tableConfigurationArray[1][2] == DYN_PLAYGROUND_TABLE_INIT[1][2] ){ return true; } else { return false; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////// ENABLE UI FUNCTION ///////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function Enable_ModellingDynPlay_UI(enableUI) { knob_MODEL_DynPlayground_UserMakeUpGain_GUI.set("enabled", enableUI); table_MODEL_DynPlayground_Table_GUI.set("enabled", enableUI); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////// STANDARD LIBRARY: CORE FUNCTIONS ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function TRANSFORM_Architect_SUBMOD_DynPlayground_PerformOp (moduleState) { // ============================================== Reset Ops if (moduleState == "init" || moduleState == "ready") { // ------------- Disabling the Network // Disable the Node processor. UTILITY_SetEffectActivationState(fx_NODE_DynPlayground, false); // ------------- Disabling Widgets // Disable the UI widgets. Enable_ModellingDynPlay_UI (false); // ------------- User Makeup Gain // Set the knob to zero. knob_MODEL_DynPlayground_UserMakeUpGain_GUI.setValue(0); // Manually set the Network parameter. fx_NODE_DynPlayground.setAttribute (fx_NODE_DynPlayground.userMakeupGain, 0.0); // ------------- Table Topology // Set it to the closest thing to unity. ResetDynPlayTable(); // ------------- Internal Makeup Gain fx_NODE_DynPlayground.setAttribute (fx_NODE_DynPlayground.internalMakeupGain, 0.0); } // ======================================== Specific Ops switch (moduleState) { case "init": // ------------- Table Length // Set the table length to zero. fx_NODE_DynPlayground.setAttribute (fx_NODE_DynPlayground.EnvDuration, 0); break; case "ready": // If there are resonance parameters, load them in. if (isDefined (g_articulationData.dynamicsSuite)){ // ------------- Enabling Widgets // Disable the knob. knob_MODEL_DynPlayground_UserMakeUpGain_GUI.set("enabled", false); // Enable the table. table_MODEL_DynPlayground_Table_GUI.set("enabled", true); // ------------- Table Length // Get the length of the first sample. local sampleLengthInSamples = global_allHits[0].get(Sampler.SampleEnd); // Convert it to milliseconds. local sampleLengthInMs = Engine.getMilliSecondsForSamples(sampleLengthInSamples); // Set the table length. fx_NODE_DynPlayground.setAttribute (fx_NODE_DynPlayground.EnvDuration, sampleLengthInMs); // ------------- Internal Makeup Gain // Set the table parameter for any initial makeup gain specified by the Encoder. fx_NODE_DynPlayground.setAttribute (fx_NODE_DynPlayground.internalMakeupGain, g_articulationData.dynamicsSuite.internalMakeupGain); } break; case "user_poweroff": // Disable the processor. UTILITY_SetEffectActivationState(fx_NODE_DynPlayground, false); break; case "user_poweron": // Only do something if the knob is not at zero; activate the Node. if ( (MODULE_GetModuleActivationStateByID("panel_MODULE_MODEL")) && (!IsDynPlaygroundTableClean()) ){ // Activate the Node. UTILITY_SetEffectActivationState(fx_NODE_DynPlayground, true); } break; } }
-
@clevername27 perhaps load the screen cap movie to your server and point at it here?
-
@Lindon I appreciate that. If HISE management isn't interested, I'm not going to spend several hours preparing this stuff.
-
@clevername27 Well I'm pretty interested if that helps at all...
-
@clevername27 If you have a video file ready, just drop it here and I will host it: https://simondalzell.com/index.php/s/MP6AnNwJSEgsxQT
-
@Lindon @clevername27 me too!
-
@clevername27 Very interesting! Are you using the stock dynamic to build some improvements around it or running your own comp?
-
-
New embeds are very cool.
-
This post is deleted! -
This post is deleted! -
@Simon @clevername27 Getting no sound here... Is this just me?
-
@ustk Same
-
-
@clevername27 Oh ok I thought it was the new video stuff broken
-
-
yes yes now I understand! It unlocked some ideas for me
-
@clevername27 still no sound here...
-
@Lindon Skip to 00:42
-
@Lindon no sound here either, even after 0.42