所以我正在尝试使用AVAudioPlayer创建一个小型音频采样器乐器类。我的乐器需要复音,这意味着我可以互相叠加多个样本。
但是,我在使用AVAudioPlayer在结束前多次播放相同的样本时遇到了一些麻烦。我很好奇是否有另一种方法可以获得复调音。
这是项目:
节拍器课程
class TMetronome: NSObject {
// MARK: - Variables
var bpm: Int!
private var timer: NSTimer?
private var lastFire: NSTimeInterval = NSDate.timeIntervalSinceReferenceDate()
var perc: TPercussion? = nil
var time: TimeSignature? = nil
var ticks = 0
var pattern: TPattern?
// MARK: - Initializers
convenience init(bpm: Int, timeSignature: TimeSignature) {
self.init()
self.bpm = bpm
self.perc = TPercussion()
self.time = timeSignature
generatePattern()
}
// MARK: - BPM Functions
func setBPM(bpm: Int) {
self.pattern?.bpm = bpm
self.bpm = bpm
generatePattern()
}
func setTime(time: TimeSignature) {
self.time = time
generatePattern()
}
func generatePattern() {
var p: [PatternEvent] = []
for i in 1...time!.upper*2 {
switch i % time!.upper {
case 1:
p.append(.kick)
case (time!.upper/2)+1:
p.append(.snare)
default:
p.append(.closedHiHat)
}
}
self.pattern = TPattern(p, bpm: bpm, time: time!)
}
// MARK: - Metronome Timing
func start() {
timer = NSTimer(timeInterval: 0.001, target: self, selector: "frame", userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(timer!, forMode: NSRunLoopCommonModes)
}
@objc private func frame() {
let clock = NSDate.timeIntervalSinceReferenceDate()
let difference = clock-self.lastFire
if difference >= pattern!.resolution {
lastFire = NSDate.timeIntervalSinceReferenceDate()
perc!.playSound(pattern!.next())
}
++ticks
}
}
我的打击乐对象:
class TPercussion: NSObject {
var audioPlayer = AVAudioPlayer()
var kit: DrumKit? = nil
var instrument: MIDISampler = MIDISampler()
override init() {
super.init()
// create our kits
kit = DrumKit(name: "BasicKit", tick: "tick1", tock: "tick2", kick: "kick1", snare: "snare1", openHiHat: "hihatOP", closedHiHat: "hihatCL")
}
var patterns: [String:[Int]]? = nil
func playSound(sound: PatternEvent) {
if kit!.players[sound]!.playing {
println("playing! gotta pause...")
kit!.players[sound]!.pause()
}
kit!.players[sound]!.currentTime = NSTimeInterval(0)
kit!.players[sound]!.play()
}
}
未列出的对象并不是非常复杂,只是一些基本结构。 这是DrumKit结构中唯一的半相关内容,它在初始化套件时逐个初始化声音。
for sound in sounds {
let path = NSURL(fileURLWithPath: NSBundle(forClass: TPercussion.classForCoder()).pathForResource(sound.filename, ofType: "caf")!)
println("preparing \(path)")
var player = AVAudioPlayer(contentsOfURL: path!, error: nil)
player.prepareToPlay()
players[sound.event] = player
}
该应用程序按预期工作,除非我将BPM设置为更高的值。一旦相同的声音在音频文件结束之前第二次开始播放,它就会产生这种奇怪的效果,听起来它正在跳过其他所有音符。我想象这是因为AVAudioPlayer类设置为单声道。
我尝试的另一个解决方案是使用exs乐器而不是创建我自己的示例引擎。我得到它来加载和播放乐器,但由于某种原因我的exs文件没有找到示例文件。它会加载采样器并说无法加载kick1.wav或snare1.wav。不确定我是否导出了我的前任错误。