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
I attempted to read the manual several times. It’s fun and challenging for me. I was looking for a specific example to edit the channels to make it on one channel.
Basically what I need is the cc-banks script https://patchstorage.com/cc-banks/
With the pads toggle from cc-switch.
How would I delete the pad section from cc-banks and add the pads from cc-switch?
I'd like to be able to import libraries ala Python/JS. Like
import utils/knobs as knobs
where knobs has a bunch of user defined functions that can be called in the parent script like@knobs/someMethod
. In order keep things simple with regards to sharing, there would need to be a 'flattening' feature/option added when exporting.That along with function arguments/function variable scope would be extremely helpful.
I love that some of those angled sides ended up in the GUI
It is hard to advise without understanding what you understand. When you read through the code that you posted line by line, do you understand what each line does?
The place to start might be helping you to understand anything that you don't understand in the script you quoted.
It will also help you program, if you can precisely state what you are trying to accomplish--but you can start vague and then make it more precise. I find it useful to start by writing down in easy imprecise terms what I want and then converting that into a more specific outline. I then look at the outline and make more precise anything that could be more precise. Depending how complicated the program is this might take one or two passes. But on a more complicated program, I may have to do that several times.
thanks for you will to explain.
I didnt understand most of the lines of code besides the ones that made sense with the explanations:
if it had simple explanation on the rest of the it would be probably easy to modify
I tried to precisely state what I'm trying to accomplish:
1.Have the option for a one channel with a knob selection.
2.assignable knobs for cc number per pad. like on the script "cc-bank"
I think step one for you will be to go through this program line-by-line and understanding each one. It might be useful for you to translate the code into human language. I think once you do that, you will be much closer to being able to go in the other direction: taking an idea and turning into code.
For instance,
"If MIDICommand = 0xB0 And MIDIByte2 = TrigCC"
means something like:
"if the MIDI command is a midi CC (midiCommand = 0xB0) and the CC number (MIDIByte2) is TrigCC (the CC number that I use as a trigger)"
Anyway, take some time to understand each line (referring to the Mozaic manual as needed) and come back here and ask for explanations of the individual lines you don't understand.
And, if you understand the lines but not WHY they are there, ask about that with the specific lines.
I spent a few hours yesterday trying to get a concept to work with limited success.
Most of what I want to do with Mosaic "at this moment in time" involves understanding how to store played notes into a memory buffer, and then play those notes back in various automated ways, when a specific event triggers playback.
For example. A program where I play notes, and once I reach note number 4, all four notes will be played back in a "strummed" sequence. "Strummed" meaning, notes 1, 2, 3, and 4 all play sequentially, with some milliSecond time interval between the notes.
I just can't figure out how to get more than one note into Variables, or an Array, and then get them back out again.
Here’s a short demo script of one way to go about it. Please don’t hesitate to ask about any parts that you don’t understand.
Thanks wim!
Very nice of you to do this.
I'll load it up and experiment with it tomorrow.
I learned two new commands... "Inc" and "Quarternote".
One question that confuses me is the purpose of "@End" in a script.
Based on your above script I'd guess it's for separating scripts into "Event"/"@End" segments (maybe call them something like "Event Groups" (for lack of knowing the proper term).
So once the script finishes the first "Event Group" the "whatever you'd call the code reading pointer that constantly loops through the code", only loops within one "event group" at a time. Once any "event group" has completed, that pointer travels past the @End, and then works only within the next "Event Group" (between the triggering event and the @End that follows it.
Something like this...
@OnLoad
// Do stuff
// When done
@End
// Once past this @End marker the code reading pointer stops and waits on the next event to happen
// This would be a new event:
@OnMidiNoteOn
// When the midi note occurs it starts the code reading pointer moving again
// The pointer processes all the next code and once there is no more to do
// It moves past the next @end and waits on the next Event to occur before the pointer will start moving again.
Is that how it works?
Thanks for explaining me. You on to something! We need a translator that translates the code to human language .
Until then I will go through and try to understand with manual. One day hopefully I’ll be fluent. In the meanwhile I just want to jam and to have extra tools available to other musicians
Yes, the @End is to signal the end of an event. Everything in between is what happens when that event is triggered. They’re just called Events, not Event Groups. Events are triggered by something happening during the execution of the script. In the above script there is the
@OnLoad
event that is triggered when the program first loads. Then there is the@OnMidiNote
event that is triggered whenever a MIDI note is received. When an event is triggered, everything between the event name and the@End
executes.Humm, it sounds like you might be seeing that wrong. It’s not like like Basic where a script executes from top to bottom. Mozaic is “event” driven. The whole script is parsed, and then Mozaic waits for things to happen. Every time they do, Mozaic executes the code in the appropriate event. In that script, every time a MIDI note is received, the
@OnMidiNote
code executes. If no notes are received that part of the code never does anything.The part about only one event executing at a time isn’t really right either. There can be more than one thing going on at a time. You can be turning knobs while midi notes are being processed, for instance. Lots of things can be happening at once.
Under the hood, at a low level, technically only one thing is happening at a time, but at the level we are working at, it is just as though many things can be going on simultaneously.
Well, now I’m not sure how you’re seeing it from your description. Maybe you do understand and the explanation is just different than how I’d say it. The best way I can describe it is, whenever the thing happens that the event is related to, the code in that event executes.
@wim and @horsetrainer
In Mozaic there is always just one thing happing. If several events seem too occur at the same time (like knob turn while midi arrives), then the events are still executed in a well defined specific sequence - there never will be an @OnTimer while the script code for @OnMidiNoteOn is processed.
The sequence in which the Mozaic events will be fired is fixed, always from ‚general‘ to more specific events. A complex example for are several midi notes and CCs arriving just when the hostbar changed on metropulse 0. The order of midi input is: NoteOn 10, CC 20, NoteOff 30, PitchBend 40, NoteOn 50.
The order of events fired by the Mozaic runtime environment (if they are defined in the script) will result to:
So, first the host informations, then MetroPulses, and then the events for all incoming midi data. For these, several events are called depending of the midi command. MidiInput is called first, then if its a Note message MidiNote and after that the more specific MiniNoteOn or MidiNoteOff. The order is always from general to ‚specific‘.
AFter beeing fired, each event function runs until its
@End
is reached. The Mozaic runtime environment manages a list of events to be fired next.If the user also turned a knob just at that time, i suspect the OnKnob event are fired afterwards.
.
.
In other programming languages something like these Mozaic events are called functions. But you don‘t have a main function that calls all your defined functions.
Like @wim described, its the Mozaic Runtime that calls specific functions (or events) and executed them until End is reached in that function.
Mozaic allows to define own functions ( user events) , which can be called during the predefined Moazic events. The End in such user-event returns to the calling event.
If any of the Mozaic event functions you defined in your script takes too long (perhaps due to nested loops with computations) you will get a CPU spike and perhaps crackles at small audio buffers.
Great explanation at a technical level @_;ki, but perhaps more in-depth than your average / beginner coder needs to be concerned with in some ways. For all intents and purposes, turning a knob, executing a timer, processing a midi note happen as close enough to one another as to be considered simultaneous. For instance one can have a timer flashing a pad, midi notes coming in, midi notes going out, and be adjusting knobs effectively all at the same time.
Sure, for a complex and very busy script one needs to get into multitasking and load considerations. And definitely, midi event precedence is important to understand. But beyond that, I’ve only pushed the boundaries of “multitasking” to the point of overload once.
I hesitate long and hard before contradicting anything you say because your programming ability and technical knowledge is light-years beyond mine. But I do think that a beginner is better off focusing on the basic conceptual level and doesn’t need to think of Mozaic linearly, except concerning precedence of overlapping events such as
OnMidiInput
,OnMidiNote
,OnMidiNoteOn
, etc.As long as my pad flashes every quarter note, I don’t need to worry that it has a lower priority than passing a midi note through, etc. I can just code my events and most times it’ll work. At least until I get about 1000 times better and start writing scripts as intense as yours.
For instance, while this is technically true...
... one can have a timer running and schedule simple things to happen without having to worry about where it fits in with the midi note being processed. Mozaic sorts those things out, and until things get too busy, effectively it’s all happening all at the same time.
At a conceptual level, for most practical beginner purposes, Mozaic is a multi-tasking, event driven environment. That’s the point I was trying to get across to @horsetrainer. Everything you said is completely correct (and as always, super useful to me), but we’re trying to keep @horsetrainer’s head from exploding here.
This would be great wiki fodder.
Don‘t worry, i don‘t mind beeing critizied
From my experience teaching informatics as scientific assistant at the university many are lacking the understanding what is going on in the lower levels. The have build mental models of what they think how it works, but this can lead to problems if their model differs from how things really work.
That why i always try to ‚open up a view through the surface‘ so that they have a change in understanding how and why things happen. I think its easier to know that Mozaic will call your code if things happen one input thing after the other - so you never will worry about what might happen if another note arrives. Nothing in a script will get overwritten or interrupted by other events. IMHO it helps understanding the system if you know how things fit together conceptually.
Beginners in programming/scripting just see the text and have no idea why this even works. The first thing is to understand that these statements are a step-wise recipe to get things done. But then they don’t understand when and how this is going to be initiated. My admittedly too long and possibly too 'deep' explanation was only meant to fill this last gap
.
So to summarize my previous long message:
TL;DR:
Mozaic is the main program that calls up the defined events one after the other, when there is something to do. Each line of an event is then executed from top to bottom until its End keyword. Conditional statements allow to execute if a condition is met and looped statements Execute the contained statements multiple times.
With just a little time spent with that example code and the manual, you will understand most of what there is to know. It won't take you that long as long as you go one line at a time -- and look up what about that line you don't understand.
The code to language translator is your brain. The hardest part to learn about programming is converting vague ideas into the little steps needed to accomplish them. Fortunately, Bram designed Mozaic to have none of the bells-and-whistles that advanced coders love but which are confusing to a lot of people. I honestly think that with an hour or so devoted to reading the manual enough to understand that script that you will be well on your way to being able to create your own utilities and to understand most other scripts that aren't really big.
@espiegel123 Thats what i also though when writing it down - i intend to put it on the Mozaic tips page when i wrote/edited the message. And thats also why it got overboard and i added more and more details - the script was intended as a starting point for the curious, who want to explore the described by themselves.
@horsetrainer Hope your head didn‘t explode !
Your post definitely helped me @_ki, particularly now that I've neck deep in a script that does push all the boundaries. That knowledge that deep down only one thing is happening at any one time is important when expecting a lot of "simultaneous" things to be happening.
Mozaic seems to have a great way of prioritizing tasks. For instance, I had a pad label updating as MIDI events were being processed. When the incoming MIDI load was too high, the pad label updates were simply skipped until there was enough time to resume them. I appreciated that MIDI events were processed at a higher priority rather than being skipped. (But of course, gave up the idea of updating the pad label.)
I got heavily tripped up until I understood the relationship of the MIDI Events. So that's all super good information.
If @horsetrainer's head did explode, at least it's like my Dad said once when I split my head open one time. "Oh well, at least it was only your head."
@wim BTW i have several scripts that run into audio crackles due to heavy computation in the events. Thats why several of my scripts do the heavy stuff as pre-computation.
For the current script (Chord Inverser) i needed to split the computation in 6 parts that get executed one by one in separate OnTimer tricks - otherwise pressing a pad that switched some chord detection settings resulted in 100% CPU.
My main WIP script also uses a scheduler and manages several linked lists of events that need to be fired later at specific timer ticks. For instance for smooth interpolation of CCs that will start 1/4 before the next bar. These need ideally be issued 10-20 times per sec to get smooth ramps.
And at some point i realized that my initial distribution algorithm produced spikes if many of my internal events were scheduled to the same timer tick and i needed to change strategy to distribute the updates of each of the CCs.
I am working on that one for several month now and it‘s still only 75% finished. At least the GUI code with its 5 different pages is complete and i have a working mockup
I'm working on a script that triggers some hefty array retrievals and MIDI triggering on a 1ms timer. I truly didn't think Mozaic could handle that, but have been surprised at how much I can get away with.
I'm so skeptical that I keep going back to do more and more testing. So far I haven't found performance show stoppers, only bugs in my scripting. The saying "if it seems too good to be true then it isn't true" keeps coming to mind though.
(BTW, this script would be impossible to manage without your Textastic extension. Thanks so much for that!)
a script to shuffle presets with midi program change commands plus favorite bank...
https://patchstorage.com/agogo-shuffle-version-1-0/
This is so thoughtful and much needed @nuno_agogo !! 👏👍👍👍 thank you.
I wrote you on patch storage:
Can you please add support for drum jam program change?
It’s kind of complicated.
It’s got 4 categories for changing programs:
Bank select MSB (CC0) = 00 - program change messages load pad
instruments (indexed from the alphabetically ordered list)
Bank select MSB (CC0) = 01
with LSB (CC32) picks the FACTORY preset group, with
program change events selecting the preset within that group.
Bank select MSB (CC0) = 02
with LSB (CC32) picks the USER preset group, with
program change events selecting the preset within that group.
I got a Midiflow “Patch” of the different program change controls if that helps.
Hi @nuno_agogo I realy like your script. Very usefull and direct. Thanks.
I did encounter a problem getting the script into Mozaic. The downloaded file did not include .mozaic in the filename. Had to add that to the filename to get it into Mozaic.
Also found a bug: When stored as a favorite the combination 0-0-0 will not be sent.
Looking at your code I spotted something ilegal being done to the arrays. Mozaic probably substitutes [ ] with a 0. Arrays in Mozaic can only contain numbers. It is suggested to use -1 as empty or uninitialized.
Hey Alfred! Thanks man! That's odd. The uploaded file has the proper file extension. I also did download it myself but all was fine here. What browser are you using?
Will update another version soon and get rid of those bugs as well.
Big up!
will look into it. stay tuned
@nuno_agogo you are right the missing filetype was caused by iCab. An update must have caused that because it used to work fine.
Also the download counter on patchStorage is kind of buggy...
I understood the theories but I'm still extremely fuzzy on how to write code that does what I want.
I think it might be helpful for myself and others, to have comprehensive overviews for using one or two events or functions at a time. Even if the output of the examples are just a Log outputs.
I envision code as being blocks of tasks. And I guess from what's been said here, what I'm calling a block, is the stuff that goes on between some @ Triggering Event, and the @ End.
I played with the script that Wim wrote, that plays a strum after playing four individual notes. I tried very hard to figure out a way to edit a delay into win's code so after the 4th note was pressed, there would be a delay, and then the strum would start. I tried adding in a timer function, but I just couldn't get it to work.
My heads really is stuck in thinking like the BASIC I learned back in the 1980's.
I like the idea of line numbers, and having goto commands to steer the direction of the code to different areas of a program.
Here's a simple question.... Can I put a delay event into mosaic that essentially pauses the script for a desired length of time? In the old basic days I'd use a for/next loop to add a delay. Does Mosaic have a function that you can use to tell the script to stop and wait for some number number of milliseconds, and then continue on?
I kind of wish Mosaic had a function called "Delay" and you could use it to add pauses whenever you needed one.
No, there is no delay function in the way you imagine it.
Since Mozaic is a realtime midi scripting environment, all the event blocks need to finish their stuff as fast as possible. So inserting a ‚wait‘ somewhere inside such event blocks is no feasible.
Most midi send functions have an additional delay parameter, you could use this parameter to issue the notes ‚50msec in the future‘. The SendMidiNoteOn ch,note,vel, delay will return immediately to your event block, the event is just marked for future sending.
.
The timer event is something that gets called regularly until stopped again. For really making use of it, you need to have understood how things work in Mozaic. Its something that seems to run in parallel to what you else do in the script - so one needs to communicate through variables with the timer event block, to implement own triggers. It is possible to write script code that will issue notes stored in an array at a defined timer tick in the fuure - but you have to code all that yourself.
A second ‚kind of parallel running‘ event is the OnMetroPulse, which is triggered in sync to the host tempo in a user specified divisions (Pulses per Quarter Note). This event only triggers if the host is running, but its more convenient to use since with CurrentMetroPulse you already get the current position in a bar (and don‘t have to code this yourself like with OnTimer)
Are all the Mozaic plugins that people have written on Patch Storage? And is there a list of 'must have' scripts. I'm sure it's all in this thread, but unfortunately this thread is 60 pages long...
@cian You find a categorized list of all Mozaic scripts of all scripts in the wiki. There are some scripts only published in forums threada, but i‘ll try to copy them to own wiki pages and link them.