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.

Learn to Program the Mozaic Workshop to create MIDI FX and Controllers *you could learn something*

1234689

Comments

  • @horsetrainer said:
    It would be nice if more people were interested in this.

    Like most very cool things... it's addicting.

    Most professional developers write code in their spare time just to tackle interesting problems or
    make cool apps. Either way... someone can fall into this world. Problems or bon-bons or both:
    solve the problem, get the treat. Classic addiction stimulus-response mechanism to train a behavior.
    Who says we cannot change? Just find new addictions that are positive and lose those that are not.

  • I made a new script that has a lot of new ideas for me using scales and parallel harmonized
    melodies.

  • This morning i got the following request

    I am trying build a simple midi modifier.
    essentially i want to play a midi note in, and have 2 on and off knobs. 1—adds a -1 octave to the midi note being played. 2— adds a +1 octave to the note being played. so basically if i play an E note in. i get a lower middle and upper E note coming out of Mozaic and into another app. but i don’t know how to tell Mozaic to do it. do you have any suggestions?

    And i though this might be a good example for a easy-to-read and understandable development of a Mozaic script - thats why i post the answers and even the development ideas and pitfalls in this workshop thread (after asking for permission to do so).

    .

    The request seems straight forward and complete:

    • For each incomming note, add a sub-octave and another note one octave higher, if their knobs are dialed to do so.

    In Mozaic each incomming midi event fires several events (Other languages name this behavior ‚calls user-defined functions or subroutines) . Regarding notes, there are three relevant events:

    • OnMidiNote Is called for all NoteOn and NoteOff events with the parameters for command, note, channel, velocity of the current note returned by the Mozaic functions MidiCommand, MidiChannel, MidiNote and MidiVelocity and the same raw data returned by MidiByte1, MidiByte2 and MidiByte3. According to the midi standard, MidiByte1 is a combination of MidiCommand in the upper 4 bits and MidiChannel in the lower 4 bits
    • OnMidiNoteOn is fired/called for NoteOn‘s only, the parameters are retrieved like in OnMdiNote
    • OnMidiNoteOff is fired/called for NoteOff‘s only, the parameters are retrieved like in OnMdiNote

    If a script declares such an event, it will be called.

    .

    So in our case, the first idea might be to use the OnMidiNote event, since the script will behave the same for NoteOns and NoteOffs according to the request:

    • First, output the incoming midi event, as Mozaic’s does not forward any incoming midi per default
    • A knob‘s position is retrieved using GetKnobValue ‚knobnumber‘, it will return 0 to 127 with 64 beeing the center position
    • If an octave‘s knob is bigger than 64, send out the same command as the incoming one, but with a shifted note. An octave is 12 notes, so one needs to be 12 less and the other 12 higher than the incoming note number.
    • Using the same command a incoming one ensures that for each NoteOn the script generates new NoteOns and for incoming NoteOffs the script generates additional NoteOffs

    Here is this simple, but fully working first version:

    @OnMidiNote
      SendMIDIThru
    
      if (GetKnobValue 0) >= 64
        SendMIDIOut MidiCommand+MidiChannel, MidiNote-12, MIDIVelocity
      endif
    
      if (GetKnobValue 1) >= 64
        SendMIDIOut MidiCommand+MidiChannel, MidiNote+12, MIDIVelocity  
      endif
    @End
    
  • _ki_ki
    edited April 2020

    But there are at least two bugs lurking in there:

    Bug 1

    If the incoming note number is in the lowest octave, there is no possible note below that - same for incoming notes in the highest octave. The computation of MidiNote-12 or MidiNote+12 will overflow to an illegal value (the valid note range is 0..127)

    This problem can simply be solved by adding more conditions - only play an additional note, if possible:

      if (GetKnobValue 0) > 64 and MIDINote >= 12
        SendMIDIOut MidiCommand+MidiChannel, MidiNote-12, MIDIVelocity
      endif
    
      if (GetKnobValue 1) > 64 and MIDINote <= 115
        SendMIDIOut MidiCommand+MidiChannel, MidiNote+12, MIDIVelocity
      endif
    
  • _ki_ki
    edited April 2020

    Bug 2

    Now try the simple script again

    • turn on lower and high octave generation by turning knob 1 and knob 2 to the right
    • Press and hold a note and while holding the notes, turn back knob 1 and two.
    • On releasing the note, only the original note gets a NoteOff - the two additional keep playing. This ‚effect’ is called ‚hanging notes‘

    It turns out, that the simple idea on using the same code for NoteOn and NoteOff does not work. The other two event functions need to be used with slightly different implementation:

    • On NoteOn, read the knobs and add additional notes if enabled. For each channel/note combination, store what additional notes have been generated
    • On NoteOff, use the stored information and not the current knob values

    Sounds complicated, but in fact isn‘t as Mozaic already offers support for these kind of tasks:

    @OnMidiNoteOn
      SendMIDIThru
    
      playLow  = NO
      playHigh = NO
      if (GetKnobValue 0) > 64 and MIDINote >= 12
        SendMIDIOut MidiCommand+MidiChannel, MidiNote-12, MIDIVelocity
        playLow  = YES
      endif
    
      if (GetKnobValue 1) > 64 and MIDINote <= 115
        SendMIDIOut MidiCommand+MidiChannel, MidiNote+12, MIDIVelocity
        playHigh = YES
      endif
    
      SetNoteState MIDIChannel, MIDINote, playLow + 2*playHigh 
    @End
    
    
    @OnMidiNoteOff
      SendMIDIThru
    
      played = GetNoteState MIDIChannel, MIDINote
      if played & 1
        SendMIDINoteOn MIDICHannel, MIDINote-12, MIDIVelocity 
      endif
    
      if played & 2
        SendMIDINoteOn MIDICHannel, MIDINote+12, MIDIVelocity 
      endif  
    @End
    
  • oh this is brilliant, and makes sense. thanks so much for breaking it down and explaining what is going on. excellent lesson. your awesome !

  • Adding a GUI

    The above working and tested script does not provide any GUI or feedback on what to except or how the current state is.

    The user needs to know that knob 0 turned left means ‚no lower octave‘ and turned right means ‚add a lower octave‘. The same for knob 1.

    .

    First lets setup a clean GUI by setting all labels, knob positions and XY pos to better (clutter-free) default values. This is done once in the OnLoad event:

    @OnLoad
      SetShortName {OCTAVR} 
      LabelKnobs {Octaver  v1.0}
      LabelPads { }
      LabelXY { }
    
      SetXYValues 0,0
      for knob = 0 to 9
        LabelKnob knob, { }
        SetKnobValue knob, 0
      endfor
    @End
    

    Add above, code and try again: Looks a lot cleaner now:

    From there we can start to add the labels for our two knobs:

    • Since the code will be used twice (when initially displaying the UI and later when turning knobs) its best to use a user-defined event for this purpose:
    @RedrawOctaverKnobLabels
      if (GetKnobValue 0) >= 64
        LabelKnob 0, {Low: ON}
      else
        LabelKnob 0, {Low: -}
      endif
    
      if (GetKnobValue 1) >= 64
        LabelKnob 1, {High: ON}
      else
        LabelKnob 1, {High: -}
      endif
    @End
    

    This functionality can be applied by adding Call @RedrawOctaverKnobLabels where needed.

    So we need to add that line to end of the OnLoad event and also to a new added OnKnobChange event.

  • _ki_ki
    edited April 2020

    This results in the following complete script with GUI

    @OnLoad
      SetShortName {OCTAVR} 
      LabelKnobs {Octaver  v1.0}
      LabelPads { }
      LabelXY { }
    
      SetXYValues 0,0
      for knob = 2 to 9
        LabelKnob knob, { }
        SetKnobValue knob, 0
      endfor
    
      Call @RedrawOctaverKnobLabels
    @End
    
    
    @OnKnobChange
      Call @RedrawOctaverKnobLabels
    @End
    
    
    @RedrawOctaverKnobLabels
      if (GetKnobValue 0) >= 64
        LabelKnob 0, {Low: ON}
      else
        LabelKnob 0, {Low: -}
      endif
    
      if (GetKnobValue 1) >= 64
        LabelKnob 1, {High: ON}
      else
        LabelKnob 1, {High: -}
      endif
    @End
    
    
    @OnMidiNoteOn
      SendMIDIThru
    
      playLow  = NO
      playHigh = NO
      if (GetKnobValue 0) > 64 and MIDINote >= 12
        SendMIDIOut MidiCommand+MidiChannel, MidiNote-12, MIDIVelocity
        playLow  = YES
      endif
    
      if (GetKnobValue 1) > 64 and MIDINote <= 115
        SendMIDIOut MidiCommand+MidiChannel, MidiNote+12, MIDIVelocity
        playHigh = YES
      endif
    
      SetNoteState MIDIChannel, MIDINote, playLow + 2*playHigh 
    @End
    
    
    @OnMidiNoteOff
      SendMIDIThru
    
      played = GetNoteState MIDIChannel, MIDINote
      if played & 1
        SendMIDINoteOn MIDICHannel, MIDINote-12, MIDIVelocity 
      endif
    
      if played & 2
        SendMIDINoteOn MIDICHannel, MIDINote+12, MIDIVelocity 
      endif  
    @End
    

    Did you notice that the for loop in OnLoad now only runs from 2 to 9 ?

    • The first two knobs are ‚our‘ octaver knobs and not resetting their value on startup will recall the values saved with a preset - State saving without any effort
    • Their labels are set according to their values by ‚calling’ RedrawOctaverKnobLabels right at the end of the OnLoad
  • _ki_ki
    edited April 2020

    I tend to write longer scripts, therefore i add some more steps right from the start to not hinder further development into a more complex script:

    • Instead of using the knob or pad numbers directly, i define constants with their numbers. This allows to later easily change the whole layout without the need to touch the computing or knob handling code in all places. Just need to change the constant for that
    • Instead of using the knob values directly (and reading them) i tend to use variables for the different states that are set in the OnKnobChange and use throughout the computational code - this decouples the computation from the GUI - and allows to test the computational code before doing the UI by just using the vars (and changing them before each test run)
    • For ‚toggle stuff‘ i would suggest to use the pads instead the knobs. One can use either LatchPad padId to toggle a pads highlighting, or even use different colors for the pads states with ColorPad padId

    Here a variant using these suggestions, offering an additional volume modificator knob for both added octave notes and applying pad highlighting:

    @OnLoad
      SetShortName {OCTAVR} 
      LabelKnobs {Octaver  v1.5}
      LabelPads { }
      LabelXY { }
    
      // Using vars instead of knob values to decouple UI from script states
      if Unassigned octLow
        playLow    = NO
        playHigh   = NO
        volumeLow  = 100
        volumeHigh = 100
      endif
    
      // Constants for pad and knob assignment, to allow easy changes
      PAD_LOW       = 1
      PAD_HIGH      = 3
      KNOB_VOL_LOW  = 0
      KNOB_VOL_HIGH = 5    
    
      // Constants for min/max volume
      MIN_VOL = 50
      MAX_VOL = 150
    
      // Label and highlight the pads    
      LabelPad PAD_LOW, {Low Oct}
      LabelPad PAD_HIGH,{High Oct}
      LatchPad PAD_LOW, playLow
      LatchPad PAD_HIGH,playHigh
    
      // Cleanup the UI
      for _knob = 0 to 9
        SetKnobValue _knob, 0
        LabelKnob _knob, { }
      endfor
      SetXYValues 0,0
    
    
      // Initiate knob labels and positions
      LabelKnob KNOB_VOL_LOW,  {L },volumeLow, { %}
      LabelKnob KNOB_VOL_HIGH, {H },volumeHigh,{ %}
    
      SetKnobValue KNOB_VOL_LOW,  TranslateScale volumeLow , MIN_VOL,MAX_VOL, 0,127
      SetKnobValue KNOB_VOL_HIGH, TranslateScale volumeHigh, MIN_VOL,MAX_VOL, 0,127
    @End
    
    
    @OnKnobChange
      val = GetKnobValue LastKnob
      if LastKnob = KNOB_VOL_LOW
        volumeLow = Round TranslateScale val,0,127, MIN_VOL,MAX_VOL
        LabelKnob KNOB_VOL_LOW, {L },volumeLow,{ %}
    
      elseif LastKnob = KNOB_VOL_HIGH
        volumeHigh = Round TranslateScale val,0,127, MIN_VOL,MAX_VOL
        LabelKnob KNOB_VOL_HIGH, {H },volumeHigh,{ %}
      endif  
    @End 
    
    
    @OnPadDown
      if LastPad = PAD_LOW
        playLow = not playLow
        LatchPad PAD_LOW, playLow
    
      elseif LastPad = PAD_HIGH
        playHigh = not playHigh
        LatchPad PAD_HIGH, playHigh
      endif
    @End
    
    
    @OnMidiNoteOn
      SendMIDIThru
    
      if playLow and MIDINote >= 12
        vel = Clip (MIDIVelocity * volumeLow / 100), 1, 127
        SendMIDINoteOn MIDICHannel, MIDINote-12, vel
      endif
    
      if playHigh and MIDINote <= 115
        vel = Clip (MIDIVelocity * volumeHigh / 100), 1, 127
        SendMIDINoteOn MIDICHannel, MIDINote+12, vel
      endif
    
      SetNoteState MIDIChannel, MIDINote, playLow + 2*playHigh 
    @End
    
    
    @OnMidiNoteOff
      SendMIDIThru
    
      played = GetNoteState MIDIChannel, MIDINote
      if played & 1
        SendMIDINoteOn MIDICHannel, MIDINote-12, MIDIVelocity 
      endif
    
      if played & 2
        SendMIDINoteOn MIDICHannel, MIDINote+12, MIDIVelocity 
      endif  
    @End
    

    Remarks:

    • As there is now only one line of code needed per knob label of the two knobs, these are directly set in OnLoad and OnKnobChange - the RedrawOcataverKnob function is not needed
    • The computational OnMidiOn / OnMidiOff didn‘t change much versus the ‚knobs‘ version. They now use variables and it does not matter if these are set by knobs or pads (thats a benfit of the UI decoupling).
    • Volume modification just adds a code line per additional octaved note - the Clip function ensures that the product of factor*current volume stays in the range 1..127

    .

  • edited April 2020

    So one question. how do you know which pads are in the code. all i see is Pad_Low and Pad_High.
    but there are 2 high pads and two low pads. how do you assign pads and knobs in the code. for instance if i want to make another pad trigger a note 3 semitones up. how do i assign that to the right pad?

  • _ki_ki
    edited April 2020

    The PAD_LOW=1 and PAD_HIGH=3 constants are defined in OnLoad - all other pad commands then use these two constants. To show that these variables are constant values, the are written in all caps.

    Changing the single definition line to PAD_LOW=0 will change all later code that refer to this gui element, so the pad label printing and OnPadDown functionality to the first leftmost pad.

    For the current additional notes there are four things each:

    • a constant for the toggle pad id to use (PAD_LOW, PAD_HIGH)
    • a constant for the volume knob id to use (KNOB_VOL_LOW, KNOB_VOL_HIGH)
    • a boolean if its enabled (playLow, playHigh)
    • a float value defining its volume scaling (volumeLow, volumeHigh)

    To follow this lead, you need to add

    • a new PAD_THIRD constant
    • a new playThird variable initialized to NO
    • a volumeThird variable initialized to 100

    all defined in the OnLoad at the same places where the other respective vars were defined.

    Then look at the code for each occurence of either PAD_LOW, playLow or volumeLow you need to add code to support
    you new PAD_THIRD, playThird and volumeThird.

    You then will see that it will look better if the GUI is reanged:
    PAD_LOW = 0, PAD_HIGH=2 and PAD_THIRD =1 looks a lot better, and fits nicely with KNOB_VOL_THIRD = 1
    As we were using constants for the placement, such re-arrangement is super simple and doesn't need touching several code places

  • The most 'tricky' part is to store/recall this playThird variable as you need to introduce a new 'bit':

    SetNoteState MIDIChannel, MIDINote, playLow + 2*playHigh + 4*playThird
    

    All other needed code modifications are similar to the existing code, just add a new case all using the xxxThird variables.

  • _ki_ki
    edited April 2020

    BTW i think that three semitones will not sound as good as adding 7 semitones .

    When adding other values than octaves it might be better to apply a user-defined note scale to the computed note - which would need to add a scale knob and a root note knob to the GUI and code handling the GUI and computation code.

  • _ki_ki
    edited April 2020

    Ooops i just fixed a bug in nearly all the above samples:

    The if played & 2 part in the OnMidiNoteOff did send the note for the lower octave (-12) instead of the high octave - all examples are corrected now. Sorry for any inconvience this may have caused. This error class is called 'Copy Paste error' btw

  • Beautiful lesson @_ki. That's of professional best practices in your basic code examples with:

    • labeling and variable naming best practices
    • liberal comments and clear formatting to help provide focus and context for commands
  • OK... I have a new idea... smaller scripts that do useful tasks. Then run a lot of them in parallel or series or in networks.

    https://www.dropbox.com/s/vm1aryuyfsc9lrf/POs.aumproj?dl=0

    Download this AUM.project and after everything installs (AUM, Zeeon, FAC Alteza, Mozaic) open the AUM keyboard and press C4 a few times and wait a few more seconds... the E4 (same deal) and finally F4.

    Then I can document what the 3 Mozaic scripts are doing... I call them "PAD Objects ".

    I Programming an Object is a combination of some data and some behavior (i.e. Code).

    The 3 Objects only differ in the "data" sections @OnLoad. The code remains the same.

  • McDMcD
    edited April 2020

    OK. I had a request to change the Mozaic scripts embedded in this AUM project.

    USER REQUEST #1: I would like to assign each voice a midi channel.

    USER REQUEST #2: guessing rests in the sequence are achieved with a low register note (C0)?
    per note length and/or tie would also be something I’d like to add.

    1. is really trivial.

    2. requires some explanation of how to handle sequence playback (skip an implied beat or implement a more complex rhythmic scheme. Note length and termination which is implied in a tie. All related.

    I need to go and get the code... be right back.

  • edited April 2020

    .

  • Here's the code for what I call a "Drummer's Pad Object".

    @OnLoad

       // The NOTE the Drummer's Pad emits when hit. C4 = 60... easy to change.
    
       Base_Note = 60
    
       // A Round-Robin sequence as requested by the Drum Pad Magician @hypnopad 
       // The Numbers are the positions in a 8 note scale 1,2,3,4,5,6,7,8....
    
       Sequence = [1,2,3,5,7,8,6,5,4,5,2,3,5,4,3,2]
       Sequence_Length = 16
    
       // These are relative steps between the notes of the scale in 1/2 steps.
       // This scale is the Aeolian Minor scale like C, D, Eb, F, G, Ab, Bb, C for 2 octaves
       Scale = [1,3,4,6,8,9,11,13,15,16,18,20,21,23,25]  
    
       // Build on C4
       Octave = 4
    
       // Space each between Notes in the sequence segment for each drum hit
       delay = 200
    
    
       // code logic variables
       loop = 0
       ShowLayout 2
       Old_Note = Scale[1] + (Octave * 12) - 1
    

    @End

    @OnMidiInput

     // Check to see if the Drum Pad has issued a NOTE ON for Note = C4/60
    
      if MIDICommand = 144 and MIDINote = Base_Note
    
        MIDItype = MIDICommand
        pad_note= MIDINote % 12 + 1
    
        // Convert the Notes' Velocity to control the Number of Nots to send from the Sequence
        // In my 1st case the Velocities input ranged from 70 to 127 so I scale it to 1-6 Notes out
        Outer_Loop = round (MIDIVelocity / 10) - 6
    
        // This outer_loop controls how many notes sent per drum hit
        Log {Outer_Loop:}, Outer_Loop
        for i = 0 to Outer_Loop - 1
          if loop = Length
            loop = 0
          endif
    
          Sequence_Note = Sequence[loop]
          Note = Scale[Sequence_Note - 1] + (Octave * 12) - 1
          Inc loop
          // Notes are spaced out  in multiples of the "delay" variable (200 ms default)
          new_delay = i * delay
          Log {Loop: }, loop, { Note: }, Note, { Velocity: }, MIDIVelocity, { Delay: }, 
          SendMIDIOut MIDICommand, Note, MIDIVelocity, new_delay
          SendMIDIOut MIDICommand, Old_Note, 0, new_delay
          Old_Note = Note
      endfor
    
    
      // Any other MIDI data just flows through this Midi FX instance
      // so all Drum Pads can be on the same channel and activate their own Sequence instense
      elseif
        SendMIDIThru  
      endif
    
    @End€
    
  • OK Request 1: MODIFY THE MIDI CHANNEL for EACH INSTANCE.

    In AUM, You don't need to do this. You can configure each MIDI FX instance to it's own target AUv3 app.
    But we can change the code to allow this:

    Add a variable for the Midi_Channel in the @OnLoad section:
    Midi_Channel = 1

    And modify all the SendMIDINote commands to specific the channel requested:
    SendMIDIOut MIDICommand + (Midi_Channel - 1), Note, MIDIVelocity, new_delay
    SendMIDIOut MIDICommand + (Midi_Channel - 1), Old_Note, 0, new_delay

    Mozaic counts channels as 0 to 15 but we'll allow the user to think of 1-16 and just subject 1 on output.

  • that’s helpful. there’s an edge case in AUM when routing multiple MIDI FX to a single AUv3 app (multitimbral). the midi filter in this case would me more granular on the output of individual FX.

  • @McD Thought I’d respond here rather than my video thread.
    Interesting concept . I like what E4 is doing.
    Issues:
    Constant hung notes. I’ve seen other Mosaic programmers talking about preventing this.
    I’m not a fan of the black box concept. I would like to be able to adjust what’s going on inside the plug in (scales / root note/ etc)with pads and or knobs without having to go in and change code.
    Keep it up!

  • @crifytosp said:
    that’s helpful. there’s an edge case in AUM when routing multiple MIDI FX to a single AUv3 app (multitimbral). the midi filter in this case would me more granular on the output of individual FX.

    I can't unpack this statement yet...

    multiple MIDI FX? make me a list with some description

    What does MIDI Filter man to you? granular output? MIDI is predicatable so I don't get this either.

    I owe you a couple more answers too of "rests" and "ties". I need to create some script variations to post the answers.

  • edited April 2020

    AUM’s midi channel filtering is at input. thus every input source is subject to that configuration.

    sorry, should have made it clear I was talking about channels.

  • @crifytosp said:
    AUM’s midi channel filtering is at input. thus every input source is subject to that configuration.

    I tend to just leave AUM set to OMNI/all MIDI channels open and then select the MIDI FX apps I would like to be active for a given app. Every MIDI FX to App "wire" is vital between the 2 and not subject to any MIDI filtering that way. So every MIDI FX message can do out on channel 1 but only those configured to accept that app will get the notes being sent.

    Outside of AUM I could see the benefit of pre-coniguring MIDI FX to output on a given channel so you could use the MIDI standard to manage routing.

  • https://forum.audiob.us/discussion/34071/aum-midi-mute-best-hack/p2

    @wim was talking about stuck note prevention in this thread.
    Hope this helps.

  • heshes
    edited April 2020

    @hypnopad said:
    I’m not a fan of the black box concept. I would like to be able to adjust what’s going on inside the plug in (scales / root note/ etc)with pads and or knobs without having to go in and change code.

    I get where you're coming from. But this particular comment actually has it back-asswards. Being able to go directly to the code is the opposite of black box. Having to adjust pads and knobs is working with a black box. Whatever software you're using, there is always code behind those pads and knobs. If you can't go in and change the code directly, then you're working with a "black box", fiddling with the outside with no idea of what's inside. If you can go "inside the box" to view and change the code, then you have full transparency, full power over your tools.

    Of course, I do get that if you don't understand the code then it may as well be a black box. (And I get that your definition of "black box" may be a little diffferent.) But coding in Mozaic is pretty easily learned by anyone who's already familiar with the midi concepts. Just offering up a little different perspective. . .

  • trying to reverse engineer a Mozaic script is giving me insight into how fiendish code is. everything’s dependant on something else!

  • @hypnopad said:
    @McD Thought I’d respond here rather than my video thread.
    Interesting concept . I like what E4 is doing.

    One out of three is pretty good! Batting 333.

    The E4 sequence is the most musically interesting for sure. It does up and comes back down
    based on a C Harmonic Minor Scale.

    C4 just goes up 2 octaves of the diminished scale... yawn. But good for foggy moods.
    F4 only has 3 notes spaced by perfect 5ths. Good for a drone.

    Each is intended for a different use case... melodic, mood, drone.

    This is great feedback from someone that is a master of Drum Pad Performing.
    If you haven't seen Hynopad's Videos please check them out:

    https://www.youtube.com/channel/UC8Wh4RnkHf96cbpQthBwhAw/videos

    One out of three is pretty good!

    C4, E4 and F4 are all the same script with changes in the data:

    C4
    
     Base_Note = 60
     Sequence = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
     Scale = [1,2,4,5,7,8,10,11,13,14,16,17,19,20,22,23]
     Length = 16
     delay = 600
     Octave = 4
    
    E4
    
     Base_Note = 64
     Sequence = [1,2,3,5,7,8,6,5,4,5,2,3,5,4,3,2]
     Scale = [1,3,4,6,8,9,11,13,15,16,18,20,21,23,25]
     Length = 16
     delay = 600
     Octave = 4
    
    F4
    
     Base_Note = 65
     Sequence = [1,5,9]
     Scale = [1,2,4,5,7,8,10,11,13,14,16,17,19,20,22,23]
     Length = 3
     delay = 600
     Octave = 4
    

    So, you can change the behavior by:
    ACTIVATING NOTE: Base_Note
    MELODY: Sequence[] Array
    SCALE: Scale[] Array
    LENGTH OF MELODY: Length (I could also count the valid notes I suppose to save a step)
    SPACE BETWEEN NOTES: delay (I think I'll ad some randomization here or maybe a Timing[] Array
    Octave: Move the melody up/down octaves for bassline versus bells

    Issues:
    Constant hung notes. I’ve seen other Mosaic programmers talking about preventing this.

    Sure. I want to start with the fewest Cod lines possible to get more people to "fork" the code and add cool features and share them here. I can add a little function to delete all note outstanding and should because when it happens it's annoying. It usually happens when the targeted synth gets overloaded and misses a note off event.

    I’m not a fan of the black box concept.

    This is an attempt to help more people stop buying more sequencing/generator apps when they are so trivial to make yourself or get someone to code you one. But begging app developers to add special tweaks for your own worklflow also works well. Still... I have over $100 in apps that just output interesting MIDI patterns... most bought before Mozaic gave me a better way to save the money and get more control.

    I would like to be able to adjust what’s going on inside the plug in (scales / root note/ etc)with pads and or knobs without having to go in and change code.

    Adding 3 Knobs for these variables is also pretty trivial:

    Root = 0 (range +/- 12 to allow for transposing keys)
    Base_Note = 60 (range from 36-72 - C2 to C5)
    delay = 600 (range 10-1270)
    Octave = 4 (range 1-7)

    Setting custom Sequences and Scales can be input from PAD's too.

    Keep it up!

    So, requests for essential new features.

    1.Function to clean hung notes (use the Mozaic NoteIndex Array like @wim does)

    1. Add Knobs for:
      Root = 0 (range +/- 12 to allow for transposing keys)
      Base_Note = 60 (range from 36-72 - C2 to C5)
      delay = 600 (range 10-1270)
      Octave = 4 (range 1-7)

    2. Use PAD's to input custom Sequences and count the length.

    Does anyone want to "fork" the script and add one of more of these?
    Here's a starting Script to fork:

    @OnLoad
    
     Base_Note = 64 // E4
    
     Sequence = [1,2,3,5,7,8,6,5,4,5,2,3,5,4,3,2]
     Scale = [1,3,4,6,8,9,11,13,15,16,18,20,21,23,25]
     Length = 16
     Octave = 4
     loop = 0
     delay = 600
     ShowLayout 2
     Old_Note = Scale[1] + (Octave * 12) - 1
    
    @End
    
    
    @OnMidiInput
    
      if MIDICommand = 144 and MIDINote = Base_Note
    
        MIDItype = MIDICommand
        pad_note= MIDINote % 12 + 1
        Outer_Loop = round (MIDIVelocity / 10) - 6
        Log {Outer_Loop:}, Outer_Loop
        for i = 0 to Outer_Loop - 1
          if loop = Length
            loop = 0
          endif
    
          Sequence_Note = Sequence[loop]
          Note = Scale[Sequence_Note - 1] + (Octave * 12) - 1
          Inc loop
          new_delay = i * delay
          Log {Loop: }, loop, { Note: }, Note, { Velocity: }, MIDIVelocity, { Delay: }, 
          SendMIDIOut MIDICommand, Note, MIDIVelocity, new_delay
          SendMIDIOut MIDICommand, Old_Note, 0, new_delay
          Old_Note = Note
      endfor
    
      elseif
        SendMIDIThru  
      endif
    
    @End€
    
  • @hes said Of course, I do get that if you don't understand the code then it may as well be a black box. (And I get that your definition of "black box" may be a little diffferent.)

    You’re right. I used the wrong term but the blank outer interface of the device I was describing might as well be a black box to me. I kind of thought the knobs and pads were there to help people like me ( non coders) program certain parameters (if available)of the device to suit our needs so we didn’t have to go “under the hood “. I hope this doesn’t offend the “makers” .I think this outer UI is important to some of the non coding “users” out there. We rely on your expertise to make these incredible devices but feel like we also want to have some of that control and flexibility for ourselves without getting grease on our hands.

Sign In or Register to comment.