What are the functions I should look at for doing an arpeggiator?
-
What are the functions I should look at for doing an arpeggiator?
such as play_note, on_note, etc.
tempo stuff
also, what callbacks should I be using?
-
On timer callback
Synth.playNote
-
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.