我正在尝试在快速的AVFoundations中混合两个音频文件。我有一个混合两个音频并同时播放的解决方案。我真正想要的是在一段时间后开始播放第二个音频。例如,播放音频1,然后在10(给定时间)秒后开始播放第二音频。任何帮助表示赞赏。预先感谢。
private var audioFiles: Array<String>
private var audioEngine: AVAudioEngine = AVAudioEngine()
private var mixer: AVAudioMixerNode = AVAudioMixerNode()
func Play() {
// do work in a background thread
DispatchQueue.global(qos: .background).async {
self.audioEngine.attach(self.mixer)
self.audioEngine.connect(self.mixer, to: self.audioEngine.outputNode, format: nil)
// !important - start the engine *before* setting up the player nodes
try! self.audioEngine.start()
let fileManager = FileManager.default
for audioFile in self.audioFiles {
// Create and attach the audioPlayer node for this file
let audioPlayer = AVAudioPlayerNode()
self.audioEngine.attach(audioPlayer)
// Notice the output is the mixer in this case
self.audioEngine.connect(audioPlayer, to: self.mixer, format: nil)
let fileUrl = NSURL.init(fileURLWithPath: fileName.removingPercentEncoding!)
var file : AVAudioFile
// We should probably check if the file exists here ¯\_(ツ)_/¯
try! AVAudioFile.init(forReading: fileUrl.absoluteURL!)
audioPlayer.scheduleFile(file, at: nil, completionHandler: nil)
audioPlayer.play(at: nil)
}
}
}
答案 0 :(得分:3)
您应该使用scheduleSegment。
func scheduleWithOffset(_ offset: TimeInterval) {
let samplerate1 = file1.processingFormat.sampleRate
player1.scheduleSegment(file1,
startingFrame: 0,
frameCount: AVAudioFrameCount(file1.length),
at: AVAudioTime(sampleTime: 0, atRate: samplerate1))
let samplerate2 = file2.processingFormat.sampleRate
player2.scheduleSegment(file2,
startingFrame: 0,
frameCount: AVAudioFrameCount(file2.length),
at: AVAudioTime(sampleTime: AVAudioFramePosition(offset * samplerate2), atRate: samplerate2))
//This can take an indeterminate amount of time, so both files should be prepared before either starts.
player1.prepare(withFrameCount: 8192)
player2.prepare(withFrameCount: 8192)
// Start the files at common time slightly in the future to ensure a synchronous start.
let hostTimeNow = mach_absolute_time()
let hostTimeFuture = hostTimeNow + AVAudioTime.hostTime(forSeconds: 0.2);
let startTime = AVAudioTime(hostTime: hostTimeFuture)
player1.play(at: startTime)
player2.play(at: startTime)
}
答案 1 :(得分:1)
我个人没有使用AVAudioEngine
或AVAudioMixerNode
的经验,但是,您可以使用Timer
进行此操作。
您当前拥有audioPlayer.play(at: nil)
,但是,在建立该玩家后,此权限将始终立即播放。我会做或尝试做的是为此应用某种计时器。
var timeAfter = 10
var timer = NSTimer.scheduledTimerWithInterval(timeAfter, target: self, selector: #selector(playAudio), userInfo: audioPlayer, repeats: false)
将替换
audioPlayer.play(at: nil)
然后,您将添加计时器功能以播放音频。
func playAudio(timer:NSTimer){
var audioPlayer = timer.userInfo as AVAudioPlayerNode
audioPlayer.play()
}
答案 2 :(得分:1)
您可以将另一个playerNode添加到混音器,然后在延迟后播放,如下所示:
let audioPlayer2 = AVAudioPlayerNode()
self.audioEngine.attach(audioPlayer2)
self.audioEngine.connect(audioPlayer2, to: self.mixer, format: nil)
var file2 : AVAudioFile = try! AVAudioFile.init(forReading: fileUrl2!)
func delayTime(_ delayTime : TimeInterval) -> AVAudioTime{
let outputFormat = audioPlayer2.outputFormat(forBus: 0)
let startSampleTime = (audioPlayer2.lastRenderTime ?? AVAudioTime()).sampleTime + Int64(Double(delayTime) * outputFormat.sampleRate);
return AVAudioTime(sampleTime: startSampleTime, atRate: outputFormat.sampleRate)
}
audioPlayer2.scheduleFile(file2, at: nil, completionHandler: nil)
audioPlayer2.play(at: delayTime(3.0))
您还可以在node2和混频器之间挂接sampleDelay AU。这样一来,无需手动编程即可轻松完成工作。