Audiobus: Use your music apps together.

What is Audiobus?Audiobus is an award-winning music app for iPhone and iPad which lets you use your other music apps together. Chain effects on your favourite synth, run the output of apps or Audio Units into an app like GarageBand or Loopy, or select a different audio interface output for each app. Route MIDI between apps — drive a synth from a MIDI sequencer, or add an arpeggiator to your MIDI keyboard — or sync with your external MIDI gear. And control your entire setup from a MIDI controller.

Download on the App Store

Audiobus is the app that makes the rest of your setup better.

The Unofficial Mozaic User Helpline

13567

Comments

  • @wim said:

    @Krupa said:

    @wim said:
    Adding a timer isn't that bad. See example above. It seems to mostly work except for maybe when you do a bunch of rapid tap combinations on a bunch of pads. I'm sure it could be made bullet-proof, but the coffee hasn't started to kick in yet here. Needs a pro like @_ki to give it a look.

    Ah cheers, I didn’t see the edit, I’ll try and get my head round it in a bit and see if I can make it work with the tap/hold bit you so kindly helped with the other day :)

    Ta!

    Tap-hold is still there in the example. It just adds detecting multiple taps.

    Ah cool, sorry, I couldn’t see it in my quick skim, thanks 🙏

  • _ki_ki
    edited August 2020

    I didn‘t have to time check wims source code. But in some wake-time during the night, i though about a different approach than what i‘ve done in the Shift&Pad Manager:

    The P&S Manager uses an analysis timewindow of ≈200msec. The OnXxxDown/OnXxxUp functions only register the taps and store a timestamps of the first press - the timer checks if analysis time is over and then calls the appropriate user event callback. This results in a big delay for single clicks, as the user event callback is fired at the end of the analysis timewindow. Double clicks, tripple clicks and holds etc are all fired in the ontimer if the time for that specific pad or the shift buttons has run up.

    .

    My new idea doesn‘t do the double-click detection and event firing in the OnTimer - instead there is a short timewindow (maybe 50msec) watched after an OnXxxUp event - if the initially triggered pad or shift button has not been down again, this must have been a single tap. The OnTimer just would fire this single tap to the user-code. The double-taps, holds etc are done in the OnXxxUp events. A detected single-tap resets that pads/shift state, so that a new tap is handled as fresh start, not as the ‚next‘ tap in a row.

    The reaction time to SingleTap is a lot shorter using this new idea, but it can no longer detect tripple taps (which probably no-one ever uses)

    .

    I‘ll check wim‘s idea later this day and check the imposed delays for the various taps of his solution.

    Maybe i can do a short script, demonstrating my new idea - but i will definitely update my pad/shift manager to use this new algorithm as its better than what i implemented before. Devs using the include snippet just need to update that source part to get the faster single tap reaction, everything in their own code part stays the same.

  • Now i‘ve checked @wim ’s code: Nice 👍🏼

    At first i didn‘t understand the purpose of the maxTaps part, but it‘s there to force a reaction of the pad-detection. Otherwise one could continously tap a pad and never get a reaction.

    In your code, the detection time of 300ms starts on the pad up, all detections except long-press are delayed by this amount measured after the last pad up, not by the first initial press. This can be improved to 300ms after the first pad up by setting downEnd[pad] only if taps[pad] = 0

    The P&S Manager delays a single tap by 250ms starting from the first pad down and my new idea would react 50ms after the pad up of a single tap. I didn‘t yet verify if 50ms is a good value for the time between two double-taps, maybe its 75 or 100 - which still would be better that the previous ideas.

  • In another script I use a variation that doesn’t wait for the pad up to dispatch a long press. In that case the time is measured from the time the pad is pressed down.

    I can post that script if anyone is interested. It deals with midi note on and off rather than pad presses, but the ideas are the same.

  • i need help 😎
    i’m wondering if there are any scripts, or possible scripts to have mosaic change patterns for you either with the press of a button, the turn of a knob or set to auto switch after a certain amount of steps are played...
    for example to have it change patterns in apps like drambo, cykle, SPA or “snapshots” in step/arp bud while hosted in AUM.
    i just want to have all my songs done with apps like these but trying to change patterns manually especially on several instances is hard and i don’t believe, other then drambo any of those apps have song modes.

  • Hmm - just added logging of the time between double-taps in regards to the total duration of a double tap. And then i added statics computation and double-tapped happily along with various fingers fom both hand:

    STATISTICs for 312 double taps
     __Total_____Tap1____Gap____avg___Tap2___Cnt__
      125-150   23-23   58-58    58   81-81    1
      150-175   12-46   46-81    67   43-104  33
      175-200   41-58   64-76    69   57-76   93
      200-225   54-72   75-93    83   65-127  65
      225-250   58-72   92-104   97   72-139  33
      250-275   47-81   97-162  127   72-162  18
      275-300   58-85  108-151  134   88-140  10
      300-325   49-70  154-212  182   61-82   13
      325-350   52-64  202-226  214   68-93   34
      350-375   59-93  198-243  222   86-174  10
      375-400   81-82  220-244  232  139-164   2
    

    If i want to support up to 250ms, the single tap can safely be detected ≈125ms after the pad up .

  • wimwim
    edited August 2020

    @reasOne said:
    i need help 😎
    i’m wondering if there are any scripts, or possible scripts to have mosaic change patterns for you either with the press of a button, the turn of a knob or set to auto switch after a certain amount of steps are played...
    for example to have it change patterns in apps like drambo, cykle, SPA or “snapshots” in step/arp bud while hosted in AUM.
    i just want to have all my songs done with apps like these but trying to change patterns manually especially on several instances is hard and i don’t believe, other then drambo any of those apps have song modes.

    If I understand correctly, you're looking for something that would queue up configurable midi messages to be sent out some number of bars or beats later. If so then there's one script that might kinda-sorta fit the bill: https://patchstorage.com/orchestra/. I've not tried it myself.

    The difficulty is there's no common way of changing patterns across different apps. So, you need to be able to configure which messages get sent and to where in advance. For instance, with Drambo you can only map a midi message to a specific pattern, there's no "Next" and "Previous" pattern selector. With Rozeta it's based on which note you send. Some others use program change, etc. etc.

    Also, applications vary in how long before the start of a measure or beat they need to receive a command to process a pattern change. Some change more or less instantaneously and others you need to send before the beat actually arrives.

    It's a bit like trying to herd cats.

    There's no simple answer using Mozaic or any other app for that matter.

  • good info @wim i’ll check out that script and see if i can make it work for some of what i’m trying to do. it seems like nothing beats a daw like zenbeats/cubasis for changing sequences, im also going to look into seeing if LK can send midi to a pattern change parameter , if that was possible you could have multiple clips trigger different sequencer patterns at once, but it probably isn’t possible.
    but if you could somehow have one midi note on each clip and just run say 8 bars then change clips to trigger another note...haha the more i write this out the more i’m thinking no way this is possible 🤣

  • @wim, from reading it looks like there could be a few problems:

    • not handling multiple pads pressed in the timer event
    • Using the last tap’s release time while a pad is currently down in the timer event (this could cause issues if there was non-trivial processing in the timer or anything it calls)
    • Not sure what it’s supposed to do while the pad it being pressed when the timer goes off

    Although this sample counts taps in a three second window, it doesn’t really do double-tap handling. For that you’d need to define the max time between release and press that you’ll interpret as a double-tap. You’d fire the double-tap event in the padUp (or padDown depending on the needs) event and then the single-tap event in the timer event after that window expires. I’m sure you realize that the latency of the single-tap is just shy of 2x your timer frequency.

    I think this might work but as you can see it hasn’t been attempted

    OnLoad
      NumPads = 16
      FillArray PadExpiration, 0, NumPads
      FillArray PadDoubleTapped, 0, NumPads
      DoubleTapTime = 500  // millisecond window between a release and tap that is considered a double-tap
      StartTimer 10
    
    OnPadDown
      If ( PadExpiration[LastPad] > 0 ) and ( SystemTime - PadExpiration[LastPad] < DoubleTapTime )
        Call OnPadDoubleTapDown
        PadDoubleTapped[LastPad] = 1
      Endif
      PadExpiration[LastPad] = 0
    
    OnPadUp
      If PadDoubleTapped[LastPad]
        Call @OnPadDoubleTapUp
        PadExpiration[LastPad] = 0
      Else
        PadExpiration[LastPad] = SystemTime
      Endif
      PadDoubleTapped[LastPad] = 0
    
    
    OnTimer
      For I = 0 to NumPads - 1
        If ( PadExpiration[i] > 0 ) and ( PadExpiration[i] - SystemTime >= DoubeTapTime )
          PadExpiration[i] = 0
          Pad = i 
          Call OnPadSingleTap
        Endif
      Endfor 
    
    
  • wimwim
    edited August 2020

    Thanks @xor - I’ll leave it to others to take further. It’s not something I plan to give attention until I need it in context later.

    The timing works out fine for me. I intentionally want the built up latency. My interest is the duration of and between each tap, not the total duration of a double or triple tap.

    Also, I generally wouldn’t care about detecting across several pads. It would be only one at a time for anything I plan to do (which is related to detecting one switch at a time from a BlueBoard only and works exactly as I need it to in the only scripts where I deal with different tap combinations.

    But thanks for the info. 👍🏼

  • @wim said:

    @_ki said:
    I suspect that double-tap detection needs a running timer. Perhaps i find some time later in the evening to do a minimal example - or maybe @wim already has something in his sleeves :)

    I'm not sure how reliable this is. It's simpler when not trying to handle multiple pads but I kinda committed myself to that road with the last example. :D

    @OnLoad
      FillArray downStart,0,16
      FillArray downEnd,0,16
      FillArray taps,0,16
      pressTime = 300
      maxTaps = 3
      SetTimerInterval 10
      StartTimer
      ShowLayout 2
    @End
    
    @OnPadDown
      downStart[LastPad] = SystemTime
    @End
    
    @OnPadUp
      pad = LastPad
      downEnd[pad] = SystemTime
      
      if downEnd[pad] - downStart[pad] < pressTime
        if taps[pad] < maxTaps
          Inc taps[pad]
        else
          Log {Pad }, pad, {: tap ignored (too many taps) }
        endif
      else
        taps[pad] = 0
        Log {Pad }, pad, {: long-press} 
      endif
    @End
    
    @OnTimer
      if (not Unassigned pad)
        if SystemTime - downEnd[pad] >= pressTime and (taps[pad] > 0)
         Log {Pad }, pad, {: }, taps[pad], { taps}
          taps[pad] = 0
        endif
      endif
    @End
    

    I’m just getting around to implementing this - am I right to think that I put any tap actions within the @OnTimer event or is that a total nono?

  • It doesn‘t matter in which of the Mozaic events you do your scripts computational work - its ok do handle the result of taps in the OnTimer.

  • Sweet, cheers @_ki

  • wimwim
    edited August 2020

    @Krupa said:
    I’m just getting around to implementing this - am I right to think that I put any tap actions within the @OnTimer event or is that a total nono?

    Please be sure to check other's comments on this bit of code. I only skimmed them, but it seems that there's a difference in approach when checking tap durations. I only care about the duration of the tap itself and the pause to the next one, while I think others are concerned about the adding up of the length of time for the total number of taps. Or something like that. I'll be honest, I haven't paid much attention as I figure the others looking at this have a better handle on scripting than I do.

    I have only limited brain storage so I've had to flush the buffers on this one to free up space for other thoughts. So the added attention of the guys in the giga brain cell department is mucho appreciated.

  • The basic code works as well as I need, it’s only for editing stuff not triggering or anything time critical - and it already incorporates the hold which is vital, thanks again :)

  • If you need things like hold to not wait for the pad-up, but to dispatch as soon as the timeout happens, I can dig up an example from one of the other scripts I've done.

  • I actually just got it doing what i wanted but quickly noticed that single taps don’t trigger when the host is running, l might be doing other things that make that happen though, this script is eating my brain for supper each evening at the moment 😂

  • Figured it out, I was using the ‘pad’ variable in function calls being made by this routine so that was interfering, seems fine now that I’ve changed it to ‘padPressed’ 🤞🧨😅

  • @brambos - Is there some sort of limit on defining arrays? I keep getting crashes trying to build one to define all the carrier / modulator masks in this sequencer I'm working on...

    I'm trying to add the data below - it's well below the limit of the size of an array but just kills the plugin every time I upload a script with this data in. I've even tried separating it into 32 sets of six entries each, but still the same result..

    1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,1,0,1,1,1,1,1,1

  • wimwim
    edited August 2020

    @Krupa -can you post the actual line(s) of code? Also, how many total lines of code are there in the script and how many variables? There are limits on both.

  • Cheers @wim

    This is the code I'm using to make the array

    carrierMaskList[0] = [1,1,0,0,0,0]
    carrierMaskList[6] = [1,1,0,0,0,0]
    carrierMaskList[12] = [1,1,0,0,0,0]
    carrierMaskList[18] = [1,1,0,0,0,0]
    carrierMaskList[24] = [1,1,1,0,0,0]
    carrierMaskList[30] = [1,1,1,0,0,0]
    carrierMaskList[36] = [1,1,0,0,0,0]
    carrierMaskList[42] = [1,1,0,0,0,0]
    carrierMaskList[48] = [1,1,0,0,0,0]
    carrierMaskList[54] = [1,1,0,0,0,0]
    carrierMaskList[60] = [1,1,0,0,0,0]
    carrierMaskList[66] = [1,1,0,0,0,0]
    carrierMaskList[72] = [1,1,0,0,0,0]
    carrierMaskList[78] = [1,1,0,0,0,0]
    carrierMaskList[84] = [1,1,0,0,0,0]
    carrierMaskList[90] = [1,0,0,0,0,0]
    carrierMaskList[96] = [1,0,0,0,0,0]
    carrierMaskList[102] = [1,0,0,0,0,0]
    carrierMaskList[108] = [1,1,1,0,0,0]
    carrierMaskList[114] = [1,1,1,0,0,0]
    carrierMaskList[120] = [1,1,1,1,0,0]
    carrierMaskList[126] = [1,1,1,1,0,0]
    carrierMaskList[132] = [1,1,1,1,0,0]
    carrierMaskList[138] = [1,1,1,1,1,0]
    carrierMaskList[144] = [1,1,1,1,1,0]
    carrierMaskList[150] = [1,1,1,0,0,0]
    carrierMaskList[156] = [1,1,1,0,0,0]
    carrierMaskList[162] = [1,1,1,0,0,0]
    carrierMaskList[168] = [1,1,1,1,0,0]
    carrierMaskList[174] = [1,1,1,1,0,0]
    carrierMaskList[180] = [1,1,1,1,1,0]
    carrierMaskList[186] = [1,1,1,1,1,1]

    The whole script itself is just north of 1000 lines, though there are blank ones in between things...

  • wimwim
    edited August 2020

    @krupa - It works fine in a fresh script, even without being broken up into multiple lines. How many variables do you have in the script? What is the error you’re seeing?

  • It just bombs the plugin when I add it to the declare list... I’ve lost count of the variables but I just added a couple more as I was adding (yet) another feature 🤪 and it’s fine... should I post the whole thing?

  • wimwim
    edited August 2020

    Maybe just the error message you’re seeing? My guess that it could be too many variables is apparently not it.

  • There is no error message, just the dead plugin with red diagonal lines.... :#

  • hmm actually, just copied and pasted it back in and suddenly no crash, confused, sorry @wim

  • Maybe it was the Mozaic equivalent of a Psychotic Break. You’re driving it mad.

    More seriously though - sometimes in the process of copy / pasting into the script, I miss the crucial “select all” and end up with two pastes of the code in the script. That can lead to some head scratching moments. I’ve never had it actually crash the plugin, but maybe with a big enough script it could.

  • Yeah, weird, I did have a similar thing with it the other day with another dataset, was from pasting in after editing on laptop, couldn’t stand to try and enter all that on the iPad... thanks for checking though, I’m getting there, step by step :)

  • Topping the max number of variables shows an error message and new vars don‘t get assigned and will throw further ‚undefined‘ syntax error messages when used.

    .

    I managed to crash Mozaic when the per line length was tooo long, i think its somewhere between 128 and 150 chars per line - but since i often uses unicode chars in my label assignments (which use multiple bytes per char) i could be wrong.

    .

    The max script length seems to depend on the textsize, not the number of lines. The limit is somewhere around 128kb of text. I have scripts using 3300 lines. The internal editor will start having problems showing the higher lines numbers, only up to 2500 are visible - but longer scripts still work.

    If you go over the max size limit, the parser just stops parsing and seems to ends the current event function as if there was an Exit command right at the last line it interprets ignoring the rest of the event function.
    New event funtion definitions below the maximum script size are not detected and calling them outputs a ‚unknown event function‘ error. I don‘t get crashes even when having 500 more lines as allowed, they just don‘t work.

    During development of such longer scripts, i add a LengthWatchdog event function right at the end of my script that is called as first action in the OnLoad.

    @LengthWatchdog
      Log {LengthWatchDog: Ok}
    @End
    

    If i don‘t see the Log message when loading the script, i know i have to shorten the script again :)

  • Ha, good knowledge thanks @_ki , I don’t think I’m hitting those limits yet, and hopefully won’t with this one 🤞

Sign In or Register to comment.