我已經創建了一個模擬此問題的項目。它所做的只是錄製音頻,將其轉換爲數據,將其轉換回AVAudioPCMBuffer並播放音頻。
這裏是鏈接: https://github.com/Lkember/IntercomTest
有崩潰使用2個頻道的設備時,但我已經固定它。
我一直在尋找的答案,這個問題現在大約一個月左右,所以任何幫助表示讚賞!
我正在使用AVAudioEngine錄製音頻。該音頻是使用自來水記錄:
localInput?.installTap(onBus: 0, bufferSize: 4096, format: localInputFormat) {
據記載鍵入AVAudioPCMBuffer。它需要被轉換爲類型[UINT8]
我用此方法這樣做:
func audioBufferToBytes(audioBuffer: AVAudioPCMBuffer) -> [UInt8] {
let srcLeft = audioBuffer.floatChannelData![0]
let bytesPerFrame = audioBuffer.format.streamDescription.pointee.mBytesPerFrame
let numBytes = Int(bytesPerFrame * audioBuffer.frameLength)
// initialize bytes by 0
var audioByteArray = [UInt8](repeating: 0, count: numBytes)
srcLeft.withMemoryRebound(to: UInt8.self, capacity: numBytes) { srcByteData in
audioByteArray.withUnsafeMutableBufferPointer {
$0.baseAddress!.initialize(from: srcByteData, count: numBytes)
}
}
return audioByteArray
}
音頻然後被寫入到輸出流。在另一臺設備上,需要將數據轉換回AVAudioPCMBuffer以便播放。我用這個方法:
func bytesToAudioBuffer(_ buf: [UInt8]) -> AVAudioPCMBuffer {
let fmt = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: true)
let frameLength = UInt32(buf.count)/fmt.streamDescription.pointee.mBytesPerFrame
let audioBuffer = AVAudioPCMBuffer(pcmFormat: fmt, frameCapacity: frameLength)
audioBuffer.frameLength = frameLength
let dstLeft = audioBuffer.floatChannelData![0]
buf.withUnsafeBufferPointer {
let src = UnsafeRawPointer($0.baseAddress!).bindMemory(to: Float.self, capacity: Int(frameLength))
dstLeft.initialize(from: src, count: Int(frameLength))
}
return audioBuffer
}
但是,一定是因爲設備上有毛病我的邏輯,當我播放音頻,我聽到的東西,但它只是聽起來像靜態的。
任何幫助表示讚賞,正如我所說,我一直在這個問題上停留了一段時間。
編輯:
感謝您的幫助迄今。我已切換到使用數據。所以我的轉換看起來像這樣(我發現這個代碼在線):
func audioBufferToData(audioBuffer: AVAudioPCMBuffer) -> Data {
let channelCount = 1
let bufferLength = (audioBuffer.frameCapacity * audioBuffer.format.streamDescription.pointee.mBytesPerFrame)
let channels = UnsafeBufferPointer(start: audioBuffer.floatChannelData, count: channelCount)
let data = Data(bytes: channels[0], count: Int(bufferLength))
return data
}
和轉換回AVAudioPCMBuffer看起來是這樣的:
func dataToAudioBuffer(data: Data) -> AVAudioPCMBuffer {
let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false)
let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: UInt32(data.count)/2)
audioBuffer.frameLength = audioBuffer.frameCapacity
for i in 0..<data.count/2 {
audioBuffer.floatChannelData?.pointee[i] = Float(Int16(data[i*2+1]) << 8 | Int16(data[i*2]))/Float(INT16_MAX)
}
return audioBuffer
}
不幸的是,同樣的問題依然存在......
編輯4:
提交的答案,在我的樣本項目的問題,H但它並沒有解決我的主要項目中的問題。我這裏補充一個新的問題:
How to send NSData over an OutputStream
這並沒有完全解決我的問題(它在示例項目中做過),但問題仍然存在於我的主項目中。 – Kember
嗨,希望你能幫助我...你有任何使用多路連接的流式麥克風語音樣本 –
@saurabh我沒有樣本,但過去我做過。只需使用AVAudioEngine對象錄製音頻,並使用上述公式將緩衝區轉換爲NSData,然後再傳輸該NSData。然後在其他設備上使用上述功能將其轉換回緩衝區,然後使用AVAudioPlayer播放該緩衝區。 – Logan