如何解决iOS,通过 AudioUnit 从 48K 到 16K 的音频重采样
我一直在尝试使用 AudioUnit 或 AudioConverterRef 将我的实时 PCM 单声道、48000 采样率重新采样到 16000 采样率单声道,但我在两者上都没有成功其中。
我查看了以下资源,但没有发现它们有多大帮助。
- https://developer.apple.com/forums/thread/70694
- iOS: How to resample audio(PCM data) using Audio Unit at runtime?
- iOS convert audio sample rate from 16 kHz to 8 kHz
var inputFormat = CAStreamBasicDescription(
sampleRate: Double(Constants.SAMPLE_RATE),numChannels: 1,pcmf: .int16,isInterleaved: false
)
var outputFormat = CAStreamBasicDescription(
sampleRate: Double(16000),isInterleaved: false
)
status = AudioConverterNew(
&inputFormat!,&outputFormat!,&converter48To16
)
if status != noErr {
print("ERROR HERE: \(status)")
}
let outputBytes = outputFormat!.mBytesPerPacket * (640 * 1280 / inputFormat!.mBytesPerPacket)
let outputBuffer = UnsafeMutablePointer<CChar>.allocate(capacity: Int(outputBytes))
defer { outputBuffer.deallocate() }
var outputBufferList = audiobufferlist()
outputBufferList.mNumberBuffers = 1
outputBufferList.mBuffers.mNumberChannels = 1
outputBufferList.mBuffers.mDataByteSize = outputBytes
outputBufferList.mBuffers.mData = UnsafeMutableRawPointer(outputBuffer)
var outputDataPacketSize = outputBytes / outputFormat!.mBytesPerPacket
status = AudioConverterFillComplexBuffer(
converter48To16!,conversionAudioController_Callback,UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),&outputDataPacketSize,&outputBufferList,nil
)
if status != noErr {
print("ERROR HERE: \(status)")
}
并且回调是
let conversionAudioController_Callback: AudioConverterComplexInputDataProc = {(
inAudioConverter,ioNumberDataPackets,ioData,outDataPacketDescription,inUserData) -> Osstatus in
let delegate = unsafeBitCast(inAudioConverter,to: AudioUnitDataChannelCallbackDelegate.self)
let result = delegate.performConversion(
ioNumberDataPackets: ioNumberDataPackets,ioData: ioData,outDataPacketDescription: outDataPacketDescription,inUserData: inUserData
)
return noErr
}
let delegate = unsafeBitCast(inAudioConverter,to: AudioUnitDataChannelCallbackDelegate.self)
线程 1:EXC_BAD_ACCESS(代码=1,地址=0xdbd000)
我在设置属性时没有遇到任何问题,但仅在实际执行代码时收到错误。
我目前正在以 48000 采样率录制 PCM 16 位单声道并尝试将其下采样到 16000
问题已更新:
func performConversion(ioNumberDataPackets: UnsafeMutablePointer<UInt32>,ioData: UnsafeMutablePointer<audiobufferlist>,outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>?>?,inUserData: UnsafeMutableRawPointer?) -> Osstatus {
let retained = inUserData!.assumingMemoryBound(to: audiobufferlist.self)
let maxPackets = retained.pointee.mBuffers.mDataByteSize / 2
if ioNumberDataPackets.pointee > maxPackets {
ioNumberDataPackets.pointee = maxPackets
}
print("CONVERSION RUNNING...")
let ioDataPtr = UnsafeMutableaudiobufferlistPointer(ioData)
ioDataPtr[0].mData = UnsafeMutableRawPointer(inputBufferList?.mBuffers.mData)
ioDataPtr[0].mDataByteSize = 1280
ioDataPtr[0].mNumberChannels = inputBufferList!.mBuffers.mNumberChannels
print("ioDataPtr: \(ioDataPtr[0].mDataByteSize)")
return noErr
}
**************问题已编辑:************
记录数据和下采样 48K 到 16K。
func performRecording(_ ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,inTimeStamp: UnsafePointer<AudioTimeStamp>,inBufNumber: UInt32,inNumberFrames: UInt32,ioData: UnsafeMutablePointer<audiobufferlist>) -> Osstatus {
print("*******************")
var err: Osstatus = noErr
err = AudioUnitRender(audioUnit!,ioActionFlags,inTimeStamp,1,inNumberFrames,ioData)
var monoSamples = [Int16]()
let rawAudioPointer = ioData[0].mBuffers.mData?.bindMemory(to: Int16.self,capacity: Int(inNumberFrames))
if rawAudioPointer == nil {
return noErr
}
monoSamples.append(contentsOf: UnsafeBufferPointer(start: rawAudioPointer,count: Int(inNumberFrames)))
inputBufferList = ioData.pointee
let outputBuffer = UnsafeMutablePointer<CChar>.allocate(capacity: 684)
defer { outputBuffer.deallocate() }
var fillBufferList = audiobufferlist()
fillBufferList.mNumberBuffers = 1
fillBufferList.mBuffers.mNumberChannels = 1
fillBufferList.mBuffers.mDataByteSize = 684
fillBufferList.mBuffers.mData = UnsafeMutableRawPointer(outputBuffer)
var ioOutputDataPackets: UInt32 = 384
inputBufferList = ioData.pointee
let status = AudioConverterFillComplexBuffer(
converter48To16!,&ioOutputDataPackets,&fillBufferList,nil
)
if status != noErr {
print("ERROR HERE CONVERSION: \(status)")
}
print("MONOSAMPLE DATA \(monoSamples.count) and \(ioOutputDataPackets) and \(fillBufferList.mBuffers.mDataByteSize)")
return err
}
录制没有问题,但是当我的输出与 mDataByteSize = 684 不匹配时,我收到 ERROR HERE CONVERSION: 1768846202
的错误版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。