AVAudioEngine就是爲此而走的路。從蘋果公司的文檔:
- 播放和單軌的記錄,使用AVAudioPlayer和AVAudioRecorder。
- 對於更復雜的音頻處理,請使用AVAudioEngine。 AVAudioEngine包括用於音頻輸入和輸出的AVAudioInputNode和AVAudioOutputNode。您還可以使用處理AVAudioNode對象和混合效果到您的音頻
我會很直接跟你:AVAudioEngine是模糊的文件,很少-有用的錯誤消息極其挑剔的API,幾乎沒有在線代碼示例演示的不僅僅是最基本的任務。 但是如果你花時間來克服小的學習曲線,你可以相對容易地做一些神奇的事情。
我已經建立了一個簡單的「遊樂場」觀點,同時演示了麥克風和音頻文件採樣協同工作控制器:
import UIKit
class AudioEnginePlaygroundViewController: UIViewController {
private var audioEngine: AVAudioEngine!
private var mic: AVAudioInputNode!
private var micTapped = false
override func viewDidLoad() {
super.viewDidLoad()
configureAudioSession()
audioEngine = AVAudioEngine()
mic = audioEngine.inputNode!
}
static func getController() -> AudioEnginePlaygroundViewController {
let me = AudioEnginePlaygroundViewController(nibName: "AudioEnginePlaygroundViewController", bundle: nil)
return me
}
@IBAction func toggleMicTap(_ sender: Any) {
if micTapped {
mic.removeTap(onBus: 0)
micTapped = false
return
}
let micFormat = mic.inputFormat(forBus: 0)
mic.installTap(onBus: 0, bufferSize: 2048, format: micFormat) { (buffer, when) in
let sampleData = UnsafeBufferPointer(start: buffer.floatChannelData![0], count: Int(buffer.frameLength))
}
micTapped = true
startEngine()
}
@IBAction func playAudioFile(_ sender: Any) {
stopAudioPlayback()
let playerNode = AVAudioPlayerNode()
let audioUrl = Bundle.main.url(forResource: "test_audio", withExtension: "wav")!
let audioFile = readableAudioFileFrom(url: audioUrl)
audioEngine.attach(playerNode)
audioEngine.connect(playerNode, to: audioEngine.outputNode, format: audioFile.processingFormat)
startEngine()
playerNode.scheduleFile(audioFile, at: nil) {
playerNode .removeTap(onBus: 0)
}
playerNode.installTap(onBus: 0, bufferSize: 4096, format: playerNode.outputFormat(forBus: 0)) { (buffer, when) in
let sampleData = UnsafeBufferPointer(start: buffer.floatChannelData![0], count: Int(buffer.frameLength))
}
playerNode.play()
}
// MARK: Internal Methods
private func configureAudioSession() {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, with: [.mixWithOthers, .defaultToSpeaker])
try AVAudioSession.sharedInstance().setActive(true)
} catch { }
}
private func readableAudioFileFrom(url: URL) -> AVAudioFile {
var audioFile: AVAudioFile!
do {
try audioFile = AVAudioFile(forReading: url)
} catch { }
return audioFile
}
private func startEngine() {
guard !audioEngine.isRunning else {
return
}
do {
try audioEngine.start()
} catch { }
}
private func stopAudioPlayback() {
audioEngine.stop()
audioEngine.reset()
}
}
音頻樣本通過installTap的完成處理程序給你哪些隨着音頻實時通過輕敲節點(麥克風或音頻文件播放器)而不斷被調用。您可以通過索引我在每個塊中創建的sampleData指針來訪問單個樣本。
你可以先看看蘋果自己的例子。它們可能在Objective-C中,但API沒有改變。 在任何情況下,所有的vDSP_xx函數都有一個C API,並且實際上,您的項目的分析部分可能需要用C或C++編寫(順便說一句,蘋果工程師在今年WWDC上的建議是編寫音頻處理/渲染處理程序)。 至於音頻指紋識別,這是一個不平凡的問題,也是SO的板子。 – marko
你有什麼發現? – hoangpx