7

我在 C 中有以下代码,它分配了具有适当长度的 AudioBufferList。

  UInt32 bufferSizeBytes = bufferSizeFrames * sizeof(Float32);
  propertySize = offsetof(AudioBufferList, mBuffers[0]) + (sizeof(AudioBuffer) * mRecordSBD.mChannelsPerFrame);

  mBufferList = (AudioBufferList *) malloc(propertySize);
  mBufferList->mNumberBuffers = mRecordSBD.mChannelsPerFrame;
  for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i)
  {
    mBufferList->mBuffers[i].mNumberChannels = 1;
    mBufferList->mBuffers[i].mDataByteSize = bufferSizeBytes;
    mBufferList->mBuffers[i].mData = malloc(bufferSizeBytes);
  }

大多数时候,mChannelsPerFrame是 2,所以上面的代码创建了两个缓冲区,每个通道一个。每个缓冲区都有一个保留的内存值bufferSizeBytes

如何在 Swift 中复制相同的行为?

4

2 回答 2

8

不幸的是,在 Swift 中,C 数组被视为一个元组,因此 AudioBufferList.mBuffers 被导入一个带有单个 AudioBuffer 的元组。C 允许您通过使用指针数学(或本例中的数组下标)来访问相邻内存以创建可变长度结构,而 Swift 没有。

AudioBufferList 只是普通的并不能很好地转换为 Swift。Apple 已经通过一些辅助函数和类型缓解了这个问题。他们创建了一个静态分配函数,该函数返回一个UnsafeMutableAudioBufferListPointer,这是一种特殊类型,其中下标返回音频缓冲区。

let bufferSizeBytes = MemoryLayout<Float>.size * 1234

var bufferlist = AudioBufferList.allocate(maximumBuffers: 2)
bufferlist[0] = AudioBuffer(mNumberChannels: 1,
                            mDataByteSize: UInt32(bufferSizeBytes),
                            mData: malloc(bufferSizeBytes))
bufferlist[1] = AudioBuffer(mNumberChannels: 1,
                            mDataByteSize: UInt32(bufferSizeBytes),
                            mData: malloc(bufferSizeBytes))

// Free your buffers and the pointer when you're done.
for buffer in bufferlist {
    free(buffer.mData)
}
free(&bufferlist)
于 2018-03-08T06:49:18.130 回答
0

您可以使用 Core Audio API 为 2 个交错流创建带有 2 个缓冲区的 AudioBufferList:

import AudioUnit
import AVFoundation

var myBufferList = AudioBufferList(
              mNumberBuffers: 2,
              mBuffers: AudioBuffer(
                  mNumberChannels: UInt32(2),
                  mDataByteSize: myBufferSizeBytes,
                  mData: nil) )
于 2018-03-06T17:19:05.433 回答