我有一个音频文件,我想使用一些效果(如音高效果)处理,然后将最终结果写入文件.
在处理文件并将其保存到光盘之前,我让用户播放音高效果并实时收听更改.
这是我如何做实时的东西:
let audioSession = AVAudioSession.sharedInstance() audioSession.setCategory(AVAudioSessionCategoryPlayback,error: nil) audioSession.setActive(true,error: nil) audioEngine = AVAudioEngine() audioFile = AVAudioFile(forReading: audioUrl!,error: nil) audioPlayerNode = AVAudioPlayerNode() audioEngine.attachNode(audioPlayerNode) changePitchEffect = AVAudioUnitTimePitch() changePitchEffect.pitch = 1.0 // default audioEngine.attachNode(changePitchEffect) audioEngine.connect(audioPlayerNode,to: changePitchEffect,format: nil) audioEngine.connect(changePitchEffect,to: audioEngine.outputNode,format: nil) let frameCapacity = UInt32(audioFile.length) let buffer = AVAudioPCMBuffer(PCMFormat: audioFile.processingFormat,frameCapacity: frameCapacity) if audioFile.readIntoBuffer(buffer,error: nil) { audioEngine.startAndReturnError(nil) audioPlayerNode.scheduleBuffer(buffer,atTime: nil,options: .Loops,completionHandler: nil) audioPlayerNode.play() // start playing in a loop }
然后使用UiSlider我让用户在循环中聆听音频时更改音高的值.
解决方法
由于在问题的标题中使用AVAudioSession并不是明确的要求,所以有两种可能的答案:
通过节点播放(使用AVAudioSession)
在节点上安装一个水龙头.见AV Foundation Framework Reference.
audioPlayerNode.installTapOnBus(0,bufferSize:frameLength,format: audioInputNode.outputFormatForBus(0),block: {(buffer,time) in let channels = UnsafeArray(start: buffer.floatChannelData,length: Int(buffer.format.channelCount)) let floats = UnsafeArray(start: channels[0],length: Int(buffer.frameLength)) for var i = 0; i < Int(self.audioBuffer.frameLength); i+=Int(self.audioMixerNode.outputFormatForBus(0).channelCount) { // process } })
AVAudioSession tap机制需要播放.更多关于通过@matt在Stack Overflow answer上播放的录音.
使用AudioSessionInitialize初始化AudioSession以播放&记录,设置阅读&写入流,并传递指向您的数据处理代码的AURenderCallbackStruct.但是,这样做不能使您无法使用AVAudioUnitTimePitch.您可以在此How to do realtime recording with effect processing on iOS文章中找到有关此解决方案的更多信息.