2017-04-25 4 views
0

Ich versuche Apples AVMIDIPlayer Objekt für das Abspielen einer MIDI-Datei zu verwenden. Es scheint einfach genug in Swift, mit dem folgenden Code:Wie hält man AVMIDIPlayer am Laufen?

let midiFile:NSURL = NSURL(fileURLWithPath:"/path/to/midifile.mid") 
var midiPlayer: AVMIDIPlayer? 

do { 
    try midiPlayer = AVMIDIPlayer(contentsOf: midiFile as URL, soundBankURL: nil) 
    midiPlayer?.prepareToPlay() 
} catch { 
    print("could not create MIDI player") 
} 

midiPlayer?.play { 
    print("finished playing") 
} 

Und es spielt für etwa 0,05 Sekunden. Ich nehme an, ich muss es in irgendeiner Art von Schleife einrahmen. Ich habe eine einfache Lösung versucht:

while stillGoing { 
midiPlayer?.play { 
    let stillGoing = false 
} 
} 

was funktioniert, aber ramps die CPU massiv. Gibt es einen besseren Weg? Neben dem ersten Kommentar habe ich versucht, eine Klasse zu erstellen, und obwohl es keine Fehler anzeigt, funktioniert es auch nicht.

class midiPlayer { 

var player: AVMIDIPlayer? 

    func play(file: String) { 
     let myURL = URL(string: file) 
do { 
    try self.player = AVMIDIPlayer.init(contentsOf: myURL!, soundBankURL: nil) 
    self.player?.prepareToPlay() 
} catch { 
    print("could not create MIDI player") 
} 
    self.player?.play() 
    } 
func stop() { 
self.player?.stop() 
} 
} 

// main 

let myPlayer = midiPlayer() 
let midiFile = "/path/to/midifile.mid" 
myPlayer.play(file: midiFile) 

Antwort

1

Sie waren in der Nähe Ihrer Schleife. Sie müssen nur der CPU Zeit geben, um loszulegen und andere Dinge zu tun, anstatt ständig zu überprüfen, ob midiPlayer schon fertig ist. Fügen Sie einen Anruf zu usleep() in Ihrer Schleife hinzu. Dieser prüft jede Zehntelsekunde:

let midiFile:NSURL = NSURL(fileURLWithPath:"/Users/steve/Desktop/Untitled.mid") 
var midiPlayer: AVMIDIPlayer? 

do { 
    try midiPlayer = AVMIDIPlayer(contentsOfURL: midiFile, soundBankURL: nil) 
    midiPlayer?.prepareToPlay() 
} catch { 
    print("could not create MIDI player") 
} 

var stillGoing = true 
while stillGoing { 
    midiPlayer?.play { 
     print("finished playing") 
     stillGoing = false 
    } 
    usleep(100000) 
} 
1

Sie müssen sicherstellen, dass das midiPlayer Objekt vorhanden ist, bis es zu spielen fertig ist. Wenn sich der obige Code nur in einer einzigen Funktion befindet, wird midiPlayer zerstört, wenn die Funktion zurückkehrt, da keine Referenzen mehr vorhanden sind. Normalerweise würden Sie midiPlayer als eine Eigenschaft eines Objekts deklarieren, wie einen untergeordneten Controller.

+0

Also muss ich eine Klasse mit diesem Code als Funktion/Methode erstellen, und dann eine Instanz der Klasse erstellen und die Methode aufrufen? Bisher ist dies nur ein CLI-Skript, also keine UI-Controller. – benwiggy

+1

Ah ok, in diesem Fall ist die Verwendung der Schleife der einzige Weg zu gehen. Setzen Sie einen 'sleep (1)' Anruf in die While-Schleife, so dass nicht die ganze CPU-Zeit verbraucht wird. Außerdem bin ich mir ziemlich sicher, dass du den 'midiPlayer? .play' Aufruf aus der while-Schleife entfernen musst. –

0

Brendan und Steves Antworten Kombination, ist der Schlüssel sleep oder usleep und außerhalb der Schleife die Play-Methode Frieren zu vermeiden, die CPU revving.

player?.play({return}) 
while player!.isPlaying { 
sleep(1) // or usleep(10000) 
} 

Der ursprüngliche stillGoing Wert funktioniert, aber es gibt auch eine isPlaying Methode.

.play braucht etwas zwischen seinen Klammern, um nach dem Abschluss nicht für immer hängen zu bleiben.

Vielen Dank.

Verwandte Themen