HISE Logo Forum
    • Categories
    • Register
    • Login

    Making a Mono Mode

    Scheduled Pinned Locked Moved General Questions
    14 Posts 3 Posters 487 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.
    • CasmatC
      Casmat
      last edited by

      Hey!

      I have a question for making a mono legato in hise.. I’m thinking of making a legato which glides by taking the sample playback position of the original note and starting the new note at that sample position and then adding a pitch plus volume fade between the two. So basically let’s say C is being pressed, then E is pressed, when E is pressed, E starts playing but at no volume and the pitch fading takes place along with the volume xfade which theoretically make the legato… right? Question is I’m wondering if this how I go about a legato which does the sample position transferring?

      Thanks!

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

        @Casmat That will work (if you want to make it better you need to do this xfade/pitch fade with each pair of notes between the first note and the last).

        The sample position isn't important (or maybe it is to you?). Just as long as the samples are looped and the loop doesn't include the transient.

        By the way, my legato script does this :)

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

        CasmatC 1 Reply Last reply Reply Quote 0
        • CasmatC
          Casmat @d.healey
          last edited by

          @d-healey thanks David! Will update you with what I find!

          By the way, my legato script does this :)

          GPL though :confounded_face:

          The functionality im planning on implementing is this:

          • Mono Retrigger Mode, no glide, just basic retrigger
          • Mono Legato Mode, glide! Basically what you said in your post
          • Anchor/Last note retrigger, if a note is held and another note is pressed and let go, the note held is played, both for legato and retrigger mode
          d.healeyD 1 Reply Last reply Reply Quote 0
          • d.healeyD
            d.healey @Casmat
            last edited by

            @Casmat said in Making a Mono Mode:

            GPL though

            I think you mean

            GPL though :party_popper: 🍾 :person_raising_hand_dark_skin_tone: :person_raising_hand: :clapping_hands_medium-light_skin_tone: 😂 :1st_place_medal:

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

            CasmatC 1 Reply Last reply Reply Quote 1
            • CasmatC
              Casmat @d.healey
              last edited by

              @d-healey definitely! I’m now debating between going for the sample switching method of legato vs going for the pitch glide method of legato.. I tried your legato script to see how it’d sound l, but after messing with the controls for a while, when it glides up/down, you can hear all the samples in between and they all play from the start, is there a way on your legato script to make it sound more “glidey” instead of that strumming sound?

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

                @Casmat yeah you need to use a start offset modulator and drop in another script to control it

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

                CasmatC 2 Replies Last reply Reply Quote 0
                • V
                  voiceover63
                  last edited by

                  Test
                  https://www.locutortv.com/
                  https://www.locutortv.es/

                  1 Reply Last reply Reply Quote -1
                  • CasmatC
                    Casmat @d.healey
                    last edited by

                    This post is deleted!
                    1 Reply Last reply Reply Quote 0
                    • CasmatC
                      Casmat @d.healey
                      last edited by Casmat

                      @d-healey revamped mono script:

                      /*
                      The MIT License (MIT)
                      
                      Copyright © 2017, 2018, 2019, 2020, 2021, 2022 David Healey
                      
                      Permission is hereby granted, free of charge, to any person obtaining
                      a copy of this file (the “Software”), to deal in the Software without
                      restriction, including without limitation the rights to use, copy,
                      modify, merge, publish, distribute, sublicense, and/or sell copies of
                      the Software, and to permit persons to whom the Software is furnished
                      to do so, subject to the following conditions:
                      
                      The above copyright notice and this permission notice shall be included
                      in all copies or substantial portions of the Software.
                      
                      THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
                      OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                      THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                      */
                      
                      Content.setWidth(650);
                      Content.setHeight(50);
                      
                      reg lastNote = -1;
                      reg retrigger = -1;
                      reg eventId;
                      reg vel;
                      reg eventIdQueue = [];
                      reg tempId;
                      reg retrigId;
                      reg noteNum;
                      reg rootNote;
                      
                      //GUI
                      const var bypass = Content.addButton("Bypass", 10, 10);
                      
                      const var time = Content.addKnob("Time", 160, 0);
                      time.setRange(0, 2000, 0.01);
                      
                      
                      inline function onTimeControl(component, value)
                      {
                      	eventIdQueue = [];
                      };
                      
                      Content.getComponent("Time").setControlCallback(onTimeControl);
                      
                      
                      function onNoteOn()
                      {
                          if (!bypass.getValue())
                          {
                      		if (!retrigId == undefined) Synth.noteOffByEventId(retrigId);
                      		vel = Message.getVelocity();
                      		noteNum = Message.getNoteNumber();
                      		
                      		if(Synth.getNumPressedKeys() == 1) rootNote = Message.getNoteNumber();
                      		
                      		if (lastNote == -1)
                              {
                                  lastNote = Message.getNoteNumber();
                                  eventId = Message.makeArtificial();
                                  Console.print("Case1");
                              }
                              else
                              {
                                  if (time.getValue() > 0 && eventId != -1)
                                  {
                                      Message.ignoreEvent(true);                
                                      Synth.addPitchFade(eventId, time.getValue(), Message.getNoteNumber() - rootNote, 0);                    
                                  Console.print("Case2");
                                  }
                                  else
                                  {
                                      if (eventId != -1) Synth.noteOffByEventId(eventId);
                                          
                                      eventId = Message.makeArtificial();
                                      Console.print("Case3");
                                  }
                                  retrigger = lastNote;
                                  lastNote = Message.getNoteNumber();
                              }
                      
                      	    eventIdQueue.push(
                      	    {
                      	        "eventId": Message.getEventId(),
                      	        "noteNumber": Message.getNoteNumber()
                              });
                          }
                      }
                      
                      
                      
                      
                      function onNoteOff()
                      {
                          if (!bypass.getValue())
                          {
                              Message.ignoreEvent(true);
                              
                      	    for (id in eventIdQueue)
                      	    {
                      	        if (time.getValue() == 0)
                      	        {
                      	            if (id["eventId"] == Message.getEventId() + 1) tempId = id;
                      	        }
                      	        else
                      	        {
                      		        if (id["noteNumber"] == Message.getNoteNumber()) tempId = id;
                      	        }
                              };
                      	    eventIdQueue.remove(tempId);
                      	    if (!Synth.isKeyDown(rootNote) && time.getValue() == 0) rootNote = eventIdQueue[0]["noteNumber"];
                      	    
                              if (!noteNum == undefined && !Synth.isKeyDown(noteNum) && time.getValue() == 0)
                              {
                                  if (!retrigId == undefined) Synth.noteOffByEventId(retrigId);
                                  retrigId = undefined;
                              }
                              Console.print(Message.getNoteNumber());
                              Console.print(noteNum);
                              //Console.print(rootNote);
                              if (Message.getNoteNumber() == noteNum && eventIdQueue.length > 0 && time.getValue() == 0)
                              {
                                  eventIdQueue.reverse();
                             	    retrigId = Synth.playNote(eventIdQueue[0]["noteNumber"], vel);
                                  noteNum = eventIdQueue[0]["noteNumber"];
                                  Synth.noteOffByEventId(eventId);
                                  eventIdQueue.reverse();
                            	    lastNote = retrigger;
                                  retrigger = -1;
                                  Console.print("test");
                              }
                              
                              if (eventId != -1)
                              {
                                if (eventIdQueue.length > 0 && time.getValue() > 0)
                                {
                      	          eventIdQueue.reverse();
                      	          Synth.addPitchFade(eventId, time.getValue(), eventIdQueue[0]["noteNumber"] - rootNote, 0);
                      	          noteNum = eventIdQueue[0]["noteNumber"];
                      	          eventIdQueue.reverse();
                      	          lastNote = retrigger;
                      	          //retrigger = -1; --Causes wierd audio glitches since first if statement on the onNote callback is activated
                                }
                                else
                                {
                                    Synth.noteOffByEventId(eventId);
                                    eventId = -1;
                                    Console.print("RAH1");
                                }
                              }
                      
                              if (!Synth.getNumPressedKeys())
                              {
                                  Synth.noteOffByEventId(eventId);
                                  lastNote = -1;
                                  Console.print("RAH2");
                              }
                          }
                          else if (eventId != -1 && eventId != undefined)
                          {
                              Synth.noteOffByEventId(eventId);
                              eventId = -1;
                              lastNote = -1;
                              eventIdQueue = [];
                          }
                          /*Console.print("new");
                          for(i in eventIdQueue)
                          {
                          	        Console.print(i);
                          };*/
                      }
                      
                      function onController()
                      {
                      	
                      }
                       function onTimer()
                      {
                      	
                      }
                       function onControl(number, value)
                      {
                      	
                      }
                       
                      

                      I made some changes to your script to get last note retriggering working! Most everything works, except for one thing, I tried finding the cause of the issue (you may see some console print statements scattered), but unsuccessful. Basically, the problem occurs when you try to "glide" from two notes. Lets say you press C, then while holding C, you press E, E plays, but as soon as you let go of C, E stops playing.

                          if (Message.getNoteNumber() == noteNum && eventIdQueue.length > 0 && time.getValue() == 0)
                          //...
                          if (eventIdQueue.length > 0 && time.getValue() > 0)
                      

                      I think i traced the problem to these if statements where the first one does what I mentioned above, but when I deleted the Message.getNoteNumber() == noteNum line (the second if statement), Instead of E stopping, It gets retriggered. Any ideas to fix?

                      Edit: there's also probably a lot of unnecessary code since i didn't replace most of your existing code which may/may not be functional due to my changes... I only removed the lastTuning variable since it was the one causing the pitch issues, all to fix was just add a rootNote var

                      Thanks!

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

                        @Casmat

                        eventIdQueue.push(
                        {
                        "eventId": Message.getEventId(),
                        "noteNumber": Message.getNoteNumber()

                        This kind of thing is slow/inefficient. Use a midi list:
                        ml.setValue(Message.getNoteNumber(), Message.getEventId());

                        if (!noteNum == undefined

                        This logic is confusing, do you want to check if noteNum is defined or if it's not defined?

                        You probably want to use if (!isDefined(noteNum))

                        Same here

                        if (!retrigId == undefined)

                        Don't put if statements on a single line, it makes the intent of the code less clear at a glance.

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

                        CasmatC 1 Reply Last reply Reply Quote 0
                        • CasmatC
                          Casmat @d.healey
                          last edited by

                          @d-healey I’m stuck trying to figure out how I can use a midi list in my case.. I tried to read the docs but there’s little info, how can I use the midi list to replicate the array system I had? In the previous system, I had stored the event Id and note number in an object that is created for each note on and deleted on the note off. The objects could be ordered in a list such that the last value would be the next one in line to be retriggered. How could I replicate this? And would this solve notes turning off when others are released?

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

                            @Casmat said in Making a Mono Mode:

                            The objects could be ordered in a list such that the last value would be the next one in line to be retriggered. How could I replicate this?

                            This shouldn't be needed. In a mono system there is only ever one active note and one old note. With retrigger you have potentially two old notes. So at max you need to keep track of those three notes.

                            And would this solve notes turning off when others are released?

                            If you are making artificial notes you still need to turn them off.

                            A midi list is an array with 128 elements that is optimized for this kind of task.

                            To create a midi list use:

                            const eventIds = Engine.createMidiList();

                            To store the event triggered by note 60 (for example):

                            eventIds.setValue(60, eventId);

                            To store events as they come in to on note on you would replace 60 with Message.getNoteNumber() and eventId with Message.getEventId(); But you can also store artificial events too.

                            To the get the eventId of note 60:

                            local eventId = eventIds.getValue(60);

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

                            CasmatC 1 Reply Last reply Reply Quote 0
                            • CasmatC
                              Casmat @d.healey
                              last edited by Casmat

                              @d-healey ohhh, I’m trying to recreate Vital’s mono mode on the “newest” voice setting which keeps track of held notes and prioritizes the newer/latest notes. I’m guessing I wouldn’t be able to hold that much note numbers in midilists, right?

                              If you are making artificial notes you still need to turn them off..

                              I thought I took care of all the hanging notes, are there more I didn’t get? The problem is that is I’m doing a regular string of notes, when I let go of the old note while holding a new note I want to hear, the new note retriggers again when the old one is let go

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

                                @Casmat said in Making a Mono Mode:

                                I’m trying to recreate Vital’s mono mode on the “newest” voice setting

                                I'm not familiar with that

                                I’m guessing I wouldn’t be able to hold that much note numbers in midilists, right?

                                A MIDI list is just a fast array, so you can definitely use it for this. You just might need more than one.

                                I thought I took care of all the hanging notes, are there more I didn’t get?

                                I dunno, I didn't try it. I was responding to this question

                                And would this solve notes turning off when others are released?

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

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

                                15

                                Online

                                1.7k

                                Users

                                11.8k

                                Topics

                                102.5k

                                Posts