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.

Streambyter Help (solved) -> 4 snapshot banks * 384CCs

edited October 2021 in App Tips and Tricks

Hi
I want to write a code which should write M2 value to array J under M1 index.

ASS JM1 = M2 +p This gives me error.

ASS J0 = M2 +p this one is working

I need write in array J under index = M1 value from M2.
Can somebody help me?
Thanks!

Comments

  • edited October 2021

    @szczyp said:
    Hi
    I want to write a code which should write M2 value to array J under M1 index.

    ASS JM1 = M2 +p This gives me error.

    ASS J0 = M2 +p this one is working

    I need write in array J under index = M1 value from M2.
    Can somebody help me?
    Thanks!

    Your problem is the "+P". You only need that in the if load section, to initialize a variable, and indicate that it should be preserved in the app state (saved in a host preset). You can only use +P on a simple assignment, not an indexed one. So, if you're planning to use 128 entries of J, you would initialize them all, as

    If load
    Ass J00 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P   # that's 16 zeros
    Ass J10 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
      .
      .
      .
    Ass J70 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    End
    

    Remember, the index is hex. Then, in the main part of the program, use

    Ass JM1 = M2
    

    The updated Jxx values will be saved in a preset because they were initialized with +P. You don't need to repeat it with every reference.

    You can get more directed help in the Audeonic forum, although there are some experienced SB coders here too.

  • WOW ,

    "The updated Jxx values will be saved in a preset because they were initialized with +P. You don't need to repeat it with every reference."

    solved!

    Can I ask second question?
    Is maximum number of available indexes = 3072, for storage user data in state-saving per AUv3 instance?
    array I, J , K , L - each 256 indexes, and W with 2048 indexes

    Thank you for help!

  • @szczyp said:
    Can I ask second question?
    Is maximum number of available indexes = 3072, for storage user data in state-saving per AUv3 instance?
    array I, J , K , L - each 256 indexes, and W with 2048 indexes

    Thank you for help!

    Yeah, I guess so. I've written quite a lot of SB code and never needed to consider it that way. Whatever you're doing might be a bit ambitious for SB though. Maybe you should consider a programmable sequencer, like LK or Atom 2. Anyway, good luck! You're welcome to check back if you hit any mystery snags, and make sure you End all your Ifs.

  • I like lego, and you asking me for playing with duplo?

    ;)

    my language is poor to understand what is "make sure you End all your Ifs" , can I ask for explanation?
    I any case, with your help, code is shorten and working!
    It receive input messages type CC on CH1, store it internally, and after save and load session, auto-send these CC values. Update include onboard Q faders.
    It also receive extra message: any note on CH1 will flush all stored CC messages.
    There is a block message at the end to block thru-going-by, this can be disabled manually.

    If load
    Ass W0 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W10 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W20 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W30 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W40 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W50 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W60 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W70 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    set include factory standard_includes
    end

    if control_q0_moved
    # Q0 has changed
    Send B0 $70 Q0
    ASS W$70 = Q0
    end
    if control_q1_moved
    # Q0 has changed
    Send B0 $71 Q1
    ASS W$71 = Q1

    end
    if control_q2_moved
    # Q0 has changed
    Send B0 $72 Q2
    ASS W$72 = Q2
    end
    if control_q3_moved
    # Q0 has changed
    Send B0 $73 Q3
    ASS W$73 = Q3
    end
    if control_q4_moved
    # Q0 has changed
    Send B0 $74 Q4
    ASS W$74 = Q4
    end
    if control_q5_moved
    # Q0 has change
    Send B0 $75 Q5
    ASS W$75 = Q5
    end
    if control_q6_moved
    # Q0 has changed
    Send B0 $76 Q6
    ASS W$76 = Q6
    end
    if control_q7_moved
    # Q0 has changed
    Send B0 $77 Q7
    ASS W$77 = Q7
    end

    subroutine sendCC
    ASS I0 = $70
    WHILE I0 < $78
    send B0 I0 WI0
    MAT I0 = I0 + 1
    END
    ASS I0 = $80
    WHILE I0 < $88
    send B0 I0 WI0
    MAT I0 = I0 + 1
    END
    END

    If load
    sendCC
    END

    If MT == 90
    sendCC
    Block
    End

    if M0 == B0
    ASS WM1 = M2

    If M1 == $70
    Ass Q0 = M2
    End
    If M1 == $71
    Ass Q1 = M2
    End
    If M1 == $72
    Ass Q2 = M2
    End
    If M1 == $73
    Ass Q3 = M2
    End
    If M1 == $74
    Ass Q4 = M2
    End
    If M1 == $75
    Ass Q5 = M2
    End
    If M1 == $76
    Ass Q6 = M2
    End
    If M1 == $77
    Ass Q7 = M2
    End
    Block
    End

    How I WILL try to use?

    Connect xTouchEX in CC mode from one side to AUM with this SB code, both connection IN OUT two "cables", now move faders somehow, after save AUM session, exit AUM, change faders position, run AUM and faders should be updated, so kind like snapshot - starting point. Thanks to your help!


  • First I set up faders, save AUM , change faders settings and again reload AUM to update hardware.

  • @szczyp You should put the sub SendCC inside the if load at the top. You could shorten the setting of Qx from a CC using indexing

    If M1 >= $70
       Mat I0 = M1 - $70
       If I0 < 8
          Ass QI0 = M2
       End
    End
    

    You can probably do the same thing handling the Qx moves.

    What I meant about Ending all the Ifs is that missing an End is a very easy mistake to make, since SB has no elsif keyword. And if an End is missing, the whole program is wrong, so it takes some work to find the error.

  • @uncledave
    What I will do without you?

    If load
    Ass W0 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W10 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W20 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W30 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W40 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W50 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W60 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    Ass W70 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +P
    set include factory standard_includes

    subroutine sendCC-and-updateQ
    ASS I0 = $0
    WHILE I0 < $8
    Mat I1 = I0 + $70
    Ass QI0 = WI1
    send B0 I1 WI1
    MAT I0 = I0 + 1
    END
    ASS I0 = $80
    WHILE I0 < $88
    send B0 I0 WI0
    MAT I0 = I0 + 1
    END
    END

    Subroutine Q-moved number_of_q q_value
    Mat I2 = number_of_q + $70
    Send B0 I2 q_value #send MIDI
    ASS WI2 = q_value #update for save-state
    End

    Subroutine received-CC
    ASS WM1 = M2 #update for save-state
    If M1 >= $70
    If M1 <= 77
    Mat I0 = M1 - $70
    Ass QI0 = M2 #update Q-faders
    End
    End
    END

    sendCC-and-updateQ
    End

    if control_q0_moved
    Q-moved $0 Q0
    end
    if control_q1_moved
    Q-moved $1 Q1
    end
    if control_q2_moved
    Q-moved $2 Q2
    end
    if control_q3_moved
    Q-moved 3 Q3
    end
    if control_q4_moved
    Q-moved 4 Q4
    end
    if control_q5_moved
    Q-moved 5 Q5
    end
    if control_q6_moved
    Q-moved 6 Q6
    end
    if control_q7_moved
    Q-moved 7 Q7
    end

    If MT == 90
    sendCC-and-updateQ
    End

    if M0 == B0
    received-CC
    End

    Block

    Working! If you know better solution for ifcontrolqmoved …. If not, I will stały with this. You helped me a lot!
    Gracias spasibas dżiekuje

  • edited October 2021

    Hi. The trick for the Qx motion is in the SB manual. This detects the internal message. M3 gives the index of Qx that changed.

    IF M0 == F0 7D 01 
       Q-moved M3 QM3
    End
    

    In Sub received-CC, 77 needs to be $77, or it will be hex. Tricky.

    You probably want Block after calling sendCC-and-updateQ in the note handler, so the note doesn't leak through. Edit: I see you have Block at the end of the script, so that's OK.

    Looks good now. Ought to work. Enjoy.

  • edited October 2021

    Goodmorning!
    Yours all words have bieg meaning for me.
    Yep, you are right , I was too ambitious to get SB, which is grreat, but have no more „hotel rooms available” for big sysex librarian with osc, with snapshots for CC for many devices in one instance. What is my idea, needs? (read later)

    Your way of thinking
    IF M0 == F0 7D 01
    Q-moved M3 QM3
    End
    Is 👌👍
    And „ 77 needs to be $77” - thank you.

    If I want to save in MIDIauv3 plugin bigger snapshot, for example 6000 parameters in snapshot, and have available memory for 100 big snapshots what should I choose? Mozaic?

    Have a nice day Bro!

  • wimwim
    edited October 2021

    There isn't anything ideal for that on iOS. Mozaic comes the closest.

    I just preliminarily completed a Mozaic script that saves and restores up to 16 channels * 128 CC's (= 2048 parameters). I'll probably put it up on patch storage after a some cleanup and more testing. Adding snapshots would bulk up the code considerably but wouldn't be too terrible hard to do.

    If you're interested in seeing what the code looks like, the first-draft is below:

    @Description
    CONTROLLER FEEDBACK AND RESTORE v0.2
    This script stores the last value of any MIDI CCs sent through it. On reload from a saved host session it dumps all stored CC's to the output. The use-case is for controllers such as the Midi Fighter Twister that display their encoder values when the values are echoed back to them. You can also manually trigger a dump by setting the USER 0 AU parameter or the first knob to 64 or greater (double-tap on the knob will also do this).
    
    Route the controller to this script, then to AUM control and also back to the controller. 
    ONLY DO THIS FOR CONTROLLERS DESIGNED TO WORK THIS WAY OR YOU MIGHT CREATE A NASTY MIDI LOOP.
    @End
    
    @OnLoad
    
      // delay in ms to insert between cc values when dumping, in case controller can't handle
      // too many simultaneous messages. Try increasing a little if any updates are dropped.
      SetTimerInterval 2
        
      if Unassigned init
        init = YES
        
        // Store the value of each channel + cc combination. There are 2048 possible combinations
        // so we need two arrays. -1 means nothing has been received for that combination.
        FillArray values1,-1
        FillArray values2,-1
        
        // It takes too much processing to brute-force loop through the two value arrays, so we
        // log the channel/cc combinations that have been received so we can just loop through
        // the ones that have been logged
        FillArray index1, -1
        FillArray index2, -1
        counter = 0
            
        for knob = 1 to 3
          SetKnobValue 0,0
          LabelKnob knob,{ }
        endfor
        LabelKnob 0,{Dump!}
        LabelKnobs { }
        SetShortName {FEEDBK}
        ShowLayout 4
        
      else
        Call @DumpControllers
      endif
      
    @End
    
    @OnMidiCC
    
      if MIDIChannel < 8
        check = values1[(MIDIChannel*128) + MIDIByte2]
        values1[(MIDIChannel*128) + MIDIByte2] = MIDIByte3 
      else
        check = values2[((MIDIChannel-8)*128) + MIDIByte2]
        values2[((MIDIChannel - 8)*128) + MIDIByte2] = MIDIByte3
      endif
      
      SendMIDIThru
      
      // Check if we've already received this Channel/CC combination
      if check = -1
        
        // Store a channel/CC combination in the next position of the index arrays
        if counter < 1024
          index1[counter] = (MIDIChannel * 0x100) + MIDIByte2
        else
          index2[counter - 1024] = (MIDIChannel * 0x100) + MIDIByte2
        endif
            
        Inc counter
        
      endif
      
    @End
    
    @OnKnobChange
      if LastKnob = 0 and (GetKnobValue LastKnob) >= 64 and not sending
        Call @DumpControllers
      endif
    @End
    
    @OnAuParameter
      if LastAUParameter = 0 and (GetAUParameter LastAUParameter) >= 64 and not sending
        Call @DumpControllers
      endif
    @End
    
    @DumpControllers
      LabelKnob 0,{Sending!}
      idx = 0
      sending = YES
      StartTimer
    @End
    
    @OnTimer
      if idx < 1024
        value = index1[idx]
      else
        value = index2[idx-1024]
      endif
      
      if value <> -1 and idx < 2048
        chan = Div (value & 0xFF00), 0x100
        controller = value & 0x00FF
      
        if chan < 8
          byte3 = values1[(chan*128) + controller]
        else
          byte3 = values2[((chan-8)*128) + controller]
        endif  
        SendMIDICC chan, controller, byte3
        Inc idx
      else
        sending = NO
        SetKnobValue 0,0
        LabelKnob 0,{Dump!}
        SetAUParameter 0,0
        StopTimer
      endif
    @End
    
  • edited October 2021

    @wim
    Nice to see you!
    Definitely you are working in the same direction, as SB code we build together with @uncledave also have płace for 2048 parameters and 1024 for additional….. but it is too limited , I will explain:

    We could consider the following scenario:

    • one auv3MIDI state saving per projekt master-memory-parameters plugin with dynamically allocated space for connected devices with n parameters each (often more than 128) , slave device will send handshake to inform about needed space. With possibility to copy data for single device to another snapshot, or whole snapshot to another

    • Many „translate-slave” plugins for each MIDI port/device communicate with master-memory via sysex
      What you think about my worry:
      Each device have separate port, some devices sharing the same signal by MIDI THRU, so one simple pluging with 2048 CC is in my opinion not enough. Sure, it is fun to have at least 2048 even without snapshots.

    It is a lot of work to manage parameters of SYNTH, fx, or other mixers. Some have sysex only.
    Sure we can record automation or use external (standalone) apps, but per projekt state-saving is attractive to at least try to understand where this idea is good and where is poor.

    If master-memory-plugin receive signal to chnge snapshot in range (selected devices) then it send again raw sysex to each translator, which translate it to specyfic for device messages.

    Maybe it is possible to dynamically allocate space in master-memory-plugin for each „translator” , by sysex handshake?

    In conclusion:

    • good to have 2048 CC memorizer for many simple tasks like controller feedback
    • Better to have the same plus more space and copy, Init function.
    • Everybody have different hardware controllers, devices, plugins, so easy to customize

    As mozaic have more memory, Im glad for your code here.
    Can I ask about yours opinion about possible limitation?

  • Hi @szczyp - tldr; ... I feel like even Mozaic isn't up to this task. There is "possible" and then there is "practical". Could a a very persistent person create something that works? Probably. But I think it would be terribly complex and involve too many workarounds to be practical. Sorry ... I do tend to be a pessimist in these things, but it remains that Mozaic wasn't really designed with this kind of scope in mind.

    We could consider the following scenario:

    • one auv3MIDI state saving per projekt master-memory-parameters plugin with dynamically allocated space for connected devices with n parameters each (often more than 128) , ...

    There is no dynamic allocation in Mozaic. The only way to store anything is in arrays with a maximum of 1024 numbers each. These must be pre-allocated in the code. I did do one experimental plugin that pre-allocated 64Kb of variable storage. It required more than 300 lines of code just to pre-allocate and manage those arrays.

    ... slave device will send handshake to inform about needed space. ...

    There's no way for Mozaic to detect when a device has connected, what device it is, what mode it's in, and any customizations, etc. So there's no way for a script to adapt to different controllers automatically. That leaves the user to select the device type from pre-configured choices, which would all need to be implemented separately in the code. Mozaic would be pretty limited in UI elements to use for selecting among many devices. The code could get very, very cumbersome.

    ... With possibility to copy data for single device to another snapshot, or whole snapshot to another

    • Many „translate-slave” plugins for each MIDI port/device communicate with master-memory via sysex

    There's no inter-app communication between instances. There are 100 "Global Variables" which are shared between all instances. You might be able to leverage these to do something like what you want. Otherwise you'd be stuck with trying to use MIDI to communicate between instances. Routing could become quite an issue, and also timing when trying to dump a bunch of midi all at once.

    What you think about my worry:
    Each device have separate port, some devices sharing the same signal by MIDI THRU, so one simple pluging with 2048 CC is in my opinion not enough. Sure, it is fun to have at least 2048 even without snapshots.

    I'm a little lost here trying to imagine the practicality of mapping that many parameters to controllers. Setting up a session to map even hundreds of controls would take hours. I also can't think that many people have a fraction of the number of controllers that would make use of that many parameters. I think I must be misunderstanding your goal.

    It is a lot of work to manage parameters of SYNTH, fx, or other mixers. Some have sysex only.

    Yes, every one is different. Not all accept feedback. Not all specifications are documented.

    Sure we can record automation or use external (standalone) apps, but per projekt state-saving is attractive to at least try to understand where this idea is good and where is poor.

    If master-memory-plugin receive signal to chnge snapshot in range (selected devices) then it send again raw sysex to each translator, which translate it to specyfic for device messages.

    In theory that sounds possible. In practicality one could spend their life working on this translator.

    Maybe it is possible to dynamically allocate space in master-memory-plugin for each „translator” , by sysex handshake?

    No, this isn't possible with Mozaic.

    In conclusion:

    • good to have 2048 CC memorizer for many simple tasks like controller feedback
    • Better to have the same plus more space and copy, Init function.

    Honestly I don't really see it due to the need to map each CC to what it will control anyway. I can't imagine mapping more than a few dozen controls to be something most people would go through. Probably more like 16 controls maximum per session for most people, I would think.

    • Everybody have different hardware controllers, devices, plugins, so easy to customize

    I'm just not really following you. Synths and hosts have MIDI Learn already for mapping controller output to parameters. Why try to package this into a script? I think I must be missing something about your idea.

    Can I ask about yours opinion about possible limitation?

    Sorry to be so discouraging. I admire your ambition. I'm just not sure Mozaic is up to this task. Also I'm not sure I visualize the practicality of the idea in general, though it's likely I just don't understand it fully.

  • @wim thank you for deep understanding and response. Yes, you are right: Im still dont know what I need to develop, but 100% still need to anawer this question (and close my internal loop IF).

    I see in imagination many different parts of this setup (many controllers, many devices to be controlled) and this is really hard to connect in inspirational way.

    Everything depend from what is the goal to achieve.

    If simple plugin-like style , to build every session in any host and be FREE, then I will consider it more. I will back I hope soon.

    And thank you for share yours code.

  • wimwim
    edited October 2021

    Best of luck with your idea @szczyp. I hope I wasn't too discouraging.

    Atom2 has a unique way of being able to communicate directly with controllers. It can recognize them by their connection names, and has scripting built in for two-way communication. I don't think Atom 2 is exactly what you need for this either, but maybe learning more about its scripting capability would help to refine your ideas. What documentation there is can be found at: https://github.com/victorporof/atom

  • edited October 2021

    It was not possible to help me better than show me where my thinking was blured.
    And was. I expected an internal protocol to keep track on parameters in session, but it is not exist.
    The only simple solution is in midi CCs and our (can I say it?) plugins-memory.
    It capture incoming CC on all channels , without thru-sending, but send all parameters (or filtered) at load session (or trigger Message). This is what we have now, and its allow to have MIDI Feedback on hardware controllers inDRAMBO, AUM and more.
    It is huge!
    Atom2 - good idea also , but I leaved ATOM2 for sequencer everyday tasks , even without LP and scripting as option to extend it , If needed.

    Shorting long story…

    Because this conversation, i found END in my thinking! Thank you @uncledave and @wim !

    I changed my expecations to more relistic, this is what I found:

    Level 1 : CC MEMORIZER with autoload and (specified trigger) sending - I think we have it, its ready. Described earlier.
    How many controllers I use? Exactly the same how many hardware controlls available. With 4 xtouches it is more than 100, and no switching bank Pages setup. So level 1.

    Level 2: controller with switching banks of CCs. Custom hardware, custom code or ready to buy. It is the same situation but with more CCs to map.
    Because xtouch have no Pages, there is possibility to do them in SB , mosaic. Even without parameters NAME on LCD, but with shown CC number, channel and value! So rather my personal need. But we can do it also in Mosaic and SB, for example:
    REVERB with 20 parameters shown on 3 pages with 8 knobs, but hey! On next pages can be other effect, and other. After midi map it all, it will be pleasure to control from one place more devices. All customizable.
    So basicaly level 2 is about controller pages. Not every one need this.
    Level 1 is mostly for hardware Feedback. But with level 3….

    Level 3: snapshots. There is as many configurations possible as many memory available, in theory would be nice to have snapshots with all 2048 CCs. At least 8 snapshots so 16384 hotel rooms was my first thinking.
    I dont know how long will be sending 2048 CC, via MIDI probably more than 6 seconds.
    But we can filter out not mapped, not needed CC!

    and If somebody want separate snapshots , or just memory for hardware Feedback device, there should be internal „lock” system for not capture, sending some selected Messages. This allow to specify what CCs are stored and sent.

    Thats all!
    I hope it was readable (not native language).
    Will be happy to see your comments.

  • edited October 2021

    Maybe atom2 allow to use internal memory for store incoming CC not in timeline but in one step? I didn't check in deep scripting in Atom yet.

    Or LK ….. will implement one day „step recording mode” with not auto select next step? Maybe Halion have this already.... I will eventually check.
    Then we can send all CC, STORE IN FIRST STEP in clip, and by change Clips we could change snapshots... if it is implemented.

    Do you see highlights of this idea?

  • edited October 2021

    Sorry for triple message, I want only show midi hardware feedback this time in Drambo.
    Still use SB (at the moment), code will be extended to 2048 plus filter on output (to select range outputted message). Level 1 almost completed. CC are MIDI mappable on Drambo, MIDI feedback at open project works, also during session it is possible to trigger output message to update controller.

    EDIT: I found Drambo filter out messages from stream , that are assigned as MIDI learn. The same BM3 - midi learned commands are omitted in MIDI input stream to track.

    AUM allow to separate track for SB and then assign SB as MIDI control source for AUM.

    Atom2 have direct controller communication as you said. So I think there are also arrays and all tools need to rewrite memorizer on that platform.

    EDIT2: I found solution to use memorizer in Drambo and get MIDI feedback working, but by using MIDI Route to Drambo #Control instead of native building MIDI OUTPUT module. Also input track (xTouch) I changed to #track only.

    This way xTouch -> track input to SB -> MIDI Route to Drambo MIDI input #control.
    Feedback to controller need MIDI output module but is used only during update hardware controller.

  • OK I got working snapshots in Drambo.

    Decided to go with 384 CCs , all under hardware controls by using 4 x xTouch + BSP.
    So I have 5 places * 384 parameters in array W (SB).
    One buffer and 4 save destinations.
    4 snapshots x384CC in one SB, ready to midi learn in Drambo, AUM etc

    I will test this more.
    One more time thank you!!

Sign In or Register to comment.