AVAudioPlayer复音

时间:2015-02-22 17:41:15

标签: ios swift avaudioplayer

所以我正在尝试使用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。不确定我是否导出了我的前任错误。

0 个答案:

没有答案