HISE Logo Forum
    • Categories
    • Register
    • Login

    What are the functions I should look at for doing an arpeggiator?

    Scheduled Pinned Locked Moved Scripting
    27 Posts 3 Posters 6.1k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • E
      elanhickler
      last edited by

      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?

      1 Reply Last reply Reply Quote 0
      • d.healeyD
        d.healey
        last edited by d.healey

        On timer callback

        Synth.playNote

        Libre Wave - Freedom respecting instruments and effects
        My Patreon - HISE tutorials
        YouTube Channel - Public HISE tutorials

        1 Reply Last reply Reply Quote 0
        • Christoph HartC
          Christoph Hart
          last edited by

          I am on the road but I'll hack something for you together when I get back.

          1 Reply Last reply Reply Quote 0
          • Christoph HartC
            Christoph Hart
            last edited by

            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
            
            1 Reply Last reply Reply Quote 0
            • E
              elanhickler
              last edited by elanhickler

              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
              
              1 Reply Last reply Reply Quote 0
              • d.healeyD
                d.healey
                last edited by d.healey

                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.

                Libre Wave - Freedom respecting instruments and effects
                My Patreon - HISE tutorials
                YouTube Channel - Public HISE tutorials

                1 Reply Last reply Reply Quote 0
                • Christoph HartC
                  Christoph Hart
                  last edited by Christoph Hart

                  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.

                  1 Reply Last reply Reply Quote 0
                  • E
                    elanhickler
                    last edited by elanhickler

                    Ok thanks!

                    I got it built, but uhh... Is there a "get num elements" function for array?

                    screenshot

                    1 Reply Last reply Reply Quote 0
                    • Christoph HartC
                      Christoph Hart
                      last edited by

                      https://www.w3schools.com/jsref/jsref_length_array.asp

                      1 Reply Last reply Reply Quote 1
                      • E
                        elanhickler
                        last edited by

                        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?

                        1 Reply Last reply Reply Quote 0
                        • Christoph HartC
                          Christoph Hart
                          last edited by

                          What limitations have you encountered? Do you mean the "Go easy on the timer" speed limit?

                          1 Reply Last reply Reply Quote 0
                          • E
                            elanhickler
                            last edited by

                            Yes that

                            1 Reply Last reply Reply Quote 0
                            • E
                              elanhickler
                              last edited by

                              How should I address the timer limitation? What constant timer should I use to schedule faster midi sequences?

                              1 Reply Last reply Reply Quote 0
                              • Christoph HartC
                                Christoph Hart
                                last edited by

                                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.

                                1 Reply Last reply Reply Quote 0
                                • E
                                  elanhickler
                                  last edited by elanhickler

                                  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?

                                  1 Reply Last reply Reply Quote 0
                                  • Christoph HartC
                                    Christoph Hart
                                    last edited by

                                    Anything below 20ms would make sense IMHO (at this speed, you won't be able to tell either note pitch or note length).

                                    1 Reply Last reply Reply Quote 0
                                    • E
                                      elanhickler
                                      last edited by elanhickler

                                      Ok let's go with 20ms for now. If a user complains I'll let you know.

                                      1 Reply Last reply Reply Quote 0
                                      • E
                                        elanhickler
                                        last edited by elanhickler

                                        how do you get the current global tempo of the DAW?

                                        1 Reply Last reply Reply Quote 0
                                        • Christoph HartC
                                          Christoph Hart
                                          last edited by

                                          Engine.getHostBpm()

                                          1 Reply Last reply Reply Quote 0
                                          • E
                                            elanhickler
                                            last edited by

                                            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.

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            22

                                            Online

                                            1.8k

                                            Users

                                            11.9k

                                            Topics

                                            104.0k

                                            Posts