Loopy Pro: Create music, your way.

What is Loopy Pro?Loopy Pro is a powerful, flexible, and intuitive live looper, sampler, clip launcher and DAW for iPhone and iPad. At its core, it allows you to record and layer sounds in real-time to create complex musical arrangements. But it doesn’t stop there—Loopy Pro offers advanced tools to customize your workflow, build dynamic performance setups, and create a seamless connection between instruments, effects, and external gear.

Use it for live looping, sequencing, arranging, mixing, and much more. Whether you're a live performer, a producer, or just experimenting with sound, Loopy Pro helps you take control of your creative process.

Download on the App Store

Loopy Pro is your all-in-one musical toolkit. Try it for free today.

MOZAIC - Create your own AU MIDI plugins - OUT NOW!

14849515354106

Comments

  • @Mayo said:
    Poly rhythms, differing BPM's on top of each other / staggering drum feels etc etc.
    I do it now with 2 ipads at different BPM's .

    From the Mozaic Manual:

    I would think someone could use these variables to make a polyrhythmic arpeggiator or sequencer based upon using the information from those variables you get from the AUv3 host app.

    Have you looked into an app like Photon where you can load a MIDI file onto six different pads, route the MIDI output independently, and set the tempo division for the host for each one? The AUv3 parameters for the six pads can be MIDI controlled too.

  • @InfoCheck said:

    @Mayo said:
    Poly rhythms, differing BPM's on top of each other / staggering drum feels etc etc.
    I do it now with 2 ipads at different BPM's .

    I would think someone could use these variables to make a polyrhythmic arpeggiator or sequencer based upon using the information from those variables you get from the AUv3 host app.

    Yes, you could make an arpeggiator like that, but what you couldn’t do is make something that speeds up a channel. Mozaic can only affect midi that passes through it. For it to, say, double the playback speed, it would need to be able to see into the future. It could conceivably slow down playback for limited amounts of notes, but variable storage is limited, so, other apps are better for that. Atom, and as you noted, Photon can be used this way, for pre-recorded midi.

  • Hey all, I’m fairly new to script writing of any kind and am getting most the basics figured out but I’ve gotten myself stuck and confused trying to implement the following idea...

    I want to send a midi macro message to Loopy (to toggle mute/unmute of a few tracks), triggered by a pad on my external controller, which starts at the beginning of the coming next bar, and repeats 8 times (synced to the beginning of each subsequent bar), then stops/exits the loop...

    As Host information doesn’t get into a loop once the event is triggered I can’t figure out how to 1)make the macro/user event wait to be sent until the beginning of the next bar, and 2)make it repeat 8 times at the beginning of each next bar

    Is there a way to ‘wait’ to start a loop after triggering it with an incoming MidiNote from my keyboard pad? I understand how to delay the sending of a midi message in milliseconds with the 4th byte but can’t figure this out...
    Do I need to use an LFO for this?
    I feel I’m just missing something pretty basic here but mind crunching for hours has brought me to my knees asking for help! Thanks

  • @ManWhoWouldBeStrings said:
    I feel I’m just missing something pretty basic here but mind crunching for hours has brought me to my knees asking for help! Thanks

    I'm also still learning but I'll take a swing at this problem to help me test my understanding.
    There are 2 ways to manage event timing:

    1. Use the DAW's metronome and count up the right amount of beats/pulses between the start and the end of a loop. The DAW has a BPM setting and Mozaic allows you to divide that pulse into fractions using the SetMetroPPQN function. Then you can use a code block that get fired off for every sub-divided (PPQN) event.

    Here's some sample code to log the time to send the event after 8 x 4 = 32 pulses.

     @OnLoad
       SetMetroPPQN 4
       Number_of_Pulses = 0
    @End
    
    @OnMetroPulse
       Number_of_Pulses = Number_of_Pulses + 1
       if Number_of_Pulses = 32
          log {This is the time to set your event}
          Number_of_Pulses = 0
       endif
    @End
    

    The Metronome pulses and the counting will start when you hit "Start" in the DAW's transport controls. Until then you'll just be loaded and waiting.

    1. The alternative is to set a timer based upon using the clock inside Mozaic.

    Here's some sample code to log the time to send the event after 8 x 4 = 32 pulses (8 seconds).

     @OnLoad
       SetTimerInterval = 250     // Timer will fire off every 250 milli-seconds = 4 times a second
       Number_of_Timers = 0
    @End
    
    @OnTimer
       Number_of_Pulses = Number_of_Timers + 1
       ResetTimer
       if Number_of_Timers = 32
          log {This is the time to set your event}
          Number_of_Timers = 0
       endif
    @End
    

    As written here, the Mozaic clock will start running when you load the script. But you can
    start a Timer in response to some external event like a MIDI Note or CC input.

    I suspect you'd want to sync with the DAW's timing and BPM. I'm sure there are additional
    mysteries to be solved but this will point you in the right direction, I hope.

    I wrote this code without any testing so hopefully you'll see those "Log" messages as I expect based upon the DAW's BPM or the 8 seconds of Timer pulses.

  • wimwim
    edited November 2019

    @ManWhoWouldBeStrings said:
    Is there a way to ‘wait’ to start a loop after triggering it with an incoming MidiNote from my keyboard pad? I understand how to delay the sending of a midi message in milliseconds with the 4th byte but can’t figure this out...

    I think all you need is the @OnNewBar event for what you want to do...

    @OnLoad
      triggernote = 48 //The note to arm the trigger
      triggerpending = NO
    
      sendchannel = 0 
      sendcc = 20
      sendvalue = 127
    @End
    
    @OnMidiNoteOn
      if (MIDINote = triggernote) and (triggerpending = NO)
        triggerpending = YES
        Log {Received trigger note }, MIDINote, {.}
      else
        Log {Received note }, MIDINote
      endif
    @End
    
    @OnNewBar
      if (triggerpending = YES)
        SendMIDICC sendchannel, sendcc, sendvalue, 0
        Log {Sent cc }, sendcc, { value }, sendvalue, { on channel }, sendchannel + 1
        triggerpending = NO
      endif
    @End
    
  • @wim said:
    I think all you need is the @OnNewBar event for what you want to do...

    Thank you for providing a complete solution.

  • edited November 2019

    Thanks @wim and @McD! You’re awesome. I got it working with this help and understand something much better now!

    I’d been trying to do something like imbed an event inside another one, like:

    @OnMidiNote
      if MIDINote = 60
        @OnNewBeat
          log {send mute/unmute messages to Loopy here}
        @End 
    @End 
    

    Which as far as I can tell is not possible right?

    Anyways I understand now how to accomplish this kind of thing simply with variables as you showed in that little super helpful bit of code @wim. Do you ever sleep I wonder?

    One question though...what’s the reason for the sendchannel, sendcc, and sendvalue variables? Rather than just entering those values into the SendMidiCC bytes?

    So this is what I ended up with to also send the macro 8 times...is this actually the best way to repeat the sending of the macro 8 times at the beginning of each new bar?

    @OnLoad
      triggernote = 60 //The note to arm the trigger
      triggerpending = NO
    
      barcounter = 8
    
    @End
    
    @OnMidiNoteOn
      if (MIDINote = triggernote) and (triggerpending = NO)
        triggerpending = YES
        Log {Received trigger note }, MIDINote, {.}
      else
        Log {Received note }, MIDINote
      endif
    @End
    
    @OnNewBar
      if (triggerpending = YES) and barcounter > 0
        dec barcounter
        Call @LoopyMutes
      elseif barcounter = 0
        triggerpending = NO
        barcounter = 8
      endif
    @End
    
    @LoopyMutes
      SendMIDINoteOn 0, 61, 80, 50 //The note to toggle mute
      SendMIDINoteOn 0, 61, 80, 50 //Twice for immediate mute
    @End
    
  • The problem I see with the options you offered @McD is that the macro would indeed wait to send until a full bar after the trigger note is heard, but that would only be at the start of the next bar if I triggered it at the start of a new bar as it’s set to either miliseconds or pulses instead of the next bar...I think... 😆

  • @ManWhoWouldBeStrings said:
    One question though...what’s the reason for the sendchannel, sendcc, and sendvalue variables? Rather than just entering those values into the SendMidiCC bytes?

    That's just a preference on my part. I like having anything I or someone else might want to adjust up in the beginning of the script and in variables so that if changes are needed a) they're easy to find, b) you only have to change once even if the value is used multiple times, and c) it's easier to see what the code is doing with names rather than numbers.

    So this is what I ended up with to also send the macro 8 times...is this actually the best way to repeat the sending of the macro 8 times at the beginning of each new bar?

    Looks good to me. I like that you made a separate call for a custom event rather than embedding the code all in the loop. That also makes it easier to read and maintain.

    I'd say you've got a good grip on things. :)

    As for embedding the built-in mozaic events inside other events, as you've seen, you can't do that. They're like independent watchers, waiting for events to happen, and you can't call them. By contrast, user created events don't watch for anything at all, and must be called.

  • @ManWhoWouldBeStrings said:
    The problem I see with the options you offered @McDtracy

    Yes. I don't even get partial credit for my answer but I suspected someone might
    be exposed to the concepts and we can slowly add more novice programmer's and have them ask the good programmers here for help. It pulled @Wim into setting the record straight.

    Please continue to ask questions... I know I will as I uncover some puzzle making new MIDI
    scripts. Making them is really fun... when they work and puzzling when they don't. I love
    a good puzzle.

    @Wim has really helped make it clear that Mozaic has these event listeners:
    @OnNewBar
    @OnMidiNOteOn
    (there are many)

    And the script author can wrap up some code with a label:
    @MyInstructionsNow
    ...
    @End

    Then call that code with a "call" instruction:
    Call @MyInstructionsNow

    Someone is thinking... I got that.

    A running Mozaic script is really a collection of potential "listeners" waiting for MIDI events to trigger code execution.

  • A question for the experienced programmer's out there.

    What common programming language is Mozaic script most like in your experience?
    Something with "Listeners" (Event Handlers) and "Functions" maybe?

  • wimwim
    edited November 2019

    @McD said:
    A question for the experienced programmer's out there.

    What common programming language is Mozaic script most like in your experience?
    Something with "Listeners" (Event Handlers) and "Functions" maybe?

    Not common anymore, but Mozaic was designed to be similar to Pascal. Which is cool for me because Pascal (and its cousin Modula 2) was the first languages other than Basic that I got serious about learning. It has always seemed like an efficient language for smaller-scale stuff because it's easy to get a grip on.

  • @wim said:
    Not common anymore, but Mozaic was designed to be similar to Pascal.

    Cool. I can see that for the easy to type syntax defining sections.

    Program MyCode
      variables
    
    Procedure DoStuff
      BEGIN
        Stuff using variables
      END;
    
    BEGIN
      Main code section that calls procedures in structured loops
    END.
    

    What's a good example of something that uses these "Event Listeners". Google puts "Javascript" at the top of the query but I expect there's a better answer historically.
    SmallTalk? Lisp? I remember they are essential for making Graphical User Interfaces
    and might be more of a systems facility than a language concept.

  • wimwim
    edited November 2019

    @McD said:
    What's a good example of something that uses these "Event Listeners". Google puts "Javascript" at the top of the query but I expect there's a better answer historically.

    I dunno other than Javascript. All I know is it's a perfect paradigm for this kind of plugin. I love how you don't need to worry about watching for events and calling them when needed. You just know they're going to fire when they should and that if you didn't code anything for that event, you don't ever have to worry about it triggering anything.

    IMO, Mozaic is the most elegantly designed purpose-built language I've ever used.

  • @wim said:

    @McD said:
    What's a good example of something that uses these "Event Listeners". Google puts "Javascript" at the top of the query but I expect there's a better answer historically.

    I dunno other than Javascript. All I know is it's a perfect paradigm for this kind of plugin.

    This is open for anyone to comment and share their tips.

    Do you have any advice regarding "data structure" in your use of Mozaic? I have considered
    putting data in variables in a sequences like a string of 4 or 5 note chords. Or using some delimiter value at the end of a string of elements. Knowing that 1024 limit is always there I reconsidered and just used a variable per chord but then I have to hard code the use of any code. Trade-offs always need to be made.

    Any advice?

  • wimwim
    edited November 2019

    I can't offer any specific advice on that without more context about what you're trying to store.

    If you need to store more data than 1024 numbers, then you need to pre-allocate enough arrays and then maintain two counters. One for the array to use, and one for the position in that array. Then you need an if/else/endif block to tuck the data into the right array.

    (You mention strings and delimiters. There is no string variable storage in Mozaic, only numbers.)

  • McDMcD
    edited November 2019

    @wim said:
    I can't offer any specific advice on that without more context about what you're trying to store.

    If you need to store more data than 1024 numbers, then you need to pre-allocate enough arrays and then maintain two counters. One for the array to use, and one for the position in that array. Then you need an if/else/endif block to tuck the data into the right array.

    (You mention strings and delimiters. There is no string variable storage in Mozaic, only numbers.)

    That's a pretty good answer. You indicate that there's not another way to store data creatively.

    Here's what I was considering. Let's say I have a variable describing chord types:

    Major gets coded as 0, 4, 7 (half-steps above the root)
    Minor is 0, 3, 7
    Dominant 7th 0, 4, 7, 10

    I can "string" there numbers into a single array and separate them with a delimiter
    like 99:

    Chords = [0, 4, 7, 99, 0, 3, 7, 99, 0, 4, 7, 10, 99]

    Then the code can pull out the 1st, 2nd or 3 chord by counting those delimiters. Using delimiters will allow for extra notes to be added to the "Chord" array.

    Packing extra content into a data structure with these delimiters is a type of data encoding.
    It can effectively allow me to encode arrays so they have more dimensions than a single index.

    I'm working on a chord making script and haven't decided which approach to release.
    Using:
    Major = [0,4,7]
    Minor = [0,3,7]

    which makes me use "Case statement" like ladders of if statement tests:

        if Chord = 0
          Log {Major time}  // there are "strings" we can embed in our code
          Log {Hello World!}
        end
        if Chord = 1
          Log {Minor Chord to output}
    

    With an encoded chord map I can use that "Chord variable" in a loop and process
    the correct code and avoid long lists of "if" tests. Trade offs. But knowing what's going on
    would not be obvious to someone reading the code. If it runs... I'm happy. @_Ki has followed
    my intention and made much more elegant versions of a nasty Streambyter script I posted.

  • wimwim
    edited November 2019

    @McD said:
    I can "string" there numbers into a single array and separate them with a delimiter
    like 99:

    Chords = [0, 4, 7, 99, 0, 3, 7, 99, 0, 4, 7, 10, 99]

    Then the code can pull out the 1st, 2nd or 3 chord by counting those delimiters. Using delimiters will allow for extra notes to be added to the "Chord" array.

    Well, it’s semantics only, but you’re actually not counting delimiters, you’re referencing positions in the array. ;)

    (BTW, you can store negative numbers in an array as well. I would normally use -1 rather than 99 in the example above.)

    For interest sake, I found an easy way to construct regular chords is to quantize every third note above the root to the chosen scale. This is what I used to construct chords of any degree (“notes” = degree in the snippet below from the Chordulator script).

    @MakeChord
      note[0] = ScaleQuantize MIDINote
      for i = 1 to (notes - 1)
        note[i] = ScaleQuantize note[i-1] + 3
      endfor
    @End
    
  • _ki_ki
    edited November 2019

    @Mcd And i even finished a even more complicated version of the One Finger Orchestra, which i didn't publish as playing with it did not inspire me.

    .

    And yes, you can do that kind of packed storage also in Mozaic, it works the same as in the StreamByter examples we exchanged back then. As you mentioned, you need a delimiter for the chords.
    From that chord array i compiled a ref indexing into the chord definitions to each start of a chord .

    @OnLoad
      _delim = -1
       chords = [0, 4, 7, -1, 0, 3, 7, -1, 0, 4, 7, 10,-1,-1]  
      // Two delimiters define end of chord data !
    
       FillArray ref, 0  // reference array, each entry indexes
                         // to start of a chord
       _idxC = 0    // index pointing into chords
       _idxR = 0    // index pointing into ref
    
      // Build Ref-Array
      // First entry of chord is always the first chord
    
      _endIdx = 500 // End iteration if double delimiter is missing
      repeat
        ref[_idxR] = _idxC
        Inc _idxR
        Inc _idxC
        while chords[_idxC] <> _delim and _idxC < _endIdx
          Inc _idxC
        endwhile
        Inc _idxC
      until chords[_idxC] = _delim or _idxC >= _endIdx
    
      numOfChords = _idxR // Number of chords
    
    
      // Dump the Chords
      for _c = 0 to numOfChords-1
        _idx = ref[_c]
        repeat
          Log {Chord },_c,{ interval },chords[_idx]
          Inc _idx
        until chords[_idx] = _delim or _idxC > 500
        Log {---}
      endfor
    
    @End
    

    Using the ref array it is easy to pick out the chords from the packed storage.

    @wim IIRC i used 0xFF as delimiter in my streambyter code. Using -1 also works and is easy to test ( < 0)
    In the end i had defined 37 different chord types to pick from, all stored in a single array using the packed form.
    Like in the OneFingerOrchestra script of @McD , one could pick a chord per base note, this script offered 4 of these base-settings. All chords could be 'inverted/extended' in 6 types, strummed in sync with variable timing and arped in 8 pattern. All controlled by 4 CCs (chordset, inversion, strum speed, arp pattern) since at that time StreamByter didn't have UI support.
    Worked very well, but it sounded so mechanical and not musical as i expected. Automation produced generative pieces, but it didn't bring more fun as the first experiments with @McDs script.

    Your idea of using the Mozaic quatizer is nice, thanks for the tip.

    .

    I hope this 'boffin talk' doesn't scare off the other readers of this thread :p

  • Ahh. I misunderstood. I thought when @McD referred to “delimiters” he was referring to the commas between the numbers in the array. Got it. Sorry for the confusion.

  • @_ki said:
    I hope this 'boffin talk' doesn't scare off the other readers of this thread :p

    The other way around, I find it highly inspirational, and I'm still only at "reading up on things" phase. :)

  • xorxor
    edited November 2019

    And yes, you can do that kind of packed storage also in Mozaic, it works the same as in the StreamByter examples we exchanged back then. As you mentioned, you need a delimiter for the chords.
    From that chord array i compiled a ref indexing into the chord definitions to each start of a chord .

    What I wouldn’t give for multi-dimension arrays.

    chords = [ [ 3, 0, 4, 7 ], [ 3, 0, 3, 7 ] ]
    
    // Assume type is 0 or 1 to indicate which chord
    for i = 1 to chords[type][0]
        Log chords[type][i]
    endfor
    

    Sure you can do the same with a packed array with the first elements being offsets but... why?

  • wimwim
    edited November 2019

    Multi dimensional arrays would be great to have, but seem like they’d be tough to implement with the type of memory and realtime processing constraints an AU plugin like this has to deal with.

  • @xor said:
    What I wouldn’t give for multi-dimension arrays.

    > chords = [ [ 3, 0, 4, 7 ], [ 3, 0, 3, 7 ] ]
    > 
    > // Assume type is 0 or 1 to indicate which chord
    > for i = 1 to chords[type][0]
    >     Log chords[type][i]
    > endfor
    > 

    Sure you can do the same with a packed array with the first elements being offsets but... why?

    One useful encoding scheme that just hit me would be to use:

    indexes 0-9 for notes for chord voicing #1
    indexes 10-19 for chord #2
    ...
    to a max of 1020-1024 for over 100+ possible chord voicings.

    I have this other array that maps a chord type to a given note in the chromatic scale
    from 0-12. That might save having to code a huge list of "if tests" for chord type.

    I was hoping someone would help provide some insight and this did help.

  • _ki_ki
    edited November 2019

    @McD You are right - I had to uses the packed format in StreamByter due to the 256 element restriction of arrays. My 37 chords were spread over two of them, so the stored ref added an offset of 256 to indicate chords in the second array.

    For Mozaic with it's longer arrays, you can use a fixed offset, which has to be longer than the size of the longest chord plus one - since you still need to store a chord-end delimiter if you want to support for variable length chords.

    Initialization is easy:

    @OnLoad
      _delim  = -1
      _offset = 10
      chords[ 0] = [0, 4, 7, -1]
      chords[10] = [0, 3, 7, -1]
      chords[20] = [0, 4, 7, 10, -1]
      maxChordIdx = 2 // One less than number of chords
    
      _endIdx = 50
      for _c = 0 to maxChordIdx
        _idx = _c * _offset // Compute chord index
        repeat 
          Log {Chord[},_c,{] = }, chords[_idx]
          Inc _idx
        until chords[_idx] = _delim or _idx > _endIdx
        Log {---}
      endfor
    @End
    
    

    If you are not sure about the size of the longest chord, you could use the safer initialization, that allows to change the _offset with a single line:

      // Safer initialization, allows to change _offset later on
      _c      = 0
      chords[_c*_offset] = [0, 4, 7, -1]
      Inc _c
      chords[_c*_offset] = [0, 3, 7, -1]
      Inc _c
      chords[_c*_offset] = [0, 4, 7, 10, -1]
      Inc _c
    
      maxChordIdx = _c - 1 // One less than number of chords
    

    In an earlier version of the mentioned StreamByter Chorder script, i used a fixed offset of 8 which was enough for chords with up to 7 notes. But the longest chord i wanted to store had 9 notes, so i had to change to packed form due to max-array size limitations.

  • McDMcD
    edited November 2019

    @_ki said:
    @McD You are right - I had to uses the packed format in StreamByter due to the 256 element restriction of arrays. My 37 chords were spread over two of them, so the stored ref added an offset of 256 to indicate chords in the second array.

    For Mozaic with it's longer arrays, you can use a fixed offset, which has to be longer than the size of the longest chord plus one - since you still need to store a chord-end delimiter if you want to support for variable length chords.

    Initialization is easy:

    @OnLoad
      _delim  = -1
      _offset = 10
      chords[ 0] = [0, 4, 7, -1]
      chords[10] = [0, 3, 7, -1]
      chords[20] = [0, 4, 7, 10, -1]
      maxChordIdx = 2 // One less than number of chords
        
      _endIdx = 50
      for _c = 0 to maxChordIdx
        _idx = _c * _offset // Compute chord index
        repeat 
          Log {Chord[},_c,{] = }, chords[_idx]
          Inc _idx
        until chords[_idx] = _delim or _idx > _endIdx
        Log {---}
      endfor
    @End
    
    

    If you are not sure about the size of the longest chord, you could use the safer initialization, that allows to change the _offset with a single line:

      // Safer initialization, allows to change _offset later on
      _c      = 0
      chords[_c*_offset] = [0, 4, 7, -1]
      Inc _c
      chords[_c*_offset] = [0, 3, 7, -1]
      Inc _c
      chords[_c*_offset] = [0, 4, 7, 10, -1]
      Inc _c
    
      maxChordIdx = _c - 1 // One less than number of chords
    

    In an earlier version of the mentioned StreamByter Chorder script, i used a fixed offset of 8 which was enough for chords with up to 7 notes. But the longest chord i wanted to store had 9 notes, so i had to change to packed form due to max-array size limitations.

    What I'm playing with are creating 10 notes voicings and giving the user a knob to control how many of the 10 notes are used from 2-10. Every chord type could have up to 10 notes.

    Then I added a delay knob to strum and arppegiate the (up to) 10 notes and then I added... you get the idea.

    I'm creating a bunch of knobs for various parameters you can change including completely different sets of chord maps for classical, jazz, power chords, quartal structures, etc. I also have a "root" change which makes it
    apply the harmony around a selected root (tone center).

    I want to add playing the chords and arp'ed notes from the DAW's BPM... either as a variation of the script or another row of knobs, I think. Maybe the arp's could play over the chords from the "one finger" version. I want it to have different features from @wim's excellent Chordulator script. But it's still
    my journey to understanding how Mozaic works.

  • _ki_ki
    edited November 2019

    @McD Sounds cool 👍🏻 and is picking up the ideas we discussed with the StreamByter script.

    I also have an initial Mozaic version of a SmartChorder script based on the old ideas, but didn't work on that for the last half year. Please finish yours, so i don't have to finish mine :)

    .

    As i am currently writing an In-Order Arp script (requested in other thread) , i came up with the following idea for synced arps:

    When using a metropulse of ppqn, there are ppqn * HostBeatsPerMeasure pluses per bar. A 1/8 note will play for pulsePerBar / 8 which leads to divisions = Round (pulsePerBar / arpTiming )
    A gate-length of lenPercent % needs noteEndPulse = RoundDown ( divisions * lenPercent / 100 ) pulses

    Thats all the precomputation needed to run the following @OnMetroPulse event to generate the synced, arped notes:

    @OnMetroPulse
      _div = (CurrentMetroPulse % divisions)   
      if _div = 0
        // Time to start a new note
      elseif _div = noteEndPulse
        // Time to end a playing note
      endif
    @End
    

    More tricks: Triplets need divisions = Round ( pulsePerBar / arpTiming * 2 / 3) and fit nicely into a bar. To support dotted arps, i had to modify the base idea as their 3/2 factor results in 3 bars for repetition breaking the _div calculation. The modified version
    _div = (CurrentMetroPulse + ( (HostBar-arpStartBar)%3) * pulsePerBar)
    also works for triplets and regular notes. arpStartBar = HostBar is stored when the first note for the arp chord arrives.

    And the last hint: The above method only arps when the Host is playing, but i extended the idea into a user-event (with pPulse and pBar parameters) that can also be called from @OnTimer used when the host is not running. The @OnTimer generates the pPulse and pBar by counting pulses, @OnMetroPulse supplies CurrentMetroPulse and HostBar.

    .

    If no unexpected distractions or problems arise, the In-Order Arp script will be published after the weekend . The core functionality is already working and GUI layout is done.

  • @_ki said:
    @McD Sounds cool 👍🏻 and is picking up the ideas we discussed with the StreamByter script.

    I also have an initial Mozaic version of a SmartChorder script based on the old ideas, but didn't work on that for the last half year. Please finish yours, so i don't have to finish mine :)

    .

    As i am currently writing an In-Order Arp script (requested in other thread) , i came up with the following idea for synced arps:

    When using a metropulse of ppqn, there are ppqn * HostBeatsPerMeasure pluses per bar. A 1/8 note will play for pulsePerBar / 8 which leads to divisions = Round (pulsePerBar / arpTiming )
    A gate-length of lenPercent % needs noteEndPulse = RoundDown ( divisions * lenPercent / 100 ) pulses

    Thats all the precomputation needed to run the following @OnMetroPulse event to generate the synced, arped notes:

    @OnMetroPulse
      _div = (CurrentMetroPulse % divisions)   
      if _div = 0
        // Time to start a new note
      elseif _div = noteEndPulse
        // Time to end a playing note
      endif
    @End
    

    More tricks: Triplets need divisions = Round ( pulsePerBar / arpTiming * 2 / 3) and fit nicely into a bar. To support dotted arps, i had to modify the base idea as their 3/2 factor results in 3 bars for repetition breaking the _div calculation. The modified version
    _div = (CurrentMetroPulse + ( (HostBar-arpStartBar)%3) * pulsePerBar)
    also works for triplets and regular notes. arpStartBar = HostBar is stored when the first note for the arp chord arrives.

    And the last hint: The above method only arps when the Host is playing, but i extended the idea into a user-event (with pPulse and pBar parameters) that can also be called from @OnTimer used when the host is not running. The @OnTimer generates the pPulse and pBar by counting pulses, @OnMetroPulse supplies CurrentMetroPulse and HostBar.

    .

    If no unexpected distractions or problems arise, the In-Order Arp script will be published after the weekend . The core functionality is already working and GUI layout is done.

    That will be a nice functionality to add to the Mozaic tool chest. And thank you for sharing the details on BPM note releases. I was having fun with various PPQN settings from 1-8 and then running 2 with polyrhythms like 2:3 or 3:4. You can generate some complex textures between 2 instruments.

  • McDMcD
    edited November 2019

    Sample test drive of my Mozaic script in it's current form. I can take a single MIDI note and convert it to:

    1: large chordal voicing - suitable for orchestral ensembles
    2: apply a configurable delay and arpeggiate the chord voices - suitable for pianos, harps

    I started up 2 copies and fed one to some strings and a synth and the 2nd to a piano and harp:

  • @McD said:
    Sample test drive of my Mozaic script in it's current form. I can take a single MIDI note and convert it to:

    1: large chordal voicing - suitable for orchestral ensembles
    2: apply a configurable delay and arpeggiate the chord voices - suitable for pianos, harps

    I started up 2 copies and fed one to some strings and a synth and the 2nd to a piano and harp:

    Wow, I loved that! Looking forward to this one!

Sign In or Register to comment.