【问题标题】:How do I turn an array of Float into an AVAudioPCMBuffer?如何将 Float 数组转换为 AVAudioPCMBuffer?
【发布时间】:2022-06-20 07:03:57
【问题描述】:

我有一个Float 数组(代表音频样本),我想把它变成AVAudioPCMBuffer,这样我就可以把它传递给AVAudioFilewrite(from:)。有一个明显的方法(其实一点都不明显,我抄自this gist):

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 中这给了我一个警告 &amp;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 是同一个数字。我做错了什么?

【问题讨论】:

  • 你不想withUnsafeMutableBufferPointer吗?
  • 显然不是:Cannot convert value of type 'UnsafeMutableBufferPointer&lt;Float&gt;' to expected argument type 'UnsafeMutableRawPointer?'(它作为mData 传递到AudioBuffer 构造函数)
  • Objective-C 中的辅助函数可能是一个选项

标签: swift pointers avaudioengine audiobuffer audiobufferlist


【解决方案1】:

这个解决方案有点老套,但应该可以:

@implementation AVAudioFile (FloatArrayWriting)

- (BOOL)writeFloatArray:(const float *)data count:(NSInteger)count format:(AVAudioFormat *)format error:(NSError **)error
{
    NSCParameterAssert(data != NULL);
    NSCParameterAssert(count >= 0);
    NSCParameterAssert(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 中实现该方法,您可以避开 Swift 中 AVFAudio 所需的指针体操。

【讨论】:

    猜你喜欢
    • 2014-06-28
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    相关资源
    最近更新 更多