What are the functions I should look at for doing an arpeggiator?
-
I am on the road but I'll hack something for you together when I get back.
-
Alright, this is a minimal example for a working arpeggiator script:
- only monophonic (just repeats the last pressed note)
- tempo synced and connected to a slider with the special TempoSync mode
I don't know what other features you need, but this should be a good starting point.
/** Simple Arpeggiator */ // Use `reg` instead of `var` to use the faster access storage type reg lastEventId = -1; reg lastNoteNumber = -1; // Use `const` for all UI widgets or immutable objects. const var Tempo = Content.addKnob("Tempo", 0, 0); // [JSON Tempo] Content.setPropertiesFromJSON("Tempo", { "max": 10, "mode": "TempoSync", "stepSize": 1 }); // [/JSON Tempo] // Use `inline` before a function to make it faster inline function startArp() { // Use `local` for variables within callbacks and inline functions local interval = Engine.getMilliSecondsForTempo(Tempo.getValue()) / 1000.0; Synth.startTimer(interval); }; function onNoteOn() { lastNoteNumber = Message.getNoteNumber(); startArp(); } function onNoteOff() { if(Message.getNoteNumber() == lastNoteNumber) { Synth.stopTimer(); lastNoteNumber = -1; } } function onController() { } function onTimer() { if(lastNoteNumber != -1) { if(lastEventId != -1) { Synth.noteOffByEventId(lastEventId); } lastEventId = Synth.playNote(lastNoteNumber, 127); startArp(); } else { Synth.stopTimer(); } } function onControl(number, value) { }
Here is a example patch with a sine blip (File -> Replace With Clipboard Content)
HiseSnippet 1423.3oc4XstaaaCEVJIBc1sNaEH6+bA6GNnsN1ocqcKHn4Ria8ZyEDklsgsgZZIZatHQpQQ4V2h7yg85rGg9HrGk9FrcHoTjriaZcP6VKlfSf445G+H44P48EbORbLWXYe4CGFQrruhi6Plr+V8wTlUq6YYWwYCQDZ6mgCiBHVaNLBGGS7srsm89JSrKMmkk05+7e7m2cSb.l4QREoeNhS8HOhFRk4Rau9CoAAMw9jCogEr9Vq2xiy1hGvS.3LqScqHr2w3djcwJylwwZ.k7zXK65N2bkZhiaz44aTCd7HsDjCtCoVstsf+9lV0ulR9su1NqbmqQ1rVMKuDgfvjGAtaY6X+2visy19TIW3JwRBDy41j6OzsO+oLSpOhFS6.yWXPCKW.SFwM4A9pIu56Va0mF3ueFCFaAwd+b9bVCetfyNTe5oxy40OSq.k6QQp0dlyCdMtfvyt.7ly.uq535InQxbMJrsfiKUsbifkdRudTrbL7YbxZleeNmkWF83XBpsfzqMhxhkDrOh2E0d.VzFI4nDPqrOA0EC5DHrmJQnXHjvZKRBvnRYvYT.ne6Av5TKezZnazX0bw6xkjcSB6.tmpoR4r7B6YhksQc4PnCBPOtE5oT+dDYLBjPCCSjXfoP7N+JwSFWqr1dD.NzgjvHNDvs3LIj1ZXe+Gx3cptnVwhWGUG9rzppL8Sem6d6Zb3WJmYeLQQaQDgjRhaJ3gJix89EUJiPKFhe1heKpQ8qaFw8IvPiMvAMuEMxAlIxk9bktFUJeRZRWtPVKNkor.JizF0g.yZBBi5lv7jTNSQ2g3iIHpLktqT1XbtIwRrPBqqUWpRY.hkxBZ.2CGX3QfbnJRKFnRYeJCAZB5.GFiQXlOZrHFCAQ6Ln.x3.3Kqg1l0CroFrNrCbXm5R.Z2OtIWnmMU0+Wo8HbPBo5RKgVF3n50qUGVaKAezEgpowppJgnZVrAp4jUOcxvYpsF6wptT4W.nX7sJ6.6zfMYpDkKu5Ro4HmIfXVd7X1sqInztUeMgAs1Zis6DnzRJN8T3yiLnWmxRSZqb4RmLZxU6tD7f.kWp7Op1zvoW4pnA2XA8KTQ8TbjpO6X0oJMZSgIyLc2bXpYEcAnlRkNQYb1DH+Hpw6n.7PU9GCHWG0Xkaal1p+Jx053QBhIud150wJUYoAefZeSF+.E7FsbY42txkdlCxELjyZwnx8hHosAx1ecFIc6VTT9ZVQo5ISlfF4lkayYqQakVbQUsN0bvTotV87o0pcCn9DgEEpDeIG8IIKMcj2Jcg0sNaodngC2OIPUKuXWHUW7TE.UORU9VJnDSkCyi7qt6TzZp9DaM0XRS62R3dUm8oRu9SFuyLA7B736a7l1nuhy1c6BsXxA6bNM+gKZW8KFTl2.kKCsuYD8oJMP9b8Xz2iGPP2mvHhyzOuvU4fm+5c+U41ySBY+PAlEGwiGIvtjP5gblhPxEBsjZJH+1ApE4hx2hiEST0qtaSXNNQebwxDgd2xFg7DlbjcGydgtn0nGZJX+Dt00b+Gbov28m7duVn3BdG1qXv6kb13A2y8fTXp+Nb+iAj.3tYuYXtgTB2rYqDwfQ1UdOhGd3YjZL9rRdDARWQwO.lE4i+x00g6TAuTrtaBzRr3gte7kGPBH33QNFMNGN6aGG9Fd0jyacFdcO8LBoOQ+gc2f4yvpg9+vFrWwQuG3iAd8ScR2c9QAwNuS5AmOFn1y8BLy9+yKvb.OQRY81AKEzmAUpfWfvEt3fGAPBiAunf5GsYFUyey35pwlaNv7qm8K5jprgZrcpxFYJ+WIGgXOA+Idlasqp49IZIv7lo+ErJ4riZLpQ100UbSHzu+IddJx9F.6LYOVYp83lSsG2Zp83qlZO95o1iaO0dbmywC0kq1HQxCMG8rr9GdeqtZC
-
What object do I use to see held notes or add/remove notes from a list? MidiList seems to not work. Any time you set a value for an index, it increases the number of indexes... wtf?
HiseSnippet 1495.3oc4XstaaaCEVJIBc1sNaEn6+bA6GN.sN1soqCKHnIwItMq4FhRytiZZIZatHQ5QQ4T2h96sGm8HzGg8nz2fsCIkrjcbRiCZ2ZwDLLLOWH+Ne7PdNxGH3djnHtvx95GMnGwx9FNtCXxt06hoLqs2zxtjy5hdnsdNNrW.wZiA8vQQDeKa6YejxD6ByYYYs1O+6+4C2.GfYdjDQ5mi4TOxNzPpLSZy0dBMHnA1mbDMLm0Ku11dbVcd.OFfyrNUs5g8NA2grGVY1LNV8ojSirrq5bu6VQbRsVuX8Jpm5URe1YyeryxA3SNswN5wato5aKuXgfvjGCtaY6X+2visyV9TIW3JwRBLmysA2efaW9oLyReLMh1BhWXPMKW.SFwM3A9pfW8aq5coA9GjxfQVvbePFeNqgOukytTe5P4Y75moUfx7HO0ZOyEAuZWQ3YmCdyYf2Mcb8DzdxLMJrcKGWpZ6FAa8jNcnX4X3y3j0L+giyRKgdZDA0TP5zDQYQRB1GwaiZ1GKZhjbTLnU1kfZiAcBD1SsPnHXJg8VjDfQohfyn.P+V8g8os8QqhtSsUxDuGWR1KNrE3dhlRESWWHmIR1D0lCScP.5oaiNk52gHiPfDZXXrDCLEh25WIdxnJE01i.vgNhD1iCSXcNSBKaEru+SX7VkWPqXgaipBeVbE0J8Seq696Yb3WJlZeDQQa8HBIkD0PvCUFk48KKUDgVHD+7E9FTsp21Lh6SfgFafCZdKXjCLSOW5KT5pUp3qRVzkxsp4CYJKfxHMQsHPTSPXT6XlmjxYJ5NDeBAQkIzcohFiyLIRhERXes7hkJBPrP5jFv8vAFdDHGphzh.pT1kxPflfVvgwHDl4iFaFifIQ6Ln.Vw9vOVEsEqCXSEXeXW3vN0k.zteTCtPGMk0eqzdLNHlTdwEQKAbT0pUpB6sEfO5Kgpnwp5VBQ4z4FnlWo2+U4F6NPcFZGJrgNbI8DD3LSp7xKtxvHmyT4Q6yJuXwWBPd77pcgzRHiTgpL4f+F.cdytQaFotRAijLnoxSLgIjEfteUsOJSf7nHd.oROADbky4fBAwgtItEAzyJm07IiVE8Tb7HtcaSHSaedtgVc0wNnAYGEToGC2I38LaDF3OoSkEK7JSruzRSJ5Omk1bFaDPqNfI3AAJ0JbOp1DXnSdKoCpw.yWnPyP7mnO8lkgJMZSBOlgl1XPhY4cAPWAcjUHMvytkx3cu.7.05OFPtMp1cevvc674HFlhDDQNeVFrYhrRYVxj2Wwpo7Cbm+nULJd4pX3YtKKWkONaaFUteOxvwlSMoRpYMLqJuQY6Y4kpClIXVlnyVlxJ49UUAqDyASk5xUymTtxMf5SDVTnXz0bzWlXooirtIt0ZVmsZGTyk6GGnJmkuPrpQlDE.UORgtsUPIhJGjMyu4gSQ04pSr5bsIE1WR3dSmCnRutSFuyLA7B736a7lzqSImsZ2FpxlA14bZ78W0FatZPYdCTtNzACinOUoAxmqGi9NbeB5QDFQblVZx0MK77Wu66lceOIr5GIvrnd7nQlXWRH8HNSQHYBgpxMDje6P0lbd404XwDU8lG1.hwI5iKVFKzYKqGxiYxQxNF6lCmK2MGidnIm8W7dk8b+Gzi769SguWuz3J1R+ML38ZNq+3McOLAl5eC8F0mD.sp91g45RIznW8XQ+QxP2j3gGbFoFiOqjcHvxkW7ignHa7Wtld5FJ30h0bigxi4O.9Cu9PR.AGMxQpw4vYubb3a4M0tn8Y3se0QDRe59C6JCymhUC8+gMXugiNG3iAd8ScRxN+nfXm2I4fyGCT6E1Lyr++rYlC4wRJqytXof9b3lJ0qBBMQ3Q.jvXvKMn9OrlQ0HfYbU0XSWDL+po+AWIJqoFamnrVpx+UViPrmf+LOSG7p6b+DsDHtY5+PuBN6pFipk15thaBg58OyySQ12AXmI6wcmZOt2T6wxSsG2ep83qlZOdvT6wWeAdnZtZ8XIOzbzyx5e.GPXCoC
-
Engine.createMidiList() is used to declare a special array.
Engine.createMidiList(); startArp(); MyMidiList.setValue(10, 50); Console.print(MyMidiList.getNumSetValues()); Console.print(Message.getNoteNumber());
Where do you get MyMidiList from? You shouldn't really declare Midi lists - or most other variables - in the on note callback.
-
Oops, you're right - Actually I haven't used the
getNumSetValues()
function since ages. It's fixed now.But I actually don't understand why you create a MidiList in the
onNoteOn
callback without referencing it, but as David suggested, this is a bad idea anyway as it allocates.Now to your actual problem: the most simple solution is using a plain old array for this. I added a method that reserves storage so you can insert elements without allocating.
You can then use the
sort
method to change the arp order.const var notes = []; // This is new: notes.reserve(127); function onNoteOn() { notes.push(Message.getNoteNumber()); } function onNoteOff() { notes.remove(Message.getNoteNumber()); } function onController() { } function onTimer() { } function onControl(number, value) { }
BTW, If you press the debug button, you can see the content of the array in the live variable watch and check that it works.
-
Ok thanks!
I got it built, but uhh... Is there a "get num elements" function for array?
-
-
Ok, so the timer has some limtations. I will have to schedule midi notes to be played to overcome the speed limit, but not sure how much time I should use for a "block". What is your suggestion?
-
What limitations have you encountered? Do you mean the "Go easy on the timer" speed limit?
-
Yes that
-
How should I address the timer limitation? What constant timer should I use to schedule faster midi sequences?
-
How fast do you need the timer to be? This is a pretty random value that is only there for safety reasons (so you don't freeze the CPU by eg.
Synth.startTimer(0)
. I didn't need it to be any faster until now, but it's only a number in the code not an actual limitation. -
How far can we push it? I don't want the end user to complain that the arpeggiator isn't running fast enough. What about 10ms? What about 1ms? 5ms?
-
Anything below 20ms would make sense IMHO (at this speed, you won't be able to tell either note pitch or note length).
-
Ok let's go with 20ms for now. If a user complains I'll let you know.
-
how do you get the current global tempo of the DAW?
-
Engine.getHostBpm()
-
How do you create a table for the steps? I need the bar graph type slider. I looked at the widgets, couldn't figure it out.
-
I think what you're after is the sliderPack widget
-
With the example script Christoph posted, note off does not work. Setting sustain to 0db (all the way up) will have the synth playing the note indefinitely... unless the AHDSR is not implemented correctly.