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.
Saving a midi file corrupts it
Hi All,
Really hoping someone can help as I'm pulling my hair out here, and I really don't have much to spare.
The app I'm developing is coming along slowly but surely (except for being butt-ugly and still trying to resolve heterogenous object saving/loading in JSON, dammit!), but I've come across an issue recently which I'm having a real problem trying to resolve.
I'm using Swift and SwiftUI, and have tried to resolve the issue with both AudioKit and MIKMIDI. I'm simply trying to save the notes I've produced as a midi file. Up until recently, and I fear it might have been the latest OS update, everything was working fine (using AudioKit) and now when I try to save a file...well, it's just corrupt. A single track with 5 notes starting from position 0 looks like this when viewed in Garageband:
I've used an online midi-analyzer and it gives an error of "Undefined variable: last". The example code I've written is as simple as can be (though you'll need MIKMIDI, and a soundfont in a folder called resources to make it work) and the code is shown at the bottom of the post.
My next step will be to load a file I know works and then save it straight back out again to see if there's any difference.
Has anyone else come across this issue, or is it just something I'm doing wrong? The fact it's happening in both frameworks is really frustrating but suggests that they're not the problem. Has the midi format changed in latest version, which would be weird I admit? Not knowing a great deal about how Mac's work under the hood, is there a .mid definition that could have been corrupted? Or is it that I'm simply doing something fundamentally wrong?
I'd really appreciate it if someone could help me out here as I've scoured and posted elsewhere but have not had any responses back.
Thanks in advance,
Jes
import SwiftUI
import MIKMIDI
let sequence = MIKMIDISequence()
let sequencer = MIKMIDISequencer()
func initialise(){
do {
let tempo = 120.0
let signature = MIKMIDITimeSignature(numerator: 4, denominator: 4)
sequence.setOverallTempo(tempo)
sequence.setOverallTimeSignature(signature)
for t in sequence.tracks {
sequence.removeTrack(t)
}
let _ = try sequence.addTrack()
let track = sequence.tracks[0]
let trackSynth = sequencer.builtinSynthesizer(for: track)
if let soundfont = Bundle.main.url(forResource: "Chaos Bank", withExtension: "sf2") {
do {
try trackSynth?.loadSoundfontFromFile(at: soundfont)
} catch {
print("can not load SoundFont with error: \(error)")
}
var instrumentId = MIKMIDISynthesizerInstrument(id: 10, name: "Eric")
try trackSynth!.selectInstrument(instrumentId!, error: ())
print("Available Instruments \(trackSynth!.availableInstruments)")
}
var notes = [MIKMIDINoteEvent]()
for n in 0..<5 {
let note = MIKMIDINoteEvent(timeStamp:Double(n),note:UInt8(60 + n),velocity:100,duration:0.25,channel:1)
notes.append(note)
}
track.addEvents(notes)
let length = track.length
sequence.length = length
sequencer.sequence = sequence
print("Duration in seconds \(sequencer.sequence.durationInSeconds)")
print("Tempo Track \(sequence.tempoTrack.length), \(sequence.tempoTrack.notes.count)")
for t in sequence.tracks {
print("Track Number \(t.trackNumber)")
for notes in t.notes {
print("Note \(notes.note), \(notes.duration), \(notes.timeStamp)")
}
}
let hexValues = sequencer.sequence.dataValue!.map { String(format: "%02X", $0) }
print(hexValues.joined(separator: " "))
} catch let error {
print(error.localizedDescription)
}
}
func startPlayback(){
sequencer.startPlayback()
}
func stopPlayback(){
sequencer.stop()
}
func getDocumentsDirectory() -> URL {
// find all possible documents directories for this user
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
// just send back the first one, which ought to be the only one
print(paths[0])
return paths[0]
}
func saveFile()->String{
try! sequence.write(to: getDocumentsDirectory().appendingPathComponent("MIKMIDI.mid"))
return getDocumentsDirectory().absoluteString
}
struct ContentView: View {
var body: some View {
VStack {
Text("MIKMIDI Test 01")
let _ = initialise()
Button("Play", action: startPlayback)
Button("Stop", action: stopPlayback)
Button("Save") {
let _ = print(saveFile())
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Comments
Hi All.
I think I might have resolved it by starting at position 1...
Could it really be that simple? That seems to have worked with the code above, now need to check in my full app. Not sure that's ever changed but worth verifying - I'll get back to you as soon as I've found out.
Jes
Hi All.
Ok, so tried setting the start position to 1 when using both MIKMIDI and AudioKit; the former produces a valid file, the latter still has the same problem. I've taken a look at the Data within both sequences I've created using each Framework and there is a clear discrepancy though I don't understand the format well enough to identify what that is.
I'll post the full (again, butt-ugly) test code below and if anyone can tell me what I'm doing wrong it'd be appreciated.
I've got no problem in using AudioKit for the main part of my app and MIKMIDI solely for saving the data but, obviously, would prefer not to (I currently can't use MIKMIDI for everything as I'm running into problems with choosing different instruments from soundfont).
Again, thanks in advance,
Jes
@SadOldGoth : have you contacted the AudioKit folks about this?
Yes, I have, via StackOverflow, though not quite as fully detailed as above. If you know of another channel to contact them, could you let me know? Thanks (and thanks for responding).
Jes
There is contact number information on
https://audiokitpro.com/audiokit/
You may also be able to log bugs via the relevant github