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 5.2k 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

                      Link Preview Image
                      W3Schools.com

                      Well organized and easy to understand Web building tutorials with lots of examples of how to use HTML, CSS, JavaScript, SQL, Python, PHP, Bootstrap, Java, XML and more.

                      favicon

                      (www.w3schools.com)

                      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

                                            56

                                            Online

                                            1.7k

                                            Users

                                            11.7k

                                            Topics

                                            101.7k

                                            Posts