2017-04-25 56 views
0

我正尝试使用Apple的AVMIDIPlayer对象来播放MIDI文件。在Swift中看起来很容易,使用下面的代码:如何保持AVMIDIPlayer播放?

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

回答

1

你很接近你的循环。你只需要给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) 
} 
1

您需要确保midiPlayer对象存在,直到它完成播放。如果上面的代码只是一个函数,当函数返回时midiPlayer将被销毁,因为没有剩余的引用。通常,您会声明midiPlayer作为对象的属性,例如子类控制器。

+0

所以我不得不用这个代码创建一个类作为函数/方法,然后创建一个类的实例并调用方法? 到目前为止,这只是一个CLI脚本,所以没有UI控制器。 – benwiggy

+1

好吧,在这种情况下,使用循环是唯一的出路。在while循环中放置一个'sleep(1)'调用,这样它就不会占用你所有的CPU时间。另外,我很确定你需要将'midiPlayer?.play'调用移出while循环。 –

0

结合Brendan和史蒂夫的答案,关键是sleepusleep,坚持外循环播放方式,以避免转速的CPU。

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

原来stillGoing价值的作品,但也有一个isPlaying方法。

.play需要在其括号之间的东西,以避免完成后永远挂起。

非常感谢。

相关问题