无法将 [[Float]] 数组传递到 Objective-C++

Can't pass [[Float]] array into Objective-C++

本文关键字:Objective-C++ 数组 Float      更新时间:2023-10-16

我正在处理应用程序内的声音。DSP算法是用C++编写的。我需要将数据传递到C++然后将结果传递到音频子系统中Swift.

为了将数据传递到C++我编写了一个Objective-C++类:

#define BufferSize 10240
@interface EffectsWrapper : NSObject
-   (void) processBuffer: (float * _Nonnull *_Nonnull) dataIn ofSize: (int) dataSize intoOutputBuffer: (float * _Nonnull *_Nonnull) dataOut;
@end
@implementation EffectsWrapper
-   (void) processBuffer: (float * _Nonnull *_Nonnull) dataIn ofSize: (int) dataSize intoOutputBuffer: (float * _Nonnull *_Nonnull) dataOut
{
for(int channel = 0; channel < 2; channel ++)
{
for(int i = 0; i < dataSize; i ++)
{
float data =  dataIn[channel][i];
dataOut[channel][i] = data;
}
}
}
@end

如您所见,现在它只是将输入复制到输出中。

该方法的调用是在闭包MTAudioProcessingTapProcessCallback内完成的,闭包被描述为MyClass的属性。EffectsWrapper也是此类的属性。

为了"处理"数据,首先,我创建输入和输出数组,如下所示:

var dataIn: [[Float]] = Array(repeating: Array(repeating: 0.0, count: framesCount), count: 2)
var dataOut: [[Float]] = Array(repeating: Array(repeating: 0.0, count: framesCount), count: 2)

其次,我用数据填充输入数组。然后我调用EffectsWrapper.process方法如下:

let dataInPtr = UnsafeMutablePointer(mutating: [UnsafeMutablePointer(mutating: dataIn[0]), UnsafeMutablePointer(mutating: dataIn[1])])
let dataOutPtr = UnsafeMutablePointer(mutating: [UnsafeMutablePointer(mutating: dataOut[0]), UnsafeMutablePointer(mutating: dataOut[1])])
myClass.effectsWrapper.processBuffer(dataInPtr, ofSize: Int32(framesCount), intoOutputBuffer: dataOutPtr)

问题是EffectsWrapper里面的数据完全是垃圾。有时它甚至会给我抛出分配错误。我不明白为什么我创建的指针指向内存中的一些随机位置,而不是我需要它们指向的数组元素。

请帮忙。

这里的问题是像这样的代码

let dataInPtr = UnsafeMutablePointer(mutating: [UnsafeMutablePointer(mutating: dataIn[0]), UnsafeMutablePointer(mutating: dataIn[1])])

使用隐式桥接从数组创建UnsafePointer。 这些指针(间接)保存以供以后使用,这是未定义的行为。请参阅 https://developer.apple.com/documentation/swift/unsafepointer 和 https://developer.apple.com/documentation/swift/unsafemutablepointer 中的UnsafePointerUnsafeMutablePointer文档。 如前所述,

通过隐式桥接实例或 数组的元素仅在执行调用期间有效 功能。转义指针以在执行 函数是未定义的行为。特别是,不要使用隐式 调用UnsafePointer初始值设定项时的桥接。

在尝试以有效的方式解决此问题之前,应该探索编写包装器的可能性,即在 Swift 和包装器之间传递的输入或输出缓冲区是内存中所有通道数据连续存储的区域。 这样,缓冲区就不需要被视为指针数组,并且在 Objective-C(++) 和 Swift 之间传递浮点数组更容易。