Iteratively updating sample properties
-
Hullo. So I have this code:
Content.makeFrontInterface(600, 600); var samplers = []; inline function load_sample(file_obj) { reg pad_id = this.get("id").split("_")[2]; reg this_sampler = samplers[pad_id]; this_sampler.clearSampleMap(); reg abs_path = FileSystem.fromAbsolutePath(file_obj.fileName); reg parsed = [this_sampler.parseSampleFile(abs_path)]; this_sampler.loadSampleMapFromJSON(parsed); // sample should be loaded at this point //setSoundPropertyForAllSamples will allow me to change the root note for all //samples in a particular sampler. //But ideally I'd like to target individual samples. //this_sampler.setSoundPropertyForAllSamples(2, 60); //This creates a selection of all samples and allows me to iterate around them. //But I don't know how to set the different parameters from this point. for(sample in this_sampler.createSelection(".*")) { Console.print(sample); } } for (i = 0; i <16; i++) { var current_pad_panel = Content.getComponent("pad_panel_" + i); var current_sampler = Synth.getSampler("Sampler" + i); samplers[i] = current_sampler; current_pad_panel.setFileDropCallback("Drop Only", "*.wav", load_sample); }
So what I'm doing is this:
- 16 "pad" panels in the UI all with the id: 'pad_panel_xx' where xx is the id (0-15)
- 16 samplers in the module tree all with the id: 'Samplerxx' where xx is the id (0-15)
- I get the panel and sampler in my main for loop. I store the sampler to a global array.
- I then attach a FileDropCallback method to each panel.
- Inside the callback, I get a reference to the correct sampler by splitting the panel's id by underscores, and then using the digits at the end of the string to get the sampler from the global array.
- This allows me to do stuff to the sampler from within the callback.
- At this point, I can easily load a sample to a sampler.
TLDR; I've got drag and drop loading of samples working for 16 drum-pads in my plugin.
What I want to do now is update the sample properties for each sampler. I wanted to boilerplate this by just changing the root note.
I can change the root note by using setSoundPropertyForAllSamples, however I'd prefer to adjust each sample individually, because eventually I intend to perform auto-velocity splits on future additional samples dragged to that pad.
Long and short of it is, is there a good receipe for iterating through all samples within a sampler, and adjusting the samples properties? Things like root, lowKey, hiKey, sampleStart, sampleEnd, etc.
Cheers!
-
samplers
should be aconst
Uselocal
within inline functions@Orvillain said in Iteratively updating sample properties:
Inside the callback, I get a reference to the correct sampler by splitting the panel's id by underscores,
Can't you use something like
myPanelsArray.indexOf(thisPanel)
instead?@Orvillain said in Iteratively updating sample properties:
is there a good receipe for iterating through all samples within a sampler, and adjusting the samples properties?
The info you need should be in this thread - https://forum.hise.audio/topic/64/fun-with-regex
-
@d-healey said in Iteratively updating sample properties:
The info you need should be in this thread - https://forum.hise.audio/topic/64/fun-with-regex
Are you referring to Christoph's snippet:
for(sample in Sampler.createSelection(".*")) sample.set(Sampler.RootKey, sample.get(Sampler.RootKey);
I did find that thread in a search previously, as you might tell from my commented out code in my first post.
I've tried this:
for(sample in this_sampler.createSelection(".*")) { Console.print(sample.get(this_sampler.RootKey)); }
And I get this:
Interface:! Warning: undefined parameter 0 : Line 28, column 27 {SW50ZXJmYWNlfHwxMDY0fDI4fDI3} Interface: 0
It would be super useful if someone could post a code snippet that just demonstrates how these selection and .set and .get methods are meant to work with each other. Don't think I'm quite getting it.
-
The reason for your error (well the error tells you) is that
this_sampler.RootKey
isn't defined, as in that is not valid script.The first problem is what you are looking for is a constant of the Sampler class, not your particular sampler. The second issue is that Christoph made a typo and the constant you want is called
Root
. You can use the autocomplete in HISE to help you here. -
@d-healey sorry, I'm a bit confused. There's something I am missing I guess.
I want to get these:
And I was under the impression that these would be attributes of my particular sample instances inside of my samplemap ?
I'm not looking to adjust the global sampler settings.
-
@Orvillain Did you try what I put above? The selection is made on your specific sampler, but the constants (which are just numbers) are part of the Sampler class.
-
I tried this:
for(sample in this_sampler.createSelection(".*")) { sample.set(Sampler.Root, 36); }
And my root notes still end up as E3, so I guess it didn't work.
-
@Orvillain Have you checked that the selection is working and returns an array of samples?
-
I get an object reference - Object 0x23127408
I guess I have made the assumption that this is my sample object.
Again, my code snippet:
for(sample in this_sampler.createSelection(".*")) { Console.print(sample); //sample.set(Sampler.Root, 36); }
If I do this:
Console.print(this_sampler.createSelection(".*"));
Then yes, I get an array.
this_sampler is definitely an instance of my sampler, because the code prior works fine. It loads the samples, and I can even do what I want to do by doing this:
this_sampler.setSoundPropertyForAllSamples(4, 60 + parseInt(pad_id)); this_sampler.setSoundPropertyForAllSamples(3, 60 + parseInt(pad_id)); this_sampler.setSoundPropertyForAllSamples(2, 60 + parseInt(pad_id));
This bit of code works fine. But it will set all samples on a pad to the same root/hi/lo values, and eventually that isn't what I want.
-
@Orvillain Do other constants work?
-
They don't no.
Am I to assume then that this syntax is correct for the actual setting of the property?
sample.set(Sampler.HiKey, 36);
-
This post is deleted! -
@Orvillain said in Iteratively updating sample properties:
They don't no.
Am I to assume then that this syntax is correct for the actual setting of the property?
sample.set(Sampler.HiKey, 36);
Yes that's what I'm doing here - but I haven't tried changing the key number. Does changing the Pitch work for you?
-
@d-healey said in Iteratively updating sample properties:
@Orvillain said in Iteratively updating sample properties:
They don't no.
Am I to assume then that this syntax is correct for the actual setting of the property?
sample.set(Sampler.HiKey, 36);
Yes that's what I'm doing here - but I haven't tried changing the key number. Does changing the Pitch work for you?
Sorry, had to pop away. But here's what I've got:
for(sample in this_sampler.createSelection(".*")) { sample.set(Sampler.Pitch, 24); //sample.set(Sampler.LoKey, 60 + parseInt(pad_id)); //sample.set(Sampler.HiKey, 60 + parseInt(pad_id)); //sample.set(Sampler.Root, 60 + parseInt(pad_id)); }
But there is something interesting going on. Let me see if I can breakdown what is happening.
First... I load my plugin from init. All my samplers are empty.
I drag a sample to one of my pads, and it loads:
But when I select the sample in the editor, you can see that Pitch is still at 0ct.
I drag another sample onto the same pad (and thus same sampler) and I get this:
Notice my sample is not selected in the editor, but the pitch box does say 24ct, as I was expecting.
But... select the sample, and....
It resets back to 0ct.
So... it seems to me something isn't being applied correctly.
Again, here is my whole code:
Content.makeFrontInterface(600, 600); const var samplers = []; inline function load_sample(file_obj) { local pad_id = this.get("id").split("_")[2]; local this_sampler = samplers[pad_id]; this_sampler.clearSampleMap(); local abs_path = FileSystem.fromAbsolutePath(file_obj.fileName); local parsed = [this_sampler.parseSampleFile(abs_path)]; this_sampler.loadSampleMapFromJSON(parsed); // I think this is supposed to work. But it doesn't. for(sample in this_sampler.createSelection(".*")) { sample.set(Sampler.Pitch, 24); //sample.set(Sampler.LoKey, 60 + parseInt(pad_id)); //sample.set(Sampler.HiKey, 60 + parseInt(pad_id)); //sample.set(Sampler.Root, 60 + parseInt(pad_id)); } } for (i = 0; i <16; i++) { var current_pad_panel = Content.getComponent("pad_panel_" + i); var current_sampler = Synth.getSampler("Sampler" + i); samplers[i] = current_sampler; current_pad_panel.setFileDropCallback("Drop Only", "*.wav", load_sample); }
Syntax and standards aside, can you spot anything that would cause this kind of issue?
Here is the HISE snippet:
HiseSnippet 2708.3oc6c1ubabaD.+nkNWKFmLIo9O5ezNCFNcZnhcYHonHkpSmP8gUjRLsUEcbSGqTMP2AJhpiGt4NbRlMiadU5iPeD7iReDxaP6h6NxCjRTQhlzwLb4XKc36cWfE3GANaruuvhEDH7Mxrzy55wLxbWylccks2pMk6Zr21P7l1rVzPGowlc8nAALaiLYV3KUImYoEMh97iewlTGpqEKMJCimK3VrGy6vkowte8ul63rC0l8LdGsbWo9dVB2sDNhPPTVvrngG05T5IrmPUY6VlFYt8ir4RgeSIUxBLxr3lB6tMaKN2MN+OmGvO1goBTxnITQwQuivwVIwpXM1pM2wd+dpbfgQl6sepAXgXCv8Lavs48iO0P7gQIPRKgt8HysFT7VX.wqjt3UTS7tDQJilHsXrH8QlMs74dxzTTxy6Ytmqj42hBlccQINuF2528qL2R.4vUVnC8T1N9Pf9kHe0hEe.A9wxOLaVvzGHImQ8IAzNdNL+.xel7huCRg65vcYjVgtVRtvk3Hn1GEmo7s3NriDG+OVN62mcIGgE0g3AoxsgBKayCJbBSlOG2N2xEB7b3vyGka4WTFp1jbqxTRk4CkoWa+h3ZQkO8bTvxgQ8aFEnA0K+x8qG5wAG4Qksg5XGPlZ1MPx5TnkunyFGGHbBkr8gT6KuETOnFWkVCdTev3oT5AZwnniaQUEmuWCs7EjMkcounAV5NeUym9j7wUqpYxtzm8YIJHInsHzwlbLKxZBMKUFYJHdBtqLNuALYSQnqZjgGyW1cGg+FNNwsP.4bvGhPcbDmS5vHRAwpM08D3o1LhuPHItBIzoI7UYJp5RJH2kPUJqjaE5j1cWPkmMCkDtMCJQWxdehMwgeZTcKo9PGITTa9Yb6PvZkTaQkZ.qvUJ04qnFuQterwFFHlOtedYk84FUQqLopnxWQEkzmsmpqw8z3NH3OAgddB0XEvxbtv+zBjH6ljXKXAtehDLJfcOeRWMXuGbHrOCldnIygE4NkOWgOM2xKmcIvAZo37nj37MSx99boU6GPJWQIP86FGHKOV70rtWgZb4kZW93TpCfgVWQgdU1WcwILj97SNg4CtM14YmAyEEMaAuEIND3TysNE7QxRfOeOI5WpO2r4St1SnrTzhaE7bnceB3in7T+l8xWZDZ0CHkhlfTIPQZmxkJOGp5hOjvIedopvut+8iTI0rmVg99fRoTV3utLGHm8lBFD9sDc7DtPf745miixAsKWY9zqfTcHVdgBmzIjOWxC8KWesj+cP9GpFfzufPo5SUSmsM3SrE3teLrRa9bpPjm55zM2CH49zBmSOCdPa59kGUU0PDFv5WOZ82PIdU19CDDtJC9ScyGYsfTHCmTqVWZZJCnuvQo6WVxJNB+qpf4cC6bLy+Av5aNgr9YDVbcvUrMG8J15.EVw8mZYT3tmKW9TOl6nvLLRFD.O8M6sMURUKymDWxLSbkHjYa1Y.yT7h9KYtMK3TovCHO5OxwHSVYTpueOj.U2fA2VES5fphFuLks52Wua+.+6+U8y41x1oo92p2lwOosTOFI6kxHnqn0X502FnPf1R4uFP9CjcEmw7M3vJs8n1tqYkxqsd0UVqX0xZITdnTLtoJSIck4uOiqLk0TlW6LiqLqnoL0CmwUlJiRYd84ydJypiZX1rnxTcTS.LKpL0F0TyyhJyZixm4+5M6oLqOJelYEk4CzWzr3nbZlI0lRixqYlTaJOJ2FC6YPsYkQ42LSpMUFkeyLo1r5n7adWPat3Fc9glMD1gNT4f66pZylSR.9pcCrYmpMzzMfK6puYzSrMi85JhejYzV0b4x3stDYD9BfSCYLYKreeyG0pEyRlJfKZty2Nc1uZ8l+2F27erYSoOi1g6dRxlUDICYMSBUbRbRBdW6SRXeeVz1yx+mZY6002LDrQ9CF6+odTSsQGQn6.sUhje.yiQkP2rVYtS8CN3K8EgdCWpe7KhFT7LevkALE5I7TWFXqk553V9hffVf5DUWA5Isen+IJaUZLGv.etfAi6Igcf9aWvsWsYFYxn1rg.lp+ka0fJ84uTO2QsRwmQi5iAG7nvkFJb4gBuxPgqLT3UGJb0gBWKMbFyAG+cmq2tuzf5EMSmVN2jeR+cdONF8y7ouYMpo0Nun+J8LVKgeGsZ5RNLlaOsNenEud9aW8wWMCLC5.Gm0R8jwlbUG1ibOC7LgXTx3Gatc7wL1K1RCHkMDtBu1BWt0f9AI62ntreoJzFRI3FlFy8pe.ygQCX5KO9XtKi5On68MxVT5FezdWZ+0uwLVbIpo1HuI8auUGlckqBtv0ZUvIt7N9qH9V0z8AIqMRfV2W9Nd+7cMilMmnV78mKQ8.QnDVTs2BalvpeMgU7sX5qAdK05pwgKpBqDnlLW6n.+O3SRhk5sfoJwR8RzvpWUA5VxyQadelEXtpUShf6bfkhczGRG.bEJQBVjyH9nS5nVXxL1xsUXfL9zgMZBq.EOWSrjMDFQrD0fasu.Lof2jZpGyGpAJP6zgNfkNSb6AqltSxQbaj4yM29OcXxAdd319gcBNbWtL9QRCpUaXNuC23TJm7sGTp3gperK+uTrj5DfLdr34JkKV91kmD3Gf.Qm6XZJIA9gndFQjzWOUk5oLaG5AeqAXXfxvMFfikPvQDbbHvwaOk.GeaBCN0+9oyj.fkQ.v2b.ved25iEla15ioIb2TW.ey.5Few6WTPbJcbnEzUVieZ.NSyRE.k4xf215ZAu8UeMYeluUXPW2CaPe4yI+QxyDP5bcFNk30ifyrT4Z8H3hiOleKJ9X9sEMqVIEeSoH5vaKLFvakQ3MDdCg2lSf2VAg2P3MDdCg2P3swBda22sf2VAg2P3MDdaNAdqBBugvaH7FBugvaSwcdCnzVoG8Vzy8g2VYzvaiywlVAg2P3MDdaNAdaUDdCg2P3MDdCg2ltvaUzf2pbs14swAdaUDdCg2P3s4D3spH7FBugvaH7FBuMVvaOVbMg2VUCda0T3sUmrGaZUDdCg2P3s4D3sZH7FBugvaH7FBuMEem2.JspZvaUSg2pNY24sZH7FBugvayIvaqgvaH7FBugvaH71MFdqoK0mU9ZBuUSCdS6evB0lr671ZH7FBugvayIvaqivaH7FBugvaH71z8cdaMM3s0Rg2VaxtyaqivaH7FBu8KS3se8E9O52hH8FRugzaH8FRuMceo2VWida8T5s0mHzauW++W5EueGP7MDeatAeCunFP7MDeCw2P7so6q8Vsho3avy8v2pUbBiug2xBH9FhuM2fugWyBH9Fhug3aH91z8EeqVIM7sRo3aklv3a38r.hug3ayM3a3Es.hug3aH9FhuMce02pUVCeqbJ9V4IL9FdSKf3aH91bC9FdUKf3aH9Fhug3aS228sZZW0B0RupEpsxDFeCuqEP7MDeatAeCurEP7MDeCw2P7so769l1ksPszKagZUlv3a3ss.hug3ayM3a30s.hug3aH9FhuMke22zttEpkdcKTa0qBe6sQWWGpku3HfJS5Kh5.uSTLf33FYcVxrgJLojwYTmvAH+5.q9djk0fU0EJX4wsfqLtErx3VvUG2BVcbKXswsfq8SWPEbzFgfOT7JFFFM1+QwdkYdTeuxEL9+TCVWXI
-
@Orvillain Ah I think I understand the problem now. I missed that this is meant to happen after you load a sample via drag/drop.
This is what is happening:
Load sample
Do the set sample stuff
Sometime later the sampler finishes loading the sample.You see HISE doesn't wait for the sample to load before the bit of code that you've written to change the sample properties. That code just fires right after you've told it to load the sample, but the sample is still loading at that point. You need to wait until the sample is loaded before trying to change its properties.
This is done using a panel and the loading callback: https://docs.hise.audio/scripting/scripting-api/scriptpanel/index.html#setloadingcallback
-
Ahhhhhhhh. Yes, that makes sense. I will read the API and try to implement this callback. My "pads" are panels already.
-
@Orvillain said in Iteratively updating sample properties:
My "pads" are panels already.
Btw, you can probably use a single panel for all your pads.
-
@d-healey said in Iteratively updating sample properties:
@Orvillain said in Iteratively updating sample properties:
My "pads" are panels already.
Btw, you can probably use a single panel for all your pads.
Thanks for the help on the setloadingcallback - I've got that working.
I guess my unfamiliarity with HISE is why I went with individual panels, but if you care to expand on how I might use a single panel, I'm all ears.
As it stands, I now have this:
Content.makeFrontInterface(600, 600); const var samplers = []; inline function load_sample(file_obj) { local pad_id = this.get("id").split("_")[2]; local this_sampler = samplers[pad_id]; this_sampler.clearSampleMap(); local abs_path = FileSystem.fromAbsolutePath(file_obj.fileName); local parsed = [this_sampler.parseSampleFile(abs_path)]; this_sampler.loadSampleMapFromJSON(parsed); } inline function set_sample_trigger_zones(isPreloading) { local pad_id = this.get("id").split("_")[2]; local this_sampler = samplers[pad_id]; if(!isPreloading) for(sample in this_sampler.createSelection(".*")) { sample.set(Sampler.LoKey, 60 + parseInt(pad_id)); sample.set(Sampler.HiKey, 60 + parseInt(pad_id)); sample.set(Sampler.Root, 60 + parseInt(pad_id)); } } inline function trigger_pad(event) { if (event.clicked) { local pad_id = this.get("id").split("_")[2]; local this_sampler = samplers[pad_id]; Synth.playNoteFromUI(1, 60 + parseInt(pad_id), 100); } } for (i = 0; i <16; i++) { var current_pad_panel = Content.getComponent("pad_panel_" + i); var current_sampler = Synth.getSampler("Sampler" + i); samplers[i] = current_sampler; current_pad_panel.setFileDropCallback("Drop Only", "*.wav", load_sample); current_pad_panel.setLoadingCallback(set_sample_trigger_zones); current_pad_panel.setMouseCallback(trigger_pad); }
And this basically gives me what I want. However, I suspect right now that my properties are being set 16 times, because the callback is triggered 16 times when I drop a wav file onto a panel.
-
@Orvillain said in Iteratively updating sample properties:
I guess my unfamiliarity with HISE is why I went with individual panels, but if you care to expand on how I might use a single panel, I'm all ears.
This should get you started
HiseSnippet 1334.3ocsW0uaaaCDmJMJnxaEaEXO.rAXExqtt1ooeflUz13jrErlVu3jrADTTvHQaQDYRCJ5XaLDf8O6OyKvdH1y1dC5tSTxRN1neXf4+H17te2w6adosVEvSRTZhi2QSFvINesamIRSTqHlPR1eGjv.ljGeTjP1ir8jArjDdHww4F+DhvwaUR5m+8EayhYx.dAIB4DkHf+ZQegofZ6W9Kh338Xg7iD8KgdyWtefR1REqFBVyMbaPFvBNm0i+FFBaEWhyZ6FJLJcGCyvS.LaqBmzIRMRZwehHQbVLGOzjzATjkLoUjHNrctmlPHNq1tvuug0u+N2CDghozK7+uMkAsPhxw.mU9XlTyu.SxojIsp0jtsam.sXfofCZOek69RCW2kAg5xlhEKYkCWyskBPHM06yNmumFNLUB+G2nQMJ7mpaUoBDtSLzKXZZaLC2j9bZtj83lVp9CTR3f+5V1qCxX+U8PlgUORcAWCxb+lyRWNrOjES.NaNGiCUilkQBdQRiVE2hEGeFjw8URKuL5nkJjwBIm1cnLvHTR50f3Gjaq0.2IdHuZk+nhGvLQEyqOPK.mvReqJdSwVWyGvPV.0KqTxfZiTOTMz.2oe9c52KUoXzhAdfIRjfQoWqBXwaqFJCS7wfZJfQ..1oa7N5Cr3JGVxfDkB4gyAACP.jJdcUZpu.P0XKpf9iyqH5Or.Ioh6cupU7.CM8VFCxCJ46oaVEfOZqLxS.xGvLQ06FqTZ.vCr.hxAv.W9BdI27DL54Wk97mSEP9vySzk5aQAWmmWOahD6c8ykwecgg22Rb8pXrwiGmvuNb6WI0GILQuJdPDqjBNqWt30J4rYEdfoPeAsY8FzmQaT+wz6S8aTeCvMtSgB3RFz9EBWu0.pf2cWX9ygXJiGdHOvvj8h49mNtFcRMH0ce5ipAoG3q2UiVxTT5Pt9PVnXXh0apj4G6ovdj2NdROtb8ZzlOM8l9bcQCerovIyB7Et0SplosPMazdBigGdDHgunF8zwz6g15D6Wnk2Lyzah195APQtFb9ZzMpgJD0zkUtDanJJ1OPMLgOs2aZ0N+BP3oU7Ap3YKYRYWebd0K3I+lHzD4W85UkXkZdagVMZQZYRIs7ybQuHy7pAKtyUSZmLnnl.HTkK3FgHBXxo4n4Jan1a0d5EYZ6YoSw7vBDrx1BIHVDbNOjd26RuikhFstVH4rlrTsmj2eLcFikdPDTZwC8sw8rh+oRUZ5SVVoz3s2nL72J8SS.vvI50Y0s6B4kMOLlqWHa7AW8GSPeH9cFWWdJJBDdQZ1m4V6y6Yt.6qIk.pj6KEl2NfmcdOUbH97E964eTjj8bD7qi2eGHGhuSlQCvMfqMBzbb1geArng8USO2c3ImaTCRwlMqm3Twjx8V4uohM.DAb02z01LPFOcWj+7We4jxGFg01DGWm+wgPhRKQwS+MbBZbTixae.S4abeUbLsfPwHPPgqc7w+0GPcVPcCjLPIkb93Nj1UWc0Gr6KM2dAvFIpvgwLyrqof6ikw.Rpyra.99uLQXlTdesufcWZ7Q2c4y0DusaagIHZw13JKvFgz8+G1X1Fe2xc2tcg4+EF3pt686K65cehq2tNQOX3mV.EZtuYX+NPlNfC2tDJ+RvBpUvRd64F3YLBzgKCSO7A3SFyl3YmLlMyYR5yBzp2GXakwcJuYJEvljoqP64d.dl1jj1dWNN2GVw88AAypp4DbikUvGtrBt4xJ3iVVAe7xJ3SVVAe5mVP7+.4UCMp911FB4f16lNOzwYW6FNX0J4+.Lr75iL
-
@d-healey Nice one, cheers!!