如何保持 AVMIDIPlayer 播放?
How to keep AVMIDIPlayer playing?
我正在尝试使用 Apple 的 AVMIDIPlayer
对象来播放 MIDI 文件。在 Swift 中使用以下代码似乎很容易:
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")
}
它播放了大约 0.05 秒。我想我需要在某种循环中构建它。我尝试了一个简单的解决方案:
while stillGoing {
midiPlayer?.play {
let stillGoing = false
}
}
有效,但会大幅提升 CPU。有没有更好的办法?
除了第一条评论,我尝试制作 class,虽然它没有标记任何错误,但它也不起作用。
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)
您需要确保 midiPlayer
对象在播放结束之前一直存在。如果上面的代码只是在一个函数中,midiPlayer
将在函数 returns 时被销毁,因为没有剩余的引用。通常,您会将 midiPlayer
声明为对象的 属性,例如子类控制器。
你已经接近循环了。您只需要给 CPU 时间去做其他事情,而不是不断检查 midiPlayer
是否已经完成。在循环中添加对 usleep()
的调用。这个每十分之一秒检查一次:
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)
}
结合 Brendan 和 Steve 的回答,关键是 sleep
或 usleep
并将 play 方法放在循环之外以避免加速 CPU。
player?.play({return})
while player!.isPlaying {
sleep(1) // or usleep(10000)
}
最初的 stillGoing
值有效,但还有一个 isPlaying
方法。
.play
需要在括号之间添加一些内容,以避免在完成后永远挂起。
非常感谢。
我正在尝试使用 Apple 的 AVMIDIPlayer
对象来播放 MIDI 文件。在 Swift 中使用以下代码似乎很容易:
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")
}
它播放了大约 0.05 秒。我想我需要在某种循环中构建它。我尝试了一个简单的解决方案:
while stillGoing {
midiPlayer?.play {
let stillGoing = false
}
}
有效,但会大幅提升 CPU。有没有更好的办法? 除了第一条评论,我尝试制作 class,虽然它没有标记任何错误,但它也不起作用。
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)
您需要确保 midiPlayer
对象在播放结束之前一直存在。如果上面的代码只是在一个函数中,midiPlayer
将在函数 returns 时被销毁,因为没有剩余的引用。通常,您会将 midiPlayer
声明为对象的 属性,例如子类控制器。
你已经接近循环了。您只需要给 CPU 时间去做其他事情,而不是不断检查 midiPlayer
是否已经完成。在循环中添加对 usleep()
的调用。这个每十分之一秒检查一次:
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)
}
结合 Brendan 和 Steve 的回答,关键是 sleep
或 usleep
并将 play 方法放在循环之外以避免加速 CPU。
player?.play({return})
while player!.isPlaying {
sleep(1) // or usleep(10000)
}
最初的 stillGoing
值有效,但还有一个 isPlaying
方法。
.play
需要在括号之间添加一些内容,以避免在完成后永远挂起。
非常感谢。