swift - 更改AudioQueueBuffer的mAudioData

标签 swift core-audio pcm audiotoolbox

我需要设置 AudioQueueBufferRef 的 mAudioData。我尝试使用 copyMemory:

inBuffer.pointee.copyMemory(from: lastItemOfArray, byteCount: byteCount) // byteCount is 512

但它不起作用。

AudioQueueNewOutput() 队列已正确设置为 Int16 pcm 格式

这是我的代码:

   class CustomObject {
       var pcmInt16DataArray = [UnsafeMutableRawPointer]() // this contains pcmInt16 data
   }
        
   let callback: AudioQueueOutputCallback = { (
       inUserData: UnsafeMutableRawPointer?,
       inAQ: AudioQueueRef,
       inBuffer: AudioQueueBufferRef) in
    
       guard let aqp: CustomObject = inUserData?.bindMemory(to: CustomObject.self, capacity: 1).pointee else { return }
       var numBytes: UInt32 = inBuffer.pointee.mAudioDataBytesCapacity
        
    
       /// Set inBuffer.pointee.mAudioData to pcmInt16DataArray.popLast()
       /// How can I set the mAudioData here??
    
       inBuffer.pointee.mAudioDataByteSize = numBytes
       AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, nil)
    }

来自苹果文档:https://developer.apple.com/documentation/audiotoolbox/audioqueuebuffer?language=objc

mAudioData:

The audio data owned the audio queue buffer. The buffer address cannot be changed.

所以我想解决方案是为同一地址设置一个新值 有谁知道怎么做吗?

更新:

传入的音频格式是以 48kHz 采样的“pcm”信号(Little Endian)。这是我的设置:

var dataFormat = AudioStreamBasicDescription()
dataFormat.mSampleRate = 48000;
dataFormat.mFormatID = kAudioFormatLinearPCM
dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved;
dataFormat.mChannelsPerFrame = 1
dataFormat.mFramesPerPacket = 1
dataFormat.mBitsPerChannel = 16
dataFormat.mBytesPerFrame = 2
dataFormat.mBytesPerPacket = 2

我正在收集传入的数据

var pcmData = [UnsafeMutableRawPointer]()

最佳答案

你已经很接近了!

试试这个:

inBuffer.pointee.mAudioData.copyMemory(from: lastItemOfArray, byteCount: Int(numBytes))

或者这个:

memcpy(inBuffer.pointee.mAudioData, lastItemOfArray, Int(numBytes))

音频队列服务在纯 C 语言时很难使用。现在我们必须做很多桥接才能让 API 与 Swift 一起使用,这真的很痛苦。如果您可以选择,请尝试 AVAudioEngine .


其他一些需要检查的事情:

确保您的 AudioQueue 具有与您在 AudioStreamBasicDescription 中定义的相同格式。

var queue: AudioQueueRef?

// assumes userData has already been initialized and configured
AudioQueueNewOutput(&dataFormat, callBack, &userData, nil, nil, 0, &queue)

确认您已分配并准备好队列的缓冲区。

let numBuffers = 3

// using forced optionals here for brevity
for _ in 0..<numBuffers {
    var buffer: AudioQueueBufferRef?
    if AudioQueueAllocateBuffer(queue!, userData.bufferByteSize, &buffer) == noErr {
        userData.mBuffers.append(buffer!)
        callBack(inUserData: &userData, inAQ: queue!, inBuffer: buffer!)
    }
}

考虑让你的回调成为一个函数。

func callBack(inUserData: UnsafeMutableRawPointer?, inAQ: AudioQueueRef, inBuffer: AudioQueueBufferRef) {

    let numBytes: UInt32 = inBuffer.pointee.mAudioDataBytesCapacity       
    memcpy(inBuffer.pointee.mAudioData, pcmData, Int(numBytes))
    inBuffer.pointee.mAudioDataByteSize = numBytes

    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, nil)

 }

此外,在尝试引入服务器端数据之前,请查看是否可以通过音频队列获取一些基本的 PCM 数据来播放。

var pcmData: [Int16] = []
for i in 0..<frameCount {
    let element = Int16.random(in: Int16.min...Int16.max) // noise
    pcmData.append(Int16(element))

}

关于swift - 更改AudioQueueBuffer的mAudioData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60562570/

相关文章:

ios - Swift:远程命令中心不显示在 lockScreen 中

ios - Opentok黑屏问题

ios - 如何在每次运行应用程序时更改 NSUserDefault 的默认返回值而不保存它

ios - 将 MTAudioProcessingTap 与 AVAssetExportSession 结合使用

c - 混合 16 位线性 PCM 流并避免剪辑/溢出

java - 编码器/解码器 PCM 到 AMR Android

ios - swift iOS 我可以通过哪些方式缓存网络调用

iphone - 使用 AVAssetReader 和 ARC 绘制波形

linux - 用户空间中的 ALSA PCM 播放设备

ios - Swift 3 - 如何将 Int32 的内存转换为四个字符