如何将Float数组转换为AVAudioPCMBuffer?



我有一个Float数组(代表音频样本),我想把它变成一个AVAudioPCMBuffer,这样我就可以把它传递给AVAudioFilewrite(from:)。有一个明显的方法(实际上根本不明显,我从这个要点中抄袭了它):

var floats: [Float] = ... // this comes from somewhere else
let audioBuffer = AudioBuffer(mNumberChannels: 1, mDataByteSize: UInt32(floats.count * MemoryLayout<Float>.size), mData: &floats)
var bufferList = AudioBufferList(mNumberBuffers: 1, mBuffers: audioBuffer)
let outputAudioBuffer = AVAudioPCMBuffer(pcmFormat: buffer.format, bufferListNoCopy: &bufferList)!
try self.renderedAudioFile?.write(from: outputAudioBuffer)

这工作(我得到我期望的音频输出),但在Xcode 13.4.1这给了我一个警告在&floats:Cannot use inout expression here; argument 'mData' must be a pointer that outlives the call to 'init(mNumberChannels:mDataByteSize:mData:)'

var floats: [Float] = ... // this comes from somewhere else
try withUnsafeMutablePointer(to: &floats) { bytes in
let audioBuffer = AudioBuffer(mNumberChannels: 1, mDataByteSize: UInt32(bytes.pointee.count * MemoryLayout<Float>.size), mData: bytes)
var bufferList = AudioBufferList(mNumberBuffers: 1, mBuffers: audioBuffer)
let outputAudioBuffer = AVAudioPCMBuffer(pcmFormat: buffer.format, bufferListNoCopy: &bufferList)!
try self.renderedAudioFile?.write(from: outputAudioBuffer)
}

警告消失了,但现在输出是垃圾。我真的不明白这个,因为floats.countbytes.pointee.count是相同的数字。我做错了什么?

这个解决方案有点粗糙,但应该可以工作:

@implementation AVAudioFile (FloatArrayWriting)
- (BOOL)writeFloatArray:(const float *)data count:(NSInteger)count format:(AVAudioFormat *)format error:(NSError **)error
{
NSParameterAssert(data != NULL);
NSParameterAssert(count >= 0);
NSParameterAssert(format != nil);
AudioBufferList abl;
abl.mNumberBuffers = 1;
abl.mBuffers[0].mData = (void *)data;
abl.mBuffers[0].mNumberChannels = 1;
abl.mBuffers[0].mDataByteSize = count * sizeof(float);
AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:format bufferListNoCopy:&abl deallocator:NULL];
return [self writeFromBuffer:buffer error:error];
}
@end

通过在Objective-C中实现这个方法,你可以避免AVFAudio在Swift中需要的指针体操。

这是一个可能的Swift解决方案:

try floats.withUnsafeMutableBufferPointer { umrbp in
let audioBuffer = AudioBuffer(mNumberChannels: 1, mDataByteSize: UInt32(umrbp.count * MemoryLayout<Float>.size), mData: umrbp.baseAddress)
var bufferList = AudioBufferList(mNumberBuffers: 1, mBuffers: audioBuffer)
let outputAudioBuffer = AVAudioPCMBuffer(pcmFormat: buffer.format, bufferListNoCopy: &bufferList)!
try self.renderedAudioFile?.write(from: outputAudioBuffer)
}

相关内容

  • 没有找到相关文章

最新更新