2017-04-25 2 views
0

J'essaie d'utiliser l'objet AVMIDIPlayer d'Apple pour jouer un fichier MIDI. Il semble assez facile dans Swift, en utilisant le code suivant:Comment conserver AVMIDIPlayer en cours de lecture?

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") 
} 

Et il joue pendant environ 0,05 secondes. Je suppose que j'ai besoin de l'encadrer dans une sorte de boucle. J'ai essayé une solution simple:

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

qui fonctionne, mais augmente massivement le CPU. Y a-t-il un meilleur moyen? Suite au premier commentaire, j'ai essayé de créer une classe, et bien qu'il ne signale aucune erreur, cela ne fonctionne pas non plus.

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) 

Répondre

1

Vous étiez proche de votre boucle. Vous avez juste besoin de donner au CPU le temps de partir et de faire d'autres choses au lieu de constamment vérifier si midiPlayer est encore fini. Ajoutez un appel à usleep() dans votre boucle. Celui-ci vérifie chaque dixième de seconde:

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

Vous devez vous assurer que l'objet midiPlayer existe jusqu'à ce qu'il soit fait jouer. Si le code ci-dessus est juste dans une seule fonction, midiPlayer sera détruit lorsque la fonction retourne parce qu'il n'y a pas de références à lui. Généralement, vous déclarez midiPlayer en tant que propriété d'un objet, comme un contrôleur sous-classé.

+0

Je dois donc créer une classe avec ce code en tant que fonction/méthode, puis créer une instance de la classe et appeler la méthode? Jusqu'à présent, il s'agit juste d'un script CLI, donc pas de contrôleurs d'interface utilisateur. – benwiggy

+1

Ah ok, dans ce cas l'utilisation de la boucle est la seule façon d'y aller. Mettez un appel 'sleep (1)' dans la boucle while afin de ne pas perdre tout votre temps CPU. En outre, je suis sûr que vous devrez déplacer l'appel 'midiPlayer? .play' hors de la boucle while. –

0

La combinaison des réponses Brendan et Steve, la clé est sleep ou usleep et coller la méthode de lecture en dehors de la boucle pour éviter la montée en régime CPU.

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

La valeur stillGoing originale fonctionne, mais il y a aussi une méthode isPlaying.

.play besoin de quelque chose entre ses supports pour éviter de suspendre pour toujours après l'achèvement.

Merci beaucoup.