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've heard Xequence user reports about "the app keyboard somehow feeling more laggy in iOS 14.2". I wonder if this conversion code maybe introduces significant latency too when using timestamps in the past (unlikely seeing that it only has to process a few bytes, but then again, who knows how many CIA security checks the MIDI packets are subjected to internally ) ?
Thanks @moodscaper and @AlanC3 for the detective work. At least I've dumped an informational message into our news API so users know that if Xequence is suddenly crashing all the time, "it wasn't me"
The fact that it's crashing for you on a single command and with the same stack trace is quite the coincidence, isn't it?
Nice to have confirmation that it's not some weird bug in my own code that I'd missed.
I really hope so: I'd rather not have to do the conversion to MIDI 2.0 right now.
It's not just the Core Audio team; Core Graphics has recently developed some bizarre behaviour that wasn't there in previous releases...
I wonder if it will get its own ring on the fitness app...?
My turn for a rant:
Just been looking at the documentation for all this. So I will ultimately need to use MIDISendEventList / MIDIReceivedEventList to send MIDIEventPackets now. What’s in one of those?
Not exactly helpful.
But there are helper functions to build events in MIDI 2.0 UMP format, like MIDI1UPNoteOn; how do they work?
Sigh.
What’s happening on the input side? Well, MIDIInputPortCreateWithBlock has been replaced with MIDIInputPortCreateWithProtocol and it takes a MIDIReceiveBlock instead of a MIDIReadBlock.
But MIDIReceiveBlock is listed in the Deprecated Symbols section...
This is why I'm going back to building kids educational apps.
@AlanC3 - it's a crazy hot mess isn't it? And I'm pretty sure Gene De Lisa mentioned that at least one of those helpers blows-up when you call it.
I'm guessing we're in the same boat - I've lots of code dependent on the "old" packet list and block-based port stuff in one of my apps. Significant number of iOS music makers not updating to iOS 14 yet either, and there's no way I'm coding around all this new stuff with horrendous #available blocks.
I strongly suspect the audio team (if there is one) has zero influence on what gets released and when, so we're basically on their dev branch and we get whatever they happened to check-in on iOS update build / release day...
Wait until iOS 17 requires user permission and an "entitlement" to request touch screen access or draw pixels on the display
I'm just taking a cursory look at the UMP specification. Is this satire?
I mean, seriously... is this for 3 year olds?
I think a lot of this has to do with lawyers, the legal system, the industry of litigation etc.
Then lawyers need to be banned, the legal system needs to change, and the industry of litigation has to be demolished
Lets just put you in charge!
I can confirm the other bug mentioned on the Juce Forums thread:
https://forum.juce.com/t/ios-14-2-midi-connections-broken/42440/8
When you call MIDIObjectGetStringProperty it may return with no error but give you a null string pointer. This was causing a crash when I was requesting the endpoint name to build a list of available MIDI devices: the function apparently succeeded, but the returned string was null causing a crash when I attempted to convert it to an NSString. My fault for not checking for null, but the endpoint name for a device should always be present.
This is another intermittent one that I can't reproduce: I've had one crash report with this as the cause.
@AlanC3 makes you wonder who the hell they let loose on the Core MIDI code between 14.1 and 14.2 release...
Luckily I escaped this other issue because of the crazy stuff I have to do when calling MIDIObjectGetStringProperty() from Swift...
Looking at it some more I can't be certain the pointer returned by MIDIObjectGetStringProperty was null, all I can say is that it was definitely invalid since the app crashed when copying the string contents. That said, if you've not been bitten by this from Swift with all the extra checks that involves, it being null does seem most likely.
@AlanC3 - yep, lots of null type checking going on in Swift, so you have to do shenanigans like this, which I guess should protect you...
Did you just add that disclaimer when you launch Xeq2?
I swear it wasn’t there last night when I was using it.
😄
Yes. Is the wording too harsh? 😬
So I've installed iOS 14.3 which, according to the thread on the juice forum, should have stopped the MIDI problems. Assuming Apple didn't drop whatever fixes were in the betas from the final release.
I can't get my own app to crash (but then I couldn't recreate the problem on 14.2) and I'm not seeing problems anywhere else, so here's hoping...
@AlanC3 Good to know. I think I just got my first 14.2 crash stemming from the MIDI issues
An additional comment Form the Auria Pro dev on Core MIDI and 14.2 found on the Auria Pro forum.
The crash I was getting on the call to MIDISend() seems to be fixed on 14.3
I guess disabling CoreMIDI on 14.2 is one way of stopping the crashing!
That's good. Looks like Apple have fixed it.
I think that a number of these documents are written for various parties, and it is almost impossible to imagine how much can be misinterpreted no matter how clear the writer thinks it is. I usually find that what people is too much actually isn't enough because it misses some material. Since much of the MIDI 2.0 material hasn't been released to the general public, I don't feel comfortable using any of the MIDI 2.0 features. I'm still trying to find information on big-endian/little-endian issues that occur when 32-bit integers (presumably unsigned) are sent over byte oriented systems.
When I look at https://developer.apple.com/documentation/coremidi/1495282-midiobjectgetstringproperty it says that MIDIObjectGetStringProperty returns a value of type OSStatus. The value of foo is only defined if the returned value is noErr. Frankly, I'm not familiar with Swift and became unhappy the more I read about it. What checks the returned value? The web page also explicitly states that the value of foo can be null.
My understanding is that Swift is a wrapper around Objective-C code and I found the discussion of what happens with the wrapper to be unclear.
My problem is that they don't seem to be consistent on the meaning of the word deprecate. Look at https://bradleyross.github.io/ObjectiveC-Examples/Documentation/BRossTools/FunctionalArea.html The items listed under new architecture (MIDI 2.0) are only available in the latest versions of the operating systems and older versions of the operating system are still supported, the items listed under "old architecture" must still be current since that is the only way to work with older operating systems. My understanding is that is that the lifecycle is: beta, production, superseded (will be deprecated), deprecated, and removed. Also notice that the tag placed on the methods in the documentation is inconsistent with what I consider to be their actual status. I look at the documentation on the web, the contents of the header files, and then run the header files through Doxygen. At that point, I still feel like I'm throwing dice to get my answer.
I'm one of those old curmudgeons who remember when documentation actually documented something and filled up bookcases.
Swift is definitely not a wrapper around Obj-C. Many of the Obj-C libraries have direct, zero cost, bridges to the Objective-C libraries and Swift was designed to handle this, but Swift isn't wrapping Objective-C to do this.
What you are seeing in these types of calls is older and deeper than that though. If you see "Core" in a library name, it usually means it's a C implementation at base. You end up needing to think a bit in a C way when you work directly with these libraries. Who checks the OSStatus value depends on who is calling the function. Sometimes, you are providing the implementation and you provide the status or the error. Sometimes it's the other way around.
There were several libraries talked about at this years WWDC that won't ever have Objective-C versions. Swift with some C is the way everything is moving at Apple now. Swift isn't my favorite language in the world, but it is pretty good and you might as well start using it if you plan on doing dev work on Apple platforms.
@NeonSilicon is spot-on. That code snippet is ugly due to it talking essentially to an API designed for C.
In the code, foo is declared as possibly being nil, and bar will only be assigned a non-nil value if foo isn't nil. What's missing / implied in the snippet is the else return nil, and the return type of an enclosing function being a String? optional (i.e. possibly nil )
In the (contrived) example, I don't check the OSStatus return value because I don't care. All I care about is whether I get something back or not, and there's a test for that when takeRetainedValue() is called.
There's all sorts of noisy code like this when you have to interact with the C-based APIs in Swift. Dealing with pointers is especially fun...
Documentation... Well, as someone once told me, if you're taking on this particular tech-stack (especially the audio sub-set) be prepared to be 40% developer and 60% detective
Having dealt with a lot of messy C code in the best, I interpreted the documentation as saying that if the return value (OSStatus), is not noErr, the value of foo is undefined. That means that the value may be the right value, the wrong value, nil, or something totally inappropriate. Assuming anything else is like being a forensic scientist without a magnifying glass, fingerprint kit, or any other tools. "Undefined" is a term I became very familiar with when coding for IBM mainframes. I still shudder when I hear the hexadecimal error code 0c4. For MS-DOS programmers, the equivalent was "General Protection Fault".
wow, interesting thread.
can us non dev's help at all? can we write apple or something?
I see... your reaction against the profession of legal practice is conditional on a premise.
I've already figured out you're a no government type so this is a consistent message.
Will there be a Xequence 3 anytime soon? Just kidding. I respect your work and will pay for more MIDI focused tools.
I think I own the whole catalog.