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 StoreLoopy Pro is your all-in-one musical toolkit. Try it for free today.
Comments
Thinking about something, is there any Mozaic script for Midi Fighter Twister?
I have different songs using different MFT knobs on it for automation , and it would be amazing to have one Mozaic app on one of channels mainly as label and save for those knobs per song. I guess this is a shoot in the dark, but maybe someone had same thoughts
https://patchstorage.com/controller-tracker-and-snapshots/
https://patchstorage.com/controller-feedback-and-restore/
These (particularly the second, older one) were written with the twister in mind, but are useful for many situations.
They provide feedback for the knob led rings, and restoration of their state on session reload.
Thank you, gonna check them out
@espiegel123
Nothing
trackpad 0
Nothing
Pattern 1 ( pad 4 )
0,1,2,3
0
Track2 ( pad 1 )
Pattern 2 ( pad 5 )
1
Pattern 2
0,1,2,3
1
1
Track 2 ( pad 1 )
0,1,2,3
@pejman : I think that my instructions might have been unclear. Also, I have made some minor changes to the script. Please use this version of the script for the exercise.
The changes I made:
Please go through this revised script line by line when you answer the questions. I suggest printing it out or having it open on another screen.
========== QUESTIONS
Read your script and answer these questions before trying to run the code.
NOTE: we are using different values in trackPattern than in your version of the script. Make sure to use the updated trackpattern values
Where a pad number is asked, use the Mozaic pad number. I.e. the first pad is pad 0. Where a track number or pattern number is asked for use a 0-based numbering. The first pattern is pattern 0. The first track is track 0. This is to keep things consistent with the numbers we use in the variables.
After the script has loaded (after @onLoad has run, before any user interaction):
Imagine that you touch pad 2 (the third pad)
When @trackSelected is first called before any of its code has run:
When @trackSelected has finished running:
========== AFTER YOU HAVE ANSWERED THESE QUESTIONS
Please post the answers to the questions above then perform the following exercise and add another post with the information you found by logging the results.
Add log lines to the script:
Log the following information in each of those places:
For example: at the beginning of @trackSelected add something like
log {At start of trackSelected}
log {lastPad: }, lastPad, { selectedtrack: }, selectedtrack
log {trackpattern[lastPad]: }, trackpattern[lastPad]
log {trackpattern[selectedtrack]: }, trackpattern[selectedtrack]
log {----}
@espiegel123
0
0
4
4
4,5,6,7
0
2
4
2
6
4,5,6,7
0
2
2
Pad 8 ( pattern 4)
4,5,6,7
@espiegel123
I am correcting this answer :
You wrote :
Pad 10 ( pattern 6)
@espiegel123
ANSWERS AFTER LOGGING
0
2
4
2
6
4,5,6,7
2
2
2
Pad 10 ( pattern 6 )
4,5,6,7
PRINTED OF LOGS AT BEGINNING AND END OF @trackselected :
trackpattern[selectedtrack]: 6
trackpattern[lastPad]: 6
lastPad: 2 selectedtrack: 2
At end of trackSelected
trackpattern[selectedtrack]: 4
trackpattern[lastPad]: 6
lastPad: 2 selectedtrack: 0
At start of trackSelected
@pejman : I’ll contact you via DM to go over a few of these answers and see if we can figure out the source of some confusion .
@espiegel
Ok
@espiegel123
@pejman : Great job!
A couple of little refinements that I'd like to suggest.
Once you have done that, you can work on @pattern. You will want to use the things that you learning while working on @track. It will involve updating the trackpattern array.
If you have any questions about any of this, please let me know.
@pejman : just pointed out to me that there is some refinement to be done in @track in the colorPad assignments towards the end that I missed. the code works correctly but has a redundant line.
@espiegel123
@espiegel123
@OnLoad
ShowLayout 2
for p = 4 to 15
LabelPad p, {pattern: },p-3
endfor
LabelPad 0, {1️⃣}
LabelPad 1, {2️⃣}
LabelPad 2, {3️⃣}
LabelPad 3, {4️⃣}
//NOTE THIS CHANGE BY ESPIEGEL123
//trackPattern associates each track with a pattern
//so that trackPattern[trackNumber] returns the pattern associated with the track
//for example, trackPattern[0] is the pattern to be associated with track 0
trackpattern = [0,0,0,0] //changed by espiegel123 for exercise
selectedtrack = 0
selectedpattern = 4
//color default track
ColorPad selectedtrack, 2
//color the track's pattern
ColorPad trackPattern[0] + 4, 7 //changed by ESPIEGEL123 to use trackPattern
@End
@OnPadDown
if lastPad < 4
call @track
else
call @pattern
endif
@End
@track
// When a track (pad 0-3) is tapped:
// make all other track pads white [by making previous pad white]
ColorPad selectedtrack, 0
// make the tapped pad yellow
ColorPad LastPad,2
//Update the pattern pads so the track’s associated pattern is pink (and all others are white)
// NEEDED:
// add code to color previous pattern white (or color all patterns white)
ColorPad trackpattern[selectedtrack] + 4 , 0
// remember that this track is the current one
selectedtrack = LastPad
// color the track's associated pattern pink
ColorPad trackpattern[LastPad] + 4 , 7
@end
@pattern
// When a pattern (pad 4-15) is tapped:
// make all other pattern pads white [by making previous pad white]
ColorPad selectedpattern, 0
// make the tapped pad pink
ColorPad LastPad, 7
// remember that this pattern is the current one
selectedpattern = LastPad
// compare for avoid colorless if touch Last pattern pad that is currently colored
if trackpattern[selectedtrack] + 4 <> selectedpattern
//make the old selected pattern associated with track white
ColorPad trackpattern[selectedtrack] + 4 , 0
endif
//Remember that this is the current pattern associated with the last track
trackpattern[selectedtrack] = selectedpattern - 4
@end
Mozaic n00b here. Here’s what I want to do:
Take 4 specific midi note numbers and route them to four different specific note numbers at the output. Bonus would be a matrix, so I could route two note ins to one note out, or one note in to all notes out, etc.
This is to take 4 triggers from electronic drums and use them as different kinds of triggers in a modular system.
To do that you basically use @MidiNote to check if the incoming note is one to remap or not. If it is, send out a remapped note; otherwise send out the same note that came in.
There might be a little housekeeping if mapping several different input notes to the same output note to make sure note ons and offs get paired right.
A quick and dirty version where you type in the remappings in the script would be a pretty straightforward script. Adding a user interface to set up the mappings via the user interface would be pretty straightforward but more time-consuming.
mfxConvert can do this without need for programming. It can't do one note in to multiple notes out, but it can do multiple notes in to one note out.
It's quick and convenient to set up and to save and recall presets.
Hi guys.
This detailed description is written according to the order of Espiegel.
This patch has 3 knobs, 4 tracks ( pad’s 0 to 3 with blue colored when select each of them ) , each track has 12 patterns ( pads 4 to 15 with pink color when select each of them ) , That's a total of 48 patterns.
Knob 0 = all track sync/ unsync function
Knob 1 = patterns handling
Knob 2 = volume for example
Its values (which means the set knob position here) can be stored separately in the 48 patterns created by the tracks and then called by the patterns and tracks.
Knob 0 if < value 64 = tracks are unsync.
if > value 64 tracks are sync together.
That’s mean if state = unsync when touch each tracks pads, we can select different patterns for them.
For example,
touch track 1, touch pattern 7
touch track 2, touch pattern 8
touch track 3, touch pattern 9
touch track 4, touch pattern 10
When reselect each of tracks, The patterns we have previously selected for are called and turn pink automatically .
if state = sync, when touch one pattern for example pattern 5 ( No matter which track has already been selected ), that pattern is selected for all tracks automatically. That’s mean when touch each tracks, pattern 5 is pink
NOTE : when we are in unsync mode and select different patterns for different patterns, and we change mode to cync all tracks mode , we must touch one of the patterns that we want to choose for all tracks to be selected for all tracks ( Pattern Updating ) even if the pattern is the last pattern selected for the last track.
Purpose of creating a knob pattern :
In my main script i have differnt layouts : 0 ,1,2
In layout 2 I access to tracks and all pattern pads , but in layout 0 , i have only 4 tracks and all of the used knobs , which should be their values stored in the patterns.
So I need to select the required patterns in layout 0 with a KNOB without having to change layouts each time.
With turning pattern knob we can select pattern of each tracks , as we do this with our finger by touching each Pattern Pads. So we have to select the track first and then turn the pattern knob to select the pattern.
In addition, by turning pattern knob to a specific value, the corresponding pattern turns pink, which means the selected pattern.
Explanation for knob 2 : volume
It is one of the 24 Knobs that I use in my main script, which is given here as an example.
As I wrote before, we have 48 patterns using 4 tracks, so volume knob values can be stored in patterns in 48 different positions .
For example in sync all tracks mode.
1, Touch pattern 5
2, touch track 1
3, turn volume knob to value 10
4, touch track 2
5, turn volume knob to value 20
6, touch track 3
7, turn volume knob to value 30
8, touch track 4
9, turn volume knob to value 40
10, touch track 1
Volume Knob set to value 10 auto.
11, touch track 2
Volume Knob set to value 20 auto.
and so on….
( Remarkable my good teacher Espiegel , Maybe I couldn't explain it to them clearly .)
🔺🔺Problem : Ever since I added All Track sync option to the script, I have had to use ( if sync , if unsync ) , in all line’s of codes for Knob Volume, which means that it should be in my main script, for all knobs and their sub-layers and Labels and CCs to be issued and any functionality I am going to add or add to them, IFS to use.
Is there a way I don't need IFs for KNOBs?⁉️
Please note, Some variables may not have good names regarding their performance.
Some lines may not be written in the right place.
Because this script is a small piece of my original script that is going to be modified. Including vari names , Put the code in the right place and etc…
@OnLoad
patternsPerTrack = 12
knobsPerPattern = 4
numtracks = 4
//🔺🔺Array for store knobs position associated with patterns associated with tracks
for i = 0 to patternsPerTrack*numtracks - 1
allTrackPadKnobs[i * knobsPerPattern] = [64,0,0,0]
endfor
for i = 0 to 3
SetKnobValue i, allTrackPadKnobs[i]
endfor
ShowLayout 2
for p = 4 to 15
LabelPad p, {pattern: },p-3
endfor
LabelPad 0, {1️⃣}
LabelPad 1, {2️⃣}
LabelPad 2, {3️⃣}
LabelPad 3, {4️⃣}
LabelKnob 0, {All TR},{ }, {ON}
LabelKnob 1, {PAT },1
LabelKnob 2, {vol },0
lall = 2
trackpattern = [0,0,0,0]
selectedtrack = 0
ColorPad selectedtrack, 5
ColorPad trackPattern[selectedtrack] + 4, 7
//🔺🔺Variable for set pattern knob position in sync mode
setpatternknob = 0
//🔺🔺Array for set position pattern knob with touching pattern pads
setpatknobposvalue = [0,6,18,30,45,60,75,85,95,105,115,127]
@End
@OnPadDown
if lastPad < 4
call @track
else
call @pattern
endif
Call @setknobposition
Call @setknoblabel
@End
@track
//🔺🔺condition for the operation of tracks in relation to patterns in all tracks sync mode
if lall = 2
ColorPad selectedtrack, 0
selectedtrack = LastPad
ColorPad selectedtrack,5
FlashPad trackpattern + 4
//🔺🔺if all tracks unsync mode
else
ColorPad selectedtrack, 0
ColorPad trackpattern[selectedtrack] + 4 , 0
selectedtrack = LastPad
ColorPad selectedtrack,5
//🔺🔺for pattern coloring associated with track When the track is touched
ColorPad trackpattern[selectedtrack] + 4 , 7
endif
@end
@pattern
if lall = 2
ColorPad trackpattern + 4, 0
ColorPad LastPad , 7
trackpattern = LastPad - 4
setpatternknob = setpatknobposvalue[trackpattern]
else
//🔺🔺with touching each pattern pad, pattern knob set to the specific position associated with pattern numbers
//🔺🔺for store knobs values to especific array cells associated with knob number associated with patterns num associted with tracks num ; 1 = knob number
allTrackPadKnobs[1 + selectedtrack* 48 + 4 * selectedtrack] = setpatknobposvalue[trackpattern[selectedtrack]]
endif
@end
@OnKnobChange
//🔺🔺knob all track sync/unsync mode
if LastKnob = 0
all = GetKnobValue 0
//🔺🔺lall vari for creating 2 state for sync/unsync modes
lall = Round TranslateScale all, 0,127,1,2
LabelKnob 0, {All TR},{ }, {OFF}
elseif lall = 2
LabelKnob 0, {All TR},{ }, {ON}
endif
endif
//🔺🔺pattern knob for handling pattern pads as shortcut in different layout. translated to 12 as 12 patterns
pat = Round GetKnobValue 1
lpat = Round TranslateScale pat, 0,127,1,12
if LastKnob = 1
if lall = 2
setpatternknob = Round pat
ColorPad trackpattern+4, 0
ColorPad lpat+3, 7
trackpattern = lpat -1
FlashPad lpat+3
else
allTrackPadKnobs[1 + selectedtrack* 48 + 4 * selectedtrack] = Round pat
endif
ColorPad trackpattern[selectedtrack]+4, 0
ColorPad lpat+3, 7
trackpattern[selectedtrack] = lpat -1
FlashPad lpat+3
endif
if LastKnob = 2
if lall = 2
allTrackPadKnobs[2 + selectedtrack* 48 + 4 * trackpattern] = Round GetKnobValue 2
else
allTrackPadKnobs[2 + selectedtrack* 48 + 4 * trackpattern[selectedtrack]] = Round GetKnobValue 2
endif
endif
Call @setknobposition
Call @setknoblabel
@End
@setknobposition
if lall = 2
SetKnobValue 1,setpatternknob
elseif lall = 1
SetKnobValue 1,allTrackPadKnobs[1 + selectedtrack* 48 + 4*selectedtrack]
endif
if lall = 2
SetKnobValue 2, allTrackPadKnobs[2 + selectedtrack* 48 + 4 * trackpattern]
else
SetKnobValue 2, allTrackPadKnobs[2 + selectedtrack* 48 + 4 * trackpattern[selectedtrack]]
endif
@End
@setknoblabel
if lall = 2
LabelKnob 2, {vol, }, allTrackPadKnobs[2 + selectedtrack* 48 + 4 * trackpattern]
else
LabelKnob 2, {vol, }, allTrackPadKnobs[2 + selectedtrack* 48 + 4 * trackpattern[selectedtrack]]
endif
if lall = 2
lpat = Round TranslateScale setpatternknob , 0,127,1,12
else
lpat = Round TranslateScale allTrackPadKnobs[1 + selectedtrack* 48 + 4 * selectedtrack],0,127,1,12
endif
LabelKnob 1, {PAT},{ }, lpat
@End
Any ideas / experience if the "PresetScale" and "CustomScale" commands have a noticable impact on CPU / DSP and latency when used repeatedly ?
I am asking, because I am working on a sequencer project with two lanes that can have different scales. And I wonder why the scale settings in Mozaic have been designed that way, and the scale and root selection have not just been added as parameters to ScaleQuantize and related commands.
@catherder I just checked the performance of SetRootNote and PresetScale with a script changing both 64 times per QuarterNote (ie at 1/256 note rate) and didn‘t notice any additional cpu percentage when running that script.
When starting AUMs timeline, there is no additonal cpu load on my iPad Pro 10.7 - Mozaic runs with 0.6% dsp according to AUMs node statistics.
You can verified that SetRootNote and PresetScale really were called by uncommenting the Log messages, which on my iPad raised the dsp to 1.5%
I think calling it for two times during note output of your sequencer (probably with 1/16 or 1/32 timing) won‘t matter at all.
Thanks a lot @_ki for taking the time to test this. This is good news so I can go ahead.
I’m looking for a script that would setup each note of an octave on a pad of its own, then have a knob to select the required octave of the note. Then when the pad is pressed the note is latched on (sendmidinoteon) with the note velocity set to 0 until pad is pressed again. Need to be able to have all pads on at same time or any combination of them as selected.
Also needs to kill all latched notes when octave is changed as well as a midi panic to turn stuck notes off.
This is to be able to use the new sympathetic resonance feature of pure piano with a 25/32 note midi controller so that keys at Lower or higher octave range than available can be selected while playing piano parts on the controller in another octave.
Hope somebody has some efficient code to do this or likes a challenge or can point me in direction of using midinote to send the note value 0 - 127 rather than note name C1, C2 etc.
Note On velocity at zero is equivalent to Note Off in midi terms.
You can't send a Note On at velocity zero as Mozaic automatically converts it to Note Off.
[edit]
SendMIDIOut 0x90, 36, 0
does work to send a raw Note On velocity zero.But still, are you sure this is correct behavior? It isn't correct per the MIDI spec. It would be the equivalent of sending a note off followed by another note off on the second press.
That is true, however from the vides on YouTube for this feature of pure piano what actual happens is that the damper is lifted from the selected piano strings to allow it to resonate when other notes are played. I tested with ChordBud setting a pattern of chords with 0 velocity playing then playing other keys to hear the resonance effect. I could use this but it is a lot of pattern programming and would rather be able to do this as I perform.
But setting a velocity of 1 hopefully would have same effect
I edited my post above. It is possible to work around the conversion of Note Off velocity zero. What should happen when the pad is pressed again though? A "valid" note off?
Also, you're likely to get some weird-ass behavior if the pad happens to be set to the same octave as you're actually playing in.
Correct, but common sense would be that the player would do it on purpose, it’s almost like it would be replacing playing the right or left hand if you are only selecting lower or higher octave notes to send.
What about my other question? What happens on the second pad press? A valid Note Off?
Also, how would be best to select the pad to edit the octave on? One knob to select the pad and another to select the octave? Or touch a pad while holding down SHIFT? Or maybe long-press on a pad?
Would there be a use for a knob to set the same octave on all notes at once?