I have an AVMIDIPlayer I am trying to load with the soundfont of one instrument (steinway grand piano) and I keep getting these errors when trying to play the song with my device:
DLSBankManager.cpp:99 BankEntry::LoadInstrument: Unable to find patch 0 bank 0x78/0
DLSBankManager.cpp:100 about to throw -10851: LoadInstrument: Failed to load patch from bank
GlobalState.cpp:486 DLS/SF2 bank load failed
I have tried setting the errno to 0, but this did not solve my problem. Here is my code:
import SwiftUI
import AudioToolbox
import AVFoundation
class Song {
var musicSequence: MusicSequence?
var tracks: [Int: MusicTrack] = [:]
init() {
guard NewMusicSequence(&musicSequence) == OSStatus(noErr) else {
fatalError("Cannot create MusicSequence")
}
}
}
class MidiPlayer {
var midiPlayer: AVMIDIPlayer?
var bankURL: URL
var song: Song
init(song: Song) {
guard let bankURL = Bundle.main.url(forResource: "Steinway_Model_L_Grand_Piano", withExtension: "sf2") else {
fatalError(""Steinway Model L Grand Piano.sf2" file not found.")
}
self.bankURL = bankURL
self.song = song
}
func prepareSong(song: Song){
var data: Unmanaged<CFData>?
guard MusicSequenceFileCreateData(song.musicSequence!, MusicSequenceFileTypeID.midiType, MusicSequenceFileFlags.eraseFile, 480, &data) == OSStatus(noErr) else {
fatalError("Cannot create music midi data")
}
if let md = data {
let midiData = md.takeUnretainedValue() as Data
do {
errno = 0
try self.midiPlayer = AVMIDIPlayer(data: midiData, soundBankURL: self.bankURL)
} catch let error {
fatalError(error.localizedDescription)
}
}
self.midiPlayer!.prepareToPlay()
}
func playSong() async {
if let md = self.midiPlayer {
md.currentPosition = 0
await md.play()
}
}
func createMusicSequence(chords: [[UInt8]] ) {
//var musicSequence: MusicSequence?
var status = NewMusicSequence(&song.musicSequence)
if status != noErr {
print(" bad status (status) creating sequence")
}
var tempoTrack: MusicTrack?
if MusicSequenceGetTempoTrack(song.musicSequence!, &tempoTrack) != noErr {
assert(tempoTrack != nil, "Cannot get tempo track")
}
//MusicTrackClear(tempoTrack, 0, 1)
if MusicTrackNewExtendedTempoEvent(tempoTrack!, 0.0, 256.0) != noErr {
print("could not set tempo")
}
if MusicTrackNewExtendedTempoEvent(tempoTrack!, 4.0, 256.0) != noErr {
print("could not set tempo")
}
// add a track
var track: MusicTrack?
status = MusicSequenceNewTrack(song.musicSequence!, &track)
if status != noErr {
print("error creating track (status)")
}
// make some notes and put them on the track
var beat: MusicTimeStamp = 0.0
for batch in 0..<chords.count {
for note: UInt8 in chords[batch] {
var mess = MIDINoteMessage(channel: 0,
note: note,
velocity: 64,
releaseVelocity: 0,
duration: 1.0 )
status = MusicTrackNewMIDINoteEvent(track!, beat, &mess)
if status != noErr { print("creating new midi note event (status)") }
}// beat changes after this
beat += 1
}
CAShow(UnsafeMutablePointer<MusicSequence>(song.musicSequence!))
}
}
/*
func createPlayer(chords : [[UInt8]]){
var musicPlayer : MusicPlayer? = nil
var player = NewMusicPlayer(&musicPlayer)
player = MusicPlayerSetSequence(musicPlayer!, createMusicSequence(chords: chords))
player = MusicPlayerStart(musicPlayer!)
}
*/
struct ContentView: View {
let chords: [[UInt8]] = [[60, 64, 67], [62], [64, 67, 71]]
let song = Song()
var body: some View {
VStack {
Button("Click Me", action: {
let player = MidiPlayer(song: song)
// C, D, and E major chords
player.createMusicSequence(chords: chords)
player.prepareSong(song: song)
Task{
do{
await player.playSong()
}
catch{
print(error)
}
}
})
}
}
}
How can I successfully load the sound font?
sdetta is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.