What is a sensible number of samplers in a single plugin?
-
Keep in mind that HISE has something like 256 internal MIDI channels.
If you then add a script envelope modulator (this is completely undocumented other than what you find on the forum here), you're now in the world of polyphonic modulation.
Then, use the MIDI node (with the default MPE set to on) to do any kind of modulation you want. Trigger it using CC. You'll have to call Synth.sendController in your UI controls, intercept it down the line in another MIDI processor and adjust its channel. This sounds like it'll be tricky.
But then you can use the channel-split controllers to communicate with your modulators. Controllers on each channel will only affect notes that were played on that channel. This sounds like it'll be quite the fun to set up and get working.
You can still use multiple samplers if you want like 8 engines, these can be separate samplers if for whatever reason something doesn't work. Already 40 is a bit crazy, will eat up memory and be a PAIN to manage.
@Christoph-Hart can you please give this a read and see if I hallucinated anything,,,, And do you think that there is an easier way to send a virtual polyphonic value (channel-based cc# value) to a polyphonic modulator than the current method of calling Synth.sendController() and intercepting it down the line because Synth.sendController() doesn't take MIDI channel as parameter?
-
@Orvillain Would love to check out what you're up to.
-
This sounds like an interesting path for exploration. But reading between the lines, this wouldn't give per-sample envelopes right? It might be a way to get per-voice envelopes, but that isn't quite the same thing no?
I have finished the night with my prototype up and running, in some sense. I don't know what I did, but my project started to compile much quicker after a while, and I have managed to have 128 samplers loaded up at once with no more stability problems. I'm perplexed.
@clevername27 - throw us a private message!
-
@Orvillain generally ----- 16 samplers is a point where HISE is comfortable, I once tried 32 samplers and HISE started to give up on me....but it depends on what's in each sampler..
-
128 samplers is definitely overkill - the sampler module is designed for the purpose of streaming large sample sets so if you throw only a single one shot at it you’re definitely wasting a lot of resources (mostly RAM, take a look at your task manager after you created 128 instances)…
Loopers are a bit less resource-hungry but if you want to scale that with a good performance you should look into creating a custom sample player with scriptnode. I‘ve created a drum plugin with 36 individual channels like this and the performance is very close to the optimum (which would be handcoded c++).
-
@Christoph-Hart said in What is a sensible number of samplers in a single plugin?:
128 samplers is definitely overkill - the sampler module is designed for the purpose of streaming large sample sets so if you throw only a single one shot at it you’re definitely wasting a lot of resources (mostly RAM, take a look at your task manager after you created 128 instances)…
Loopers are a bit less resource-hungry but if you want to scale that with a good performance you should look into creating a custom sample player with scriptnode. I‘ve created a drum plugin with 36 individual channels like this and the performance is very close to the optimum (which would be handcoded c++).
Nice one, cheers! I've not looked at script node yet, guess I'll start digging into that this week.
-
Hmmm, So 128 ScriptNode Synths... each of them with a "file player" inside, gives about 500mb of RAM. Which isn't too bad I don't think.
Building my own node network for the kind of playback sampler I am looking for, seems viable.
-
@Orvillain that's a lot of RAM. Will users only load a single instance per project?
-
@d-healey said in What is a sensible number of samplers in a single plugin?:
@Orvillain that's a lot of RAM. Will users only load a single instance per project?
Well here an empty Groove Agent SE5 is coming in around 300mb by itself. I'd like to get that number down, sure. But 500mb is way more acceptable than the 3.2gb required to do this with the HISE Sampler.
-
@Orvillain yeah 300 is pretty chunky too. Do you really need 128?
-
16 pads x 8 layers.
I noticed one thing though. If I put 8 file players in a single ScriptNode instance (rather than having 128 ScriptNode instances), then that seems to bring down the memory. Still doing more testing, but 128 file_player nodes, is showing the entire HISE memory footprint of 105mb. Which is a marked improvement!
I just need to see if I can get the functionality from the HISE file_player. For instance, right now I cannot see a way to stop it from looping.
Promising stuff though.
-
How can I tell a specific instance of a file_player within a ScriptNode, to load a file from an absolute path??
More to the point - how can I iterate through properties and functions for the ScriptNode instance, from my Interface onInit method?
-
@Orvillain it depends on the type of property. Parameter sliders need to be connected to a container meta parameter and can then be accessed through the usual HISE attribute system.
Any complex data (table, slider packs, audio files) need to be registered as external data slot and then can be modified using the scripting API (just like you would load a file into the inbuilt loop player.
gives about 500mb of RAM
This is way too much but you should be able to bring this down by lowering the voice limit. If you have 128 instances, you don't need 256 voice polyphony so with 16 voices per sampler you can cut it down significantly.
-
The way I'm thinking is I somehow need to travese down this tree:
<ScriptNode>container.chain.softbypass_switch9.sb_container.sb1.file_playerAnd that would allow me to do something like:
abs_path = FileSystem.fromAbsolutePath(file_obj.fileName); parsed = [this_sampler.parseSampleFile(abs_path)]; file_player.loadSampleMapFromJSON(parsed);
Or whatever the call is to load a file into the file_player.
Sort of pseudo code, similar to what I've been doing with the SAMPLER, but hope it makes sense.If I do this:
const var ScriptnodeSynthesiser1 = Synth.getChildSynth("Scriptnode Synthesiser1"); const attr_count = ScriptnodeSynthesiser1.getNumAttributes(); for (i = 0; i < attr_count; i++) { var attr = ScriptnodeSynthesiser1.getAttributeId(i); Console.print(attr); }
Then I just get these printed in the Console:
Interface: Gain
Interface: Balance
Interface: VoiceLimit
Interface: KillFadeTime
Interface: Sample SelectSample Select is a custom meta parameter. So I'd already figured that bit out. Really what I'm looking to get is an object reference to the internal nodes within the ScriptNode.
This is where I'm currently at. You can see Sample Select at the top. You can also see that my file_player nodes are all set to an external audio file slot.
If you could help me get the object reference I'm looking for, I'm pretty sure I can figure the rest out from there. Does it have anything to do with ScriptnodeSynthesiser1.ScriptParameters; ?
-
Are you using the clone container? That might reduce some of the complexity
-
@d-healey Not yet. It isn't really what I'm after right now. I'm just trying to make sure I understand how to iterate through the node tree, get and set data within it, and then I'll look at optimization and stuff later.
I'm just trying to sus out how to achieve this before I invest too much time in it really.
PS: Been rinsing your HISE videos on Youtube. I'm half way through the paint routines one, and have learnt a lot! Thanks very much!
-
Ahhhh.. I imagine I need to use Engine.getDspNetworkReference(String processorId, String id)
in order to access the actual node network? I'll try that tomorrow.And obviousy then, I finally check the docs
https://docs.hise.audio/scripting/scripting-api/dspnetwork/index.html
I'll give this a thorough read tomorrow too. Looks like this is what I want.
-
@Christoph-Hart
Could you let me know what I'm doing wrong here?var samplepath = "D:\Samples\Drums\Hits\Reverb Drum Machines\MXR Drum Computer\Reverb MXR Drum Computer Sample Pack_Audio Files\Reverb MXR Drum Computer Sample Pack_CHH.wav"; const var s = Synth.getAudioSampleProcessor("Scriptnode Synthesiser1"); const slot = s.getAudioFile(0); slot.loadFile("{XYZ::SingleSample}" + samplepath);
I do actually see a change:
But it hasn't actually loaded it. Just applied a label.
If I do this:
var samplepath = "D:\Samples\Drums\Hits\Reverb Drum Machines\MXR Drum Computer\Reverb MXR Drum Computer Sample Pack_Audio Files\Reverb MXR Drum Computer Sample Pack_CHH.wav"; const var s = Synth.getAudioSampleProcessor("Scriptnode Synthesiser1"); const slot = s.getAudioFile(0); slot.loadFile(samplepath);
Then HISE just crashes.
And if I do this:
const var samplepath = "D:\Samples\Drums\Hits\Reverb Drum Machines\MXR Drum Computer\Reverb MXR Drum Computer Sample Pack_Audio Files\Reverb MXR Drum Computer Sample Pack_CHH.wav"; var abs_path = FileSystem.fromAbsolutePath(samplepath); var s = Synth.getAudioSampleProcessor("Scriptnode Synthesiser1"); const slot = s.getAudioFile(0); slot.loadFile(abs_path); ;
Then I get this:
Again, it doesn't load the file... but does put an object reference in the filename box.
-
Bah! Figured it out:
You can see.. the filepath needed the backslashes escaping. I have to do this when using Python all the time, and it just occurred to me to try it in HISE too.
Works fine. Sample loads. I've got enough to go on now!
-
Actually @Christoph-Hart if you do see this, how can I disable looping on the file_player object?