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
@Skyblazer I've kinda managed a very basic version, will have to think hard on the next bit, might need to use custom scales or something, not sure but I'll need to look at more of other people's scripts to get how restricting the harp to chords rather than just scales - it works quite nicely at the moment though as I've made the y value control the velocity, so you can emphasise parts...
Need also to restrict the range or have a slider control that...
Also thinking about a less precise and more expressive way of forming harmonies might be a row of sliders - most scales are less than eight notes so you could dynamically 'drawbar' scale notes out, adjust as though you were damping them in the way harpists do...
@Krupa I like your idea of using the Y axis to control velocity. I think I'll use that for my interpretation as well, if you don't mind. I just finished coding a very basic version, with three strings playing one C chord.
I'm not really familiar with the harp, so I'm not able to visualize what you're describing with the second paragraph. I'd be interested to see yours. I'm going to have users use the knobs to manually enter the note for each string, for four "chords". Maybe you're talking about doing something similar?
@wim: here is a little script to help visualize translate curve and the influence of the bias/curve param
Yours sounds interesting, probably more practical than mine, which I might put on PatchStorage so that others can try it (I'll have to check the preset licences first though). Mine's probably a little more difficult to play but might just work, if I can figure out a sensible method of quieting only the notes that you don't want to sound as you strum...
@Skyblazer I just switched note playing from @onmetropulse to @onxychange and I'm getting stutter notes, I can appreciate why, do you or anyone else have a way round that?
I'm also struggling with even starting to quieten specific scale notes, I'm thinking it's a series of if then statements with modulus in it but that seems inefficient - any real programmers got a clue to set me in the right direction? @McD @wim @_ki
Actually just remembered the discord, maybe someone there...
@Krupa If i understood correctly, you wan to speed up your IF-Cascade which filters out specific scale notes.
You could precompute the 12 (or even 127 if the result differs per octave) outcomes into a simple array containing only YES of NO and later-on just have a single IF like
.
In the case you need an offset per note or scale-step to ‚adjust‘ to a new scale, you could store the needed offset (including the 0 for NO offset) in an array and later-on just always add the computed offset - without any IF or IF-cascade needed.
And as general remark for the ‚Strumming via XY pad‘ idea, i would like to re-mention the idea (of wim iirc) that having an OnXYPadDown and OnXYPadUp Moazic event would be nice.
Thanks for that @_ki food for thought, I’m still at the point of figuring out the if cascade right now. An array sounds like a sensible proper solution that I can move to once my head is around the basic routine
I've very hackishly set out what I [Roughly] aimed to achieve but it's definitely going wrong somewhere, might well be beyond my limits already 🤣
Just trying to upload a patch to patchstorage but it won’t let me - there’s just a red delete button where the file goes... it says below that .mozaic files are supported...
Wally alert, I just needed a screenshot...
https://patchstorage.com/myharpx/
If anyone's feeling dangerous 😁
It's definitely more complex than the first script I wrote!
It looks like you're using sliders 3 to 9 to set the velocity for each note in a 7 note scale. I would add "Log notenum" after "notenum = ScaleQuantize notenum" to see how you're affecting notenum. It's not finding the closest diatonic scale degree of the triggered note. I wouldn't be the best person to help with that, because none of my scripts have anything to do with scales.
I see what you're trying to do with the "played" array to fix the stutter notes. Not a bad idea, maybe worth keeping, but I would also check to see if the note being triggered is the same as the last note, and only play it if it's different. And then also, if we get the option to cancel Note Offs soon, you could have it cancel the first Note Off when the same note is triggered twice in quick succession.
I agree, that would be useful. It can be a bit unpredictable with no way to differentiate between downs and ups.
Cheers @Skyblazer - I'll try logging the notes and see what I get, might point me in the right direction and eliminate those 'grace notes' 🤣 that keep showing...
With the played array thing, that was the only way I could think of doing it, checking if it's just been played would probably be better but I couldn't figure it out... Thinking also that I should add a condition that if it's velocity zero, it shouldn't even be triggered...
Some other thing that intruded in my thought process was, when looking at the API reference, the velocity of pads is accessible, based on distance from centre - to my mind this means that internally the XY position must be recorded - if this were accessible in scripts, we'd be able to have multiple XY pads?
Just wondering if it's ok to have this particular discussion here or if the learning one would be better, or even a new one just about harps? Don't want to keep spamming the wrong thread... 😬
@Krupa To check the last note played, you could add these three lines, indicated with ////. (And define the new LastPlayedNote variable in the OnLoad.) You'll need to use Round() on the value of notenum for this to work properly, and I would do that earlier, when notenum is first found. For knob values that translate to integers, you can use RoundDown, so that the knob positions are of equal width. SendMIDINoteOn will automatically round a value with a decimal, but if you're checking to see if two values are equal using the <> then Mozaic won't round them.
Multiple XY pads sounds fun, but unlikely. But it's possible to make a multi-window, multi-script interface by having them send AU parameters or SysEx or MIDI to each other. I plan for my XY automation record/draw/edit to use the slider+XY interface to display+draw points, and the 16 buttons+4 knobs on the bottom for playhead controls etc.
I think the thread you're referencing is for @McD's tutorial series, but I could be wrong. If there are enough people asking questions at some point, it could be good to have a dedicated topic for Mozaic programming questions.
@Skyblazer thanks for that, I'd gotten a bit of that into the latest version but it's very useful to have some of your knowledge 👍
Still really stuck on the scales stuff to be honest, have neatened up the whole thing, moved some sliders about and got decent logs going - uploaded to PatchStorage. I'll probably have another go later tonight, been looking at all the scale scripts I can find for clues 😁
We (general we) probably ought to revive @McD's tutorial thread and use it for examining Mozaic functionality in a much more rudimentary way than simply sharing examples of script.
I for one, could benefit from an overview of the procedural rules of how Mozaic executes code. And more detailed descriptions to help understand events, functions, arrays, variables, knobs, and the proper way to write math equations into event parameters.
i.e.. Can I modify the same variable in a linear way on several different lines within the same event block... Does Mozaic read and execute lines in an event block from top to bottom?
Can I use two or more instances of the same event in the same script, and if I do how does Mozaic handle execution of multiple instances of the same event?
It's the non-linear concept of code execution that keeps me confused, especially when I read examples of other peoples' code and see what looks to me like instructions written in a linear fashion.
Does this mean that some aspect of Mozaic behave linearly, and others do not?
Amongst other things I struggle to wrap my head around...
I'll take a swing at the ball. Someone might fix any corner cases I miss.
Generally, Mozaic only responds to 3 event types:
A Mozaic script just sits and waits for these events and executes "linear lines of code" in a block bookcased by "@Name" and "@End" statements. Each of these Blocks is a FUNCTION. Some FUNCTIONS come with the product and some we design with a Custom Name and execute with a "Call @MyShit" statement.
Where the magic comes from is a master list of MIDI events to be sent out by the Mozaic Master Controller that @Brambos wrote in the essential interpreter/execution engine.
It maintains a timeline list of events to execute according to an internal master clock.
So, you write an echo block and Bram's engine adds multiple output events at the right time points to send out each echo with Channel, Note, Velocity or CC details for each point in future time and future time can be a just a few internal clock ticks. Do NOT confuse this Mozaic internal clock with the DAW's clock or even some system clock.
It's the core of Bram's excution engine which does a few things in a very, very fast loop:
This internal list is executed internally. But there are no commands to ask questions about this list and do an extra editing or moving the clock back 3 seconds or any processing ideas we might have.
You may only alter the future but never anything that came before now. Once written in the master list it will happen and Bram protects the app to insure that "social contract" with us is never broken. We can generate more events on that list than most targets can accept and process... we can bury a synth with MIDI events and it might appear that Mozaic is buggy but I really doubt it's failing to just output the events requested in the script commands. We wrote a bad "idea" for the target. It's a feature... use this power wisely and debug unintended consequences. Debugging is a real bitch by the way. It's often better to roll back to something that worked and try another idea to be added.
I hope that helps.
Where the human mind fails us here is predicting what hundred of overlapping event request will do.
We write apps that forget to stop notes or play the wrong notes according to our expectations. It will do whatever we ask on this FUNCTION blocks.
Does that help? or does it need to be cut into smaller pieces?
Yes.
No, you can’t. [edit - as @_ki mentions below, only the topmost one will execute in the case of duplicate names.]
However, you can call the same event more than once. You use variables to get the different results from the event that you need each time you call it.
Within an event things are linear. However, more than one event can be doing things at a time. (Not technically, down deep, but conceptually.)
I can be making dinner following a recipe ... a sequence of events. I can be having a glass of wine while I cook. I may be thinking about conversation I had earlier in the day. I can be listening to a song, answering a question from the wife, checking a text message ... all pretty much at at the same time. Those are examples of separate linear processes. Each can continue their linear process because my brain keep tracks of what I’m doing and returns to each task as capacity allows.
Events are like that. They start with a trigger and execute top to bottom within themselves until their end. But if a trigger such as an incoming MIDI note or a timer variable reaching a certain value happens during this execution, the “brain” also allocates thinking and acting resources to that other task. It doesn’t technically do more than one thing at the same time, but since its brain is fast, and it is able to keep track of where other events are in their execution, it can juggle those tasks well enough that for all intents and purposes, they’re all running simultaneously (until they aren’t because something gets overloaded ... which is rare in my experience.)
@_ki did an excellent job some pages back at explaining how Mozaic works, event execution and priority, etc. If you look back to when you were first starting to work with Mozaic and had similar questions, I’m sure you’ll find it.
It would be difficult to write something generalized, such as you’re saying would be helpful. IMO it’s better just to ask specific questions as you have been doing until it starts to click.
@horsetrainer Everything is executed linear, at each timeframe there is only one of the Mozaic events fired and the next event will be fired when the current returned. There are no interrupts in Mozaic, no event handler will be called while an event function is handled. But since everything happens so fast, it seems that that things are done in parallel.
If there are two or more events having the same name, only the top-most event-functions is called.
@McD : you might want to add a link to your tutorial thread in the Mozaic wiki article
Thanks @McD @wim @_ki
Those explanations help resolve one of the main things I've been confused about.
In my mind, what you've said translates to this....
Mozaic has two main parts. A hidden event handling engine running in the background, that linearly handles events fed into it by a code interpreter that reads code programed by the user.
The function of Mozaic is somewhat analogous to an analog tape delay....
An old analog tape delay transports magnetic tape first across a record head, and next across a play head. If I plug my synth audio output into the tape delay and play a bunch of notes, those sounds will be recorded onto the moving tape by the record head. Those recorded notes exist on precise physical locations on the moving tape relative to time they were recorded.
When those recorded notes on the tape reach the play head of the tape delay. They are converted back into sounds that play in the same timing order that they were recorded.
The output engine in Mozaic is similar to the play head of the tape delay.
I think this analogy helps explains how this Mozaic SendMidiThru function works.
Using the tape delay analogy.... The above event block tells the Mozaic "play head" to record any Midi input it receives (such as Midi Notes), onto the moving recording tape (The Backend Mozaic Buffer).
The tape (buffer) is then read by the play head (The Mozaic output engine), and sends those midi events back out in the exact same order that they were received.
For me this solves my confusion over how the one "SendMIDIThru" command could handle multiple rapid Midi events under the assumption that Mozaic operated in a strictly non-linear fashion.
The front end of Mozaic is essentially non-linear, but the "output engine" running on the backend of the Mozaic program is a linear event processor.
This...
....Is analogous to a tape delay.
But the tape is moving so fast in Mozaic, that there is no perceptible delay.
Thanks guys, now I have an answer to one of my biggest barriers in understanding Mozaic.
I think you need to expand that just a little. There is a guy sitting in front of a bank of tape machines. Those are the events. He has an earpiece through which a bunch of people are telling him which tape machines to punch in. He triggers those each time someone tells him to. He doesn’t care what #1 is done playing when he hits play on #17, he just does it. The other people sending instructions don’t care what the others are telling him either or what the other tape machines are working on, they just tell him what to do.
OK, hopefully you’re back to total confusion. Whew. That was close.
Yup...
Might you (or anyone) please try to explain that concept using a minimum sample of functional Mozaic code as an example.
And annotate the code example to explain how the Mozaic "Backend Engine" is handling events analogous to a "bank of tape machines"?
OK, I’ll bite. The script below doesn’t process midi notes, but does demonstrate trigger-based events. A MIDI note or message is just another trigger. Hopefully you get the idea.
Many thanks @wim ,
Your example was extremely good at helping me understand Mozaic functionality better!
It also made me think of an idea for a script that I think would be a very educational "Teaching Script".
How would you write a script that does the following......
Using three PADS in "layout 0".
One PAD is labeled: "RECORD"
The second PAD is labeled: "ERASE"
The Third PAD is Labeled: "TRIGGER"
When the user press/releases the "RECORD" pad.
It arms the script for recording four individual notes.
The user can then press any four sequential notes on the keyboard, and the script will remember those four notes in the order the notes were played.
Next, the user can tap the "TRIGGER" pad at any rhythm they choose, and every single tap of the PAD will cause each of the four recorded notes to play individually, "one note at a time", "in the same order that they were recorded in". (They could loop or not, whatever is easiest)
Lastly,
Pressing the "ERASE" PAD, deletes any recorded notes, and readies the script for entering four new notes by again tapping the "RECORD" PAD.
.........
I'm also going to make a script request for a full functional version of the above principle in the script request thread. Because I really like the idea of being able to pre-enter a series of notes. Then have the ability to play them back in any rhythm you can think of by simply tapping a single pad.
If it could be made to also record and play chords... better yet!
That’s pretty easy. Chords would be a little bit more tricky as you’d have to choose a time threshold for detecting a chord vs. the next note or chordnote. And storing the notes for playback is marginally more complicated because you don’t in advance how many notes to store. But still, pretty simple.
Cool!
I think the simple version script should cover some of the elements of Mozaic scripting that I would really like to learn.
e.g.. Using variables to store notes, then recalling the notes back out of the variables.
A fully functional (useful) version of the script. Could have a knob to adjust the number of individual notes you want the script to be able to record. (or leave that number open to the number of keys the user plays?)
Can the TRIGGER PAD be used to hold each note for as long as the Pad is held down (like a keyboard key).?
I think such a script would be really cool for quickly composing fast played complex bass lines, and entering them onto a track by "playing" them with the single PAD.
It should also be useful for quickly developing melodies.
The ERASE pad lets you clear the memory and experiment with lots of ideas in short time. I think this should be a very useful compositional tool.
Close but not quite accurate. There's the Script which is fed events from a single lane MIDI road.
The script triggers FUNCTIONS based upon the MIDI event type:
That Mozaic script can store information in variables, like:
"memorize" is a nice analogy for the timeline in the core engine. It's a long running memo/list of events to sent out with timestamps on them: a "to do later" list.
The script can also forward MIDI outputs the the BACKEND runtime wizard that accepts commands and manages the future timeline.
I'll use the Echo example again:
Almost all details other than these are up to the script writer. Mozaic can accept slow MIDI streams from the MIDI road in and request thousands of MIDI events be sent in the future. What is sent and at what time is all coded in the FUNCTIONS commends. One event in and 1 to 100,000 events out.
All the other questions have to do with using Variables and Commands to create interesting MIDI FX solutions.
The things that can't be done usually have to do with someone asking for an event out in response to
something changing in the future. That won't fit on the 3-step loop of execution. Programmers call this type of Loop a REPL (read-eval-print loop)
My description does mention an explicit Go To but it does help understand the real time flow of
the engine.
Does that help any further...
Studying any single script misses something essential... you can build some amazingly complex MIDI Functions and each one is a unique script with it's own internal logic.
You’re pretty good at articulating what you want, so maybe you should noodle on it until what you want it to do fully gels, then float it over on the script request thread. Most likely someone will pick it up.