我尝试使用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 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)
答案 0 :(得分:2)
您需要确保/**
* Font 1
*/
@font-face {
font-family: "Flaticon1";
src: url("flaticon1.eot");
src: url("flaticon1.eot#iefix") format("embedded-opentype"), url("flaticon1.woff") format("woff"), url("flaticon1.ttf") format("truetype"), url("flaticon1.svg") format("svg");
font-weight: normal;
font-style: normal;
}
[class^="flaticon1-"]:before,
[class*=" flaticon1-"]:before,
[class^="flaticon1-"]:after,
[class*=" flaticon1-"]:after {
font-family: "Flaticon1";
font-size: 20px;
font-style: normal;
margin-left: 20px;
}
.flaticon1-basic21:before {
content: "\e000";
}
.flaticon1-bicycle21:before {
content: "\e001";
}
.flaticon1-car6:before {
content: "\e002";
}
/**
* Font 2
*/
@font-face {
font-family: "Flaticon2";
src: url("flaticon2.eot");
src: url("flaticon2.eot#iefix") format("embedded-opentype"), url("flaticon2.woff") format("woff"), url("flaticon2.ttf") format("truetype"), url("flaticon2.svg") format("svg");
font-weight: normal;
font-style: normal;
}
[class^="flaticon2-"]:before,
[class*=" flaticon2-"]:before,
[class^="flaticon2-"]:after,
[class*=" flaticon2-"]:after {
font-family: "Flaticon2";
font-size: 20px;
font-style: normal;
margin-left: 20px;
}
.flaticon2-basic21:before {
content: "\e000";
}
.flaticon2-bicycle21:before {
content: "\e001";
}
.flaticon2-car6:before {
content: "\e002";
}
对象存在,直到完成播放为止。如果上面的代码只在一个函数中,那么当函数返回时,midiPlayer
将被销毁,因为它没有剩余的引用。通常,您会将midiPlayer
声明为对象的属性,如子类控制器。
答案 1 :(得分: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)
}
答案 2 :(得分:0)
结合Brendan和Steve的答案,关键是sleep
或usleep
并将播放方法放在循环外部以避免加速CPU。
player?.play({return})
while player!.isPlaying {
sleep(1) // or usleep(10000)
}
原始stillGoing
值有效,但还有isPlaying
方法。
.play
在括号之间需要一些东西,以避免在完成后永远挂起。
非常感谢。