[英]iOS Swift playing audio (aac) from network stream
我正在開發一個iOS應用程序,我對iOS開發很新。 到目前為止,我已經使用VideoToolbox從網絡流中實現了h264解碼器,這非常困難。 現在我需要播放來自網絡的音頻流,但不涉及文件,只需從套接字直接讀取原始AAC流。 此流來自ffmpeg實例的輸出。 問題是我不知道如何從這開始,似乎關於這個主題的信息很少。 我已經嘗試過AVAudioPlayer
但發現只是沉默。 我想我首先需要解壓縮流中的數據包,就像使用h264解碼器一樣。
我一直在嘗試使用AVAudioEngine
和AVAudioPlayerNode
但沒有成功,與AVAudioPlayer
相同。 有人可以給我一些指導嗎? 也許AudioToolbox
? AudioQueue
?
非常感謝你的幫助 :)
編輯:我正在玩AVAudioCompressedBuffer
,使用AVAudioEngine
和AVAudioNode
沒有錯誤。 但是,我不知道這個輸出意味着什么:
inBuffer: <AVAudioCompressedBuffer@0x6040004039f0: 0/1024 bytes>
這是否意味着緩沖區為空? 我一直試圖以幾種方式提供這個緩沖區,但總是返回類似0/1024的東西。 我想我做得不對:
compressedBuffer.mutableAudioBufferList.pointee = audioBufferList
任何的想法?
謝謝!
編輯2:我正在編輯以反映我的代碼以解壓縮緩沖區。 也許有人可以指出我正確的方向。 注意:由此函數攝取的數據包實際上是在沒有ADTS標頭(9字節)的情況下傳遞的,但我也嘗試使用標頭傳遞它。
func decodeCompressedPacket(packet: Data) -> AVAudioPCMBuffer {
var packetCopy = packet
var streamDescription: AudioStreamBasicDescription = AudioStreamBasicDescription.init(mSampleRate: 44100, mFormatID: kAudioFormatMPEG4AAC, mFormatFlags: UInt32(MPEG4ObjectID.AAC_LC.rawValue), mBytesPerPacket: 0, mFramesPerPacket: 1024, mBytesPerFrame: 0, mChannelsPerFrame: 1, mBitsPerChannel: 0, mReserved: 0)
let audioFormat = AVAudioFormat.init(streamDescription: &streamDescription)
let compressedBuffer = AVAudioCompressedBuffer.init(format: audioFormat!, packetCapacity: 1, maximumPacketSize: 1024)
print("packetCopy count: \(packetCopy.count)")
var audioBuffer: AudioBuffer = AudioBuffer.init(mNumberChannels: 1, mDataByteSize: UInt32(packetCopy.count), mData: &packetCopy)
var audioBufferList: AudioBufferList = AudioBufferList.init(mNumberBuffers: 1, mBuffers: audioBuffer)
var mNumberBuffers = 1
var packetSize = packetCopy.count
// memcpy(&compressedBuffer.mutableAudioBufferList[0].mBuffers, &audioBuffer, MemoryLayout<AudioBuffer>.size)
// memcpy(&compressedBuffer.mutableAudioBufferList[0].mBuffers.mDataByteSize, &packetSize, MemoryLayout<Int>.size)
// memcpy(&compressedBuffer.mutableAudioBufferList[0].mNumberBuffers, &mNumberBuffers, MemoryLayout<UInt32>.size)
// compressedBuffer.mutableAudioBufferList.pointee = audioBufferList
var bufferPointer = compressedBuffer.data
for byte in packetCopy {
memset(compressedBuffer.mutableAudioBufferList[0].mBuffers.mData, Int32(byte), MemoryLayout<UInt8>.size)
}
print("mBuffers: \(compressedBuffer.audioBufferList[0].mBuffers.mNumberChannels)")
print("mBuffers: \(compressedBuffer.audioBufferList[0].mBuffers.mDataByteSize)")
print("mBuffers: \(compressedBuffer.audioBufferList[0].mBuffers.mData)")
var uncompressedBuffer = uncompress(inBuffer: compressedBuffer)
print("uncompressedBuffer: \(uncompressedBuffer)")
return uncompressedBuffer
}
因此,您認為您(很可能)需要解壓縮從流中接收的數據包。 我們的想法是將它們轉換為原始PCM格式,以便將其直接發送到音頻輸出。 這樣,您還可以將任何您想要的DSP /音頻操作應用於音頻流。
正如您所提到的,您可能需要查看AudioQueue
方向,Apple Docs提供實時流式傳輸音頻的良好示例,盡管這是obj-c(在這種情況下我認為攜帶它可能是個好主意)這個在obj-c)。 這可能是開始的最佳場所(將obj-c連接到swift非常簡單 )。
再看看它在Swift中有AVAudioCompressedBuffer類似乎可以為你的情況處理AAC(如果你讓它工作就不需要解碼AAC),但是沒有直接的方法來設置緩沖區,因為它是用於我相信,只是一個存儲容器。 這是一個使用AVAudioCompressedBuffer和AVAudioFile的人的一個工作示例(也許你可以將所有內容緩沖到后台線程中的文件中?我認為這將是過多的IO開銷)。
但是,如果解決這個OBJ中-C有一個崗位上如何設置AVAudioPCMBuffer(可能與AVAudioCompressedBuffer工作?)直接通過memset
(那種digusting但在同一時間,可愛的如同一個嵌入式程序員自己)。
// make a silent stereo buffer
AVAudioChannelLayout *chLayout = [[AVAudioChannelLayout alloc] initWithLayoutTag:kAudioChannelLayoutTag_Stereo];
AVAudioFormat *chFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
sampleRate:44100.0
interleaved:NO
channelLayout:chLayout];
AVAudioPCMBuffer *thePCMBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:chFormat frameCapacity:1024];
thePCMBuffer.frameLength = thePCMBuffer.frameCapacity;
for (AVAudioChannelCount ch = 0; ch < chFormat.channelCount; ++ch) {
memset(thePCMBuffer.floatChannelData[ch], 0, thePCMBuffer.frameLength * chFormat.streamDescription->mBytesPerFrame);
}
我知道這是一個很好的選擇,似乎不是一個簡單的解決方案,但我認為obj-c AudioQueue
技術將是我的第一站!
希望這可以幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.