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
Add log commands to see both the raw knob values and the rounded value each time onKnobChange is triggered.
If you still don’t understand after doing that post a screenshot of the log and we can discuss what there is to be learned.
@pejman said:
This is the patch that works
espiegel wrote:
please go back to the two examples you posted and say out loud to yourself what happens in each line of code.
And see if you can spot on your own logically why neither one works.
Then read the explanation I provided about why they don’t work.
I guess after that we need to discuss how to use logging and how to test productively.
@pejman : I really can't figure out why they don't work
@pejman: since my explanation didn't mean anything to you. Let's walk through what is supposed to happen and what does happen.
We said earlier that notenum[lastPad] will be the notenumber of the last note sent.
Is that clear?
We also said that to avoid sending a duplicate note that we can compare the new knobvalue (rounded) to the last note that we sent -- and we only process the new value if it is different from the note sent.
Is that clear?
=== Here is your attempt #1 at solving the problem and analysis.
The first thing you do is compare noten to noteNum[LastPad]
Notice that you have not yet assigned a value to noten.
You cannot compare note to noteNum[LastPad] until after you have assigned the rounded knob value to noten.
You can't use a value in a comparison until it has been assigned a meaningful value. You need to assign the knob value to noten before you compare it to notenum[LastPad]
NOTE: when you ran that code, you should have seen a syntax error from Mozaic in the Log display, which is a clue to what is going wrong.
====== Here is your attempt 2 and an analysis
In this example, you correctly assign the new knobvalue to noten
But you immediately, assign the new value to notenum[LastPad].
As we discussed earlier, what you want to do is
Since you immediately assign the new value to notenum[lastPad], the test doesn't work.
Let's walk through what happens if you load the program, tap pad 0 and start turning the knob.
Let's say onknobbchange is called with a knob value of 49.1 the first time.
We know that notenum[0] starts out with a value of 49.
Here are the first three lines of code:
Here is what you get if the knobvalue is 49.1
Let's see what happens if you keep turning the knob and the new knobvalue is 52.6
Notice what happened this time. Even though the new knob value is 53, the note doesn't get sent out because the comparison happened after you already assigned the knob value to noteNum.
What will happen, is that the note will never be played but the value will always be changed.
@pejman: to solve the problem: get the knob value, do the test. Then, if the values aren't the same process the new value.
@espiegel , THATS GREATEST EXPLANATION, VERY VERY VERY THANKS 🙏👍.
I was not able to analyze the matter for myself in this way because I did not understand the relationship of some commands/variables with each other.
You have solved the puzzle for me with your detailed explanation, but I still have a question and a confusion, But apart from this topic.
I would be grateful if you could explain the answer to my question again in the same precise and clear way, because I am not able to analyze it.
That’s patch that solved with your explanation. Solved 2 problem,
1, avoiding repeat/duplicate notes
2, avoiding of creating note that was already in Lastpad via noteknob trough: noten <> nn
If i disabled ( nn ) and put notenum[LastPad] instead of nn , Wherever there is nn, patch works but doesn’t solved problem #2.
I would be very grateful if you explain the relationship between nn and notenum [LastPad] .
@pejman : you have made progress on part of the problem and introduced a new one.
The problem with your old code was only where you put the test in relation to getting the knob value. The test itself was fine.
The test only needs to compare its new knob value to the last sent note (which is noteNum[lastPad]).
The following test was right:
In your version, you added an additional test
“ and noten <> nn”
Can you explain your reasoning for adding a new test ?
Your new condition will prevent you from setting the note back to the value it had when the pad was first tapped.
Please do an analysis like I did analyzing the result of tapping pad 0 then
espiegel wrote: Can you explain your reasoning for adding a new test ?
If you remember, you asked me two things before.
1, avoiding repeat/duplicate notes
2, avoiding of creating and playing note that was already in Lastpad via noteknob trough .
That’s mean we touch LastPad that has note number 46 , when we turn noteknob , Note number 46 should not be played anymore and should not be created in Lastknob .
In this way, I also apply item number 2 in previous post.
If you remember, I took an initiative and solved it in this way:
@pejman wrote : I would be very grateful if you explain the relationship between nn and notenum [LastPad] .
@pejman : I believe you have misunderstood something I said. I did not intend for you to eliminate the possibility of being able to reassign the original note. I don’t believe I ever said that. My instruction was when turning the knob not to send a note unless it was different from the previous note.
You wrote: “ I would be very grateful if you explain the relationship between nn and notenum [LastPad] .”
Please try to answer it yourself by analyzing your script line-by-line. I recommend either printing g it out or taking screenshots and circling nn everywhere it occurs. Then summarize your observations and let’s discuss.
Ask yourself
Where does nn get its value?
When does its value change?
What changes the value of notenum[lastPad]
espiegel wrote: I believe you have misunderstood something I said. I did not intend for you to eliminate the possibility of being able to reassign the original note. I don’t believe I ever said that. My instruction was when turning the knob not to send a note unless it was different from the previous note.
https://forum.audiob.us/post/quote/55532/Comment_1214516
I had this impression from your item number 4
Item 4 is:
I didn't mean to imply that you should prevent the original value from being reassigned. I meant:
when knob 0 is turned:
@espiegel , Your wrote; Please try to answer it yourself by analyzing your script line-by-line. I recommend either printing g it out or taking screenshots and circling nn everywhere it occurs. Then summarize your observations and let’s discuss.
Ask yourself
Where does nn get its value?
When does its value change?
What changes the value of notenum[lastPad]
Where does nn get its value?
nn takes its values from notenum[lastpad].
When does its value change?
As I can see in the screenshots, the values change when I touch the lastpad after turning the knobnote. It’s mean nn value doesn’t change after turning knob , it changes after touching lastpad after turning knob .
What changes the value of notenum[lastPad] ?
noten which was previously = to Getknobvalue 0 of course after comparing ( if noten <> notenum[LastPad] ).
@pejman : do you have any remaining questions about noten, nn and notenum[lastPad] or has your exploration answered them?
I think I have no questions or doubts at this time about nn ,notenum , noten.
I wanted to send you screenshots about my previous post, but I have been trying for several hours now and I don't know why my screenshots are not uploaded in the post.
A very small question, :
According to this code, the knob should display the number 1 when it reaches value 43 or 42, and it should display the number 2 when it reaches value 85 or 86, but this is not the case in practice. Shouldn't 0 to 2 be equally divided between 0 to 127 in Round mode?
@OnKnobChange
value = GetKnobValue 0
t = TranslateScale value, 0, 127, 0, 2
LabelKnob 0, Round t
@End
I suggest you add logging and log the raw value, the translated value and rounded value.
The translated value will round to 2 when the translated value 1.5 or above.
0 to 127 maps to 0 to 2. That gives us 64 to 127 mapping to 1 to 2.
1.5 is half way from 64 to 127. I think that gives us about 95 and above mapping to 2.
The equation of the translation is value * 2/127
Do you see something different?
Please ignore my previous post
Let's look at it this way :
When I turn knob , mozaic shows in value status bar
When label knob shows 1 , status bar shows 32
When label knob shows 2 , status bar shows 95
When knob goes to the end , status bar shows 95
That’s mean:
32 = 1 ( translated ) ==> it’s mean 0 to 1 = 32 value
95 = 2 ( translated ) ==> it’s mean 1 to 2 = 63 value
2 to end of knob = 127 ==> it’s mean 2 to end knob ==> from 95 to 127 = 32 value
0 to 1 and 2 to end of knob are equal ==> each of them are 32 value
Why 1 to 2 is 63 value ? Why is this amount twice as much as the others?
You wrote: 0 to 127 maps to 0 to 2. That gives us 64 to 127 mapping to 1 to 2.
No , mozaic does not do that, The mozaic shows 1, from 32 onwards and 2, from 95 onwards
You wrote: 1.5 is half way from 64 to 127. I think that gives us about 95 and above mapping to 2.
In this part, you are absolutely right, but I don't understand it> @pejman said:
>
You are misinterpreting what I wrote. I mean that the result of the scaling maps the numbers from 0 to 63 to the range of 0 to 1 and the input range 64 to 127 to the range 1 to 2. Which results in 95 (actually 95.25) mapping to 1.5. Rounded 1.5 becomes 2
I also provided the formula for doing the conversion.
What don’t you understand?
Did you log the values as I suggested.
The scaled value will be knobValue * (2/127)
That value is then rounded
Ok , The issue is resolved for me
Espiegel wrote: Did you log the values as I suggested.
Yes .
Meanwhile, my screenshots from the June 19th post have finally been uploaded.
Do you remaining questions about
or about anything else? Any remaining questions about the relationships you mention below?
@pejman wrote:
No, I have no problem or question.
Thank you very much for all the patience and hard work you have done for me so far. 🙏🙏🙏
If another practice or another lesson is going to start, I am ready, of course, if you are willing
@pejman : if you post your latest version, there are a few little refinements that are probably worth discussing to solidify your understanding and that may be helpful as you work on your own scripts in the future.
@pejman : that looks good.
Here a few comments/thoughts to wrap up this exercise.
in a few places there is old code that has been commented out. Now, that it isn't needed, you might want to remove those lines. I find it a good habit to remove outdated code to avoid my own confusion if i come back to a script after not seeing it for a while.
In onPadDown, you might consider using notenum[lastPad] instead of nn and notecolors[lastPad] instead of nc. and LastPadVelocity instead of vel. Sometimes it makes code more readable to use use intermediate variables like your nn and nc, but I I am not sure that is the case here.
variable names. You might want use more meaningful names for variables -- if you write code that you have to come back to at a later time or need to show someone, it makes code more readable to see a variable called something like noteToSend colorScaled rather than nn and col
It makes a big difference when reading someone else's code (or your own old code) to have variable names that tell you what they are for.
In onKnobChange, there are these lines:
A few things, you don't need to round the output of GetKnobValue 1. You can use
If you want to break up the calculation into two stages as you have, you can use just one variable. For example,
very nice information ,thanks .
Now that you have mentioned this, I have a general question in my mind.
Can using nn and nc, which are completely unnecessary in my script, affect CPU usage?
Especially when the script is Huge.
Of course you mean this :
colorIndex = Round TranslateScale colorIndex, 0 , 127, 0 , 7
Is there anything wrong with using ( colorIndex ) name again?
Once for GetKnobValue, once for TranslateScale ?
Modified by variable names
@pejman wrote:
Yes. Apologies for the typo
Do you mean is there a problem using colorIndex as I showed?
If so, there is no problem. A variable just has the last value assigned to it and Mozaic (like most programming languages) allows a variable to be assigned the result of a calculation that involves itself. The right side of the equals sign is evaluated and then assigned to the variable on the left side.
For example , the following is fine
@pejman asked
It depends. Usually, not. There are times where using an intermediate variable can save CPU — when there are loops that execute many times in a time-sensitive context, reading a function output into a variable can save time compared to reading the same function output over and over. Situations like that are context dependent.
Using a huge number of redundant variables can eat up memory in some circumstances. But in a script like this , you don’t have to worry about that.
Very nice , thanks for explanation. 🙏
Is there a new lesson or a new subject that we have to work on or can I work on the subject related to saving the color of the pad through other pads?