Don't know if this is the done thing really, but I wanted to show off:
https://youtu.be/1kMHloRQLcM
Best posts made by Orvillain
-
I wrote a reverbposted in C++ Development
-
I wrote a bbd delayposted in C++ Development
Again, wasn't sure where to put this. But I created my own node.
Modelled analog bucket brigade delay. I'm starting to build up quite a nice collection of delay and reverb utilities now!
-
RE: I wrote a reverbposted in C++ Development
@Chazrox I might do a video or two on everything I've learned!
-
RE: Third party HISE developersposted in General Questions
I'm actually moving into more JUCE C++ based projects now. But I've spent 18 years in music tech. Used to work for FXpansion, then ROLI, then inMusic until mid last year when I made the transition to developer. I've got a couple of HISE projects on the go right now - more synths and effects than sample libraries at the moment, but I've done sample libraries throughout my career, with a specific focus in drum libraries. I have a few Kontakt ports in the pipeline for this year too.
Eventually will launch my own plugin company as well. That is the goal.
-
RE: Orv's ScriptNode+SNEX Journeyposted in ScriptNode
Lesson 5 - SNEX code in a bit more detail.
So I'm by no means an expert in C or C++ - in fact I only just recently started learning it. But here's what I've sussed out in regards to the HISE template.... and template is exactly the right word, because the first line is:
template <int NV> struct audio_loaderSomewhere under the hood, HISE must be setup to send in an integer into any SNEX node, that integer corresponding to a voice. NV = new voice perhaps, or number of voices ????
The line above declares a template that takes this NV integer in, and creates a struct called audio_loader for each instance of NV. Indeed we can prove this by running the following code:
template <int NV> struct audio_loader { SNEX_NODE(audio_loader); ExternalData data; double note = 0.0; // Initialise the processing specs here void prepare(PrepareSpecs ps) { } // Reset the processing pipeline here void reset() { } // Process the signal here template <typename ProcessDataType> void process(ProcessDataType& data) { } // Process the signal as frame here template <int C> void processFrame(span<float, C>& data) { } // Process the MIDI events here void handleHiseEvent(HiseEvent& e) { double note = e.getNoteNumber(); Console.print(note); } // Use this function to setup the external data void setExternalData(const ExternalData& d, int index) { data = d; } // Set the parameters here template <int P> void setParameter(double v) { } };There are only three things happening here:
- We set the ExternalData as in a previous post.
- We establish a variable with the datatype of double called 'note' and we initialise it as 0.0. But this value will never hold because....
- In the handleHiseEvent() method, we use e.getNoteNumber() and we assign this to the note variable. We then print the note variable out inside of the handleHiseEvent() method.
Now when we run this script, any time we play a midi note, the console will show us the note number that we pressed. This is even true if you play chords, or in a scenario where no note off events occur.
That's a long winded way of saying that a SNEX node is run for each active voice; at least when it is within a ScriptNode Synthesiser dsp network.
The next line in the script after the template is established is:
SNEX_NODE(audio_loader);This is pretty straight forward. The text you pass here has to match the name of the script loaded inside your SNEX node - not the name of the SNEX node itself.

Here you can see my SNEX node is just called: snex_node.
But the script loaded into it is called audio_loader, and so the reference to SNEX_NODE inside the script has to also reference audio_loader.
-
RE: Need filmstrip animationsposted in General Questions
@d-healey I really like that UI. Very simple, accessible, and smooth looking - for lack of a better word!
-
RE: Third party HISE developersposted in General Questions
@HISEnberg said in Third party HISE developers:
A bit abashed posting here with so much talent but here it goes!
Wouldn't worry about that, you've been very helpful in getting me up and running in various threads! So thanks! (and to everyone else also!)
-
RE: Transient detection within a loaded sampler - SNEX ????posted in General Questions
@HISEnberg
Yes I wrote a custom transient detector in a c++ node, and made sure it utilised an audio file, which I can load in my UI using the audio waveform floating tile.I implemented spectral flux extraction:
- Take your audio.
- Perform an FFT on it.
- Extract the spectral flux envelope from the FFT.
- Downsample the spectral flux envelope (optional but can help accuracy)
- Perform peak picking on the spectral flux envelope.
I used the stock JUCE FFT processor.
-
RE: Can We PLEASE Just Get This Feature DONEposted in Feature Requests
Free mankini with every commercial license???
-
RE: I wrote a reverbposted in C++ Development
@Chazrox said in I wrote a reverb:
@Orvillain Please.
I've been waiting for some dsp videos! I've been watching ADC's everyday on baby topics just to familiarize myself with the lingo and what nots. I think im ready to start diving in! There are some pretty wicked dsp guys in here for sure and I'd love to get some tutuorials for writing c++ nodes.There's two guys who got me started in this. One is a dude called Geraint Luff aka SignalSmith. This is probably his most accessible video:
https://youtu.be/6ZK2GoiyotkThen the other guy of course is Sean Costello of ValhallaDSP fame:
https://valhalladsp.com/2021/09/22/getting-started-with-reverb-design-part-2-the-foundations/
https://valhalladsp.com/2021/09/23/getting-started-with-reverb-design-part-3-online-resources/In essence, here's the journey; assuming you know at least a little bit of C++
- Learn how to create a ring buffer (aka my Ring Delay thread)
- Learn how to create an all-pass filter using a ring buffer.
- Understand how fractional delays work, and the various types of interpolation.
- Learn how to manage feedback loops.
Loads of resources out there for sure!
Latest posts made by Orvillain
-
RE: Loading wavetables by drag-and-drop takes a long time??posted in General Questions
@dannytaurus said in Loading wavetables by drag-and-drop takes a long time??:
@Orvillain Weird. I'll try it out here again and see if I get the same result.
Is yours a standard mono, 'power of 2' file?
Yeppers.
-
RE: Loading wavetables by drag-and-drop takes a long time??posted in General Questions
@dannytaurus said in Loading wavetables by drag-and-drop takes a long time??:
@Orvillain To be clear, I was dropping a prepared wavetable WAV into the Wavetable Synth.
I'm not sure about the Wavetable Creator.
Are you dropping a wavetable WAV or just a plain WAV and hoping to make it into an interesting wavetable?
I have no idea how the Wavetable Creator works, or what it's for!

A wavetable wav. It sounds different when it is saved as a HWT. Very odd.
-
RE: Loading wavetables by drag-and-drop takes a long time??posted in General Questions
@dannytaurus Hilariously.... they don't sound the same!! The WAV file sounds markedly different to the HWT file here!
-
RE: Loading wavetables by drag-and-drop takes a long time??posted in General Questions
@dannytaurus You legend, cheers!! Will try it out!
Dohhh.. I was even posting in that thread, haha!
-
Loading wavetables by drag-and-drop takes a long time??posted in General Questions
When I drag and drop a wav file into the wavetable synth, it takes quite a while to process it into a wavetable. Is there a way to only need to do this once, and then cache the result, or better yet, save the resutl out as a HWT file??
I'm not having much luck with the wavetable creator. In resample mode it just keeps crashing. So I'm looking into other waves to convert my wav files into wavetables.
-
RE: Crash when loading files into Wavetable Creator (Resample Mode)posted in Bug Reports
For me it crashes whenever I try to load a 44.1kHz sample into it.
-
RE: Crash when loading files into Wavetable Creator (Resample Mode)posted in Bug Reports
Still crashes. Any word on this??
-
RE: Using custom preset system - as in the actual presets themselves, not a browserposted in General Questions
It's like this ..... I have an external arppegiator triggering my synth... I click my left/right arrows to change preset.... and because I use a custom data model, I have to tap into the pre/post callbacks.... so here's what I get:
synth notes triggering.... click the arrow....
Interface: preLoadCallback triggered - no synth notes triggering when this is running
Interface: onPresetLoad triggered - no synth notes triggering when this is running
Once the onPresetLoad method is finished, a midi note does sneak through into the synth....Then this callback fires:
Interface: postLoadCallback triggered
This kills the previous notes, and triggers the new ones.....Here is my full loadGlobalPreset method:
inline function loadGlobalPreset(obj) { local samplemaps = obj.samplemaps; local wavetables = obj.wavetables; local params = obj.parameters; local fxSelections = obj.fxSelections; local fxChainOrder = obj.fxChainOrder; lastLoadParams = params; // Restore samplemaps UISoundSelector.syncSamplerMenu(1, samplemaps[0]); UISoundSelector.syncSamplerMenu(2, samplemaps[1]); UISoundSelector.syncSamplerMenu(3, samplemaps[2]); // Restore wavetables UISoundSelector.syncSynthMenu(1, wavetables[0]); UISoundSelector.syncSynthMenu(2, wavetables[1]); UISoundSelector.syncSynthMenu(3, wavetables[2]); // Update all UI parameters - except the ones that are not tagged as saveInPreset UserPresetHandler.updateSaveInPresetComponents(params); // TODO: Restore custom samples // Fix-up FX menus by stable id, but only when they differ if (isDefined(fxSelections)) { for (i = 0; i < fxSelections.length; i++) { local sel = fxSelections[i]; if (!isDefined(sel) || !isDefined(sel.id)) continue; local targetId = (isDefined(sel.idName) && sel.idName != "") ? sel.idName : "empty"; local menu = Content.getComponent(sel.id); if (!isDefined(menu)) continue; // what saveInPreset restored (by index) local currentId = UIEffectDropDownMenu.getIdForIndex(menu.getValue()); if (currentId == undefined) currentId = "empty"; // only fire callback if mismatch if (currentId != targetId) UIEffectDropDownMenu.setMenuToId(sel.id, targetId, true); } } // Restore FX chain ordering (pageKey -> [4 slots]) if (isDefined(fxChainOrder)) { for (k in fxOrderKeys) { local key = fxOrderKeys[k]; local saved = fxChainOrder[key]; // expect an array of length 4 with unique 0..3 if (!isDefined(saved) || saved.length != 4) continue; UIEffectReordering.pageOrder[key] = saved; // update UI state UIEffectReordering.applyVisualOrder(key); // move panels PluginEffectReorder.apply(key, saved); // set DSP chain } } // Update all UI parameters - except the ones that are not tagged as saveInPreset //UserPresetHandler.updateSaveInPresetComponents(params); }It is doing quite a lot... and ultimately what happens is when I switch a preset, I get one voice that sounds one way... and then another voice that sounds completely different... like a voice is being allowed to be triggered before the preset is fully loaded.
It seems to be something related to my effect menus and/or effect re-ordering.
It is hard to explain. Might have to make a video. But any immediate thoughts??
-
RE: HISE Transformation to the new ageposted in AI discussion
@David-Healey said in HISE Transformation to the new age:
@dannytaurus said in HISE Transformation to the new age:
Nah, this is the start.
Tell me that again in 5 years
I'm not quite as cynical as I seem, I use AI all the time, I'm just cautious.
I also am concerned about AI inbreeding which is a real problem with limited solutions at the moment.
Honestly, this stuff isn't going away. It really isn't. This is the future of coding. Developers in future will be systems architects. They won't be solely opinionated language purists anymore.
-
RE: Agentic coding workflowsposted in AI discussion
I've used Antigravity to get myself up to speed with JUCE. I've built quite a few things outside of HISE using it. To the point where for my own company, I don't think I will need HISE. For freelance work, HISE is still a solid option. But I saw a competitor today show off his AI plugin generator, and it was very impressive.
In terms of HISE specific code I've been doing, certainly not entire namespaces or anything to do with the UI. But methods and functions here and there, that I knew what I wanted to do, but I just wanted AG to write it faster for me.
I've had more success with AG than ChatGPT on this stuff. Although ChatGPT is actually quite good at writing prompts.
And on a tagent slightly, but one of the biggest hurdles to writing complex projects in HISE is just how many languages and approaches you need to take command of. In C++ I can focus on JUCE and C++. In HISE, I need to learn HISEscript, C++, SNEX, simple markdown, and even css. This is a barrier to speed.