使用AVAudioTime调度音频文件以供将来播放

时间:2015-07-24 07:42:08

标签: ios objective-c swift core-audio

我试图弄清楚如何在不久的将来纠正录音。我的实际目标是同步播放多个音轨。

那么如何配置' aTime'这是正确的,所以它从现在开始大约0.3秒。 我想我也许需要hostTime,但我不知道如何正确使用它

func createStartTime() -> AVAudioTime? {
    var time:AVAudioTime?
    if let lastPlayer = self.trackPlayerDictionary[lastPlayerKey] {
        if let sampleRate = lastPlayer.file?.processingFormat.sampleRate {
            var sampleTime = AVAudioFramePosition(shortStartDelay * sampleRate )
            time = AVAudioTime(sampleTime: sampleTime, atRate: sampleRate)
        }
    }
    return time
}

这是我用来开始播放的功能:

func playAtTime(aTime:AVAudioTime?){
    self.startingFrame = AVAudioFramePosition(self.currentTime * self.file!.processingFormat.sampleRate)
    let frameCount = AVAudioFrameCount(self.file!.length - self.startingFrame!)

    self.player.scheduleSegment(self.file!, startingFrame: self.startingFrame!, frameCount: frameCount, atTime: aTime, completionHandler:{ () -> Void in
        NSLog("done playing")//actually done scheduling
    })
    self.player.play()

}

2 个答案:

答案 0 :(得分:1)

我明白了!

对于我在mach_absolute_time()中填充的hostTime参数,这是计算机/ iPad'现在'的时间。 AVAudioTime(hostTime:sampleTime:atRate)将sampleTime添加到hostTime,并在不久的将来返回可用于在同一起始时间安排多个音频片段的时间

func createStartTime() -> AVAudioTime? {

    var time:AVAudioTime?
    if let lastPlayer = self.trackPlayerDictionary[lastPlayerKey] {

        if let sampleRate = lastPlayer.file?.processingFormat.sampleRate {

            var sampleTime = AVAudioFramePosition(shortStartDelay * sampleRate )

            time = AVAudioTime(hostTime: mach_absolute_time(), sampleTime: sampleTime, atRate: sampleRate)
        }
    }
    return time

}

答案 1 :(得分:0)

嗯 - 这是ObjC - 但你明白了......

不需要 mach_absolute_time() - 如果您的引擎正在运行,您已经在AVAudioNode中获得了 @property lastRenderTime - 您的播放器&#39 ; s超类...

AVAudioFormat *outputFormat = [playerA outputFormatForBus:0];

const float kStartDelayTime = 0.0; // seconds - in case you wanna delay the start

AVAudioFramePosition startSampleTime = playerA.lastRenderTime.sampleTime;

AVAudioTime *startTime = [AVAudioTime timeWithSampleTime:(startSampleTime + (kStartDelayTime * outputFormat.sampleRate)) atRate:outputFormat.sampleRate];

[playerA playAtTime: startTime];
[playerB playAtTime: startTime];
[playerC playAtTime: startTime];
[playerD playAtTime: startTime];

[player...

顺便说一下 - 您可以使用AVAudioPlayer类获得相同的100%样本帧精确结果......

NSTimeInterval startDelayTime = 0.0; // seconds - in case you wanna delay the start
NSTimeInterval now = playerA.deviceCurrentTime;

NSTimeInterval startTime = now + startDelayTime;

[playerA playAtTime: startTime];
[playerB playAtTime: startTime];
[playerC playAtTime: startTime];
[playerD playAtTime: startTime];

[player...

如果没有startDelayTime,所有玩家的前100-200毫秒将会被截断,因为启动命令实际上会花费时间进入运行循环,尽管玩家已经开始(好,已经安排)100%同步现在即可。但是使用 startDelayTime = 0.25 ,你很高兴。并且永远不要忘记提前 prepareToPlay 你的玩家,以便在开始时不需要进行额外的缓冲或设置 - 只需启动他们; - )

有关更深入的解释,请查看我在

中的答案

AVAudioEngine multiple AVAudioInputNodes do not play in perfect sync