iOS,通过AudioUnit从48K到16K的音频重采样

iOS,通过AudioUnit从48K到16K的音频重采样,ios,swift,audiounit,audio-converter,Ios,Swift,Audiounit,Audio Converter,我一直在尝试使用AudioUnit或AudioConverterRef对我的实时PCM单声道、48000采样率到16000采样率单声道进行重新采样,但我在这两个方面都没有成功 我查看了以下资源,但没有发现它们有多大帮助 我使用AudioConverterRef的代码是 var inputFormat = CAStreamBasicDescription( sampleRate: Double(Constants.SAMPLE_RATE), nu

我一直在尝试使用AudioUnitAudioConverterRef对我的实时PCM单声道、48000采样率到16000采样率单声道进行重新采样,但我在这两个方面都没有成功

我查看了以下资源,但没有发现它们有多大帮助

我使用AudioConverterRef的代码是

     var inputFormat = CAStreamBasicDescription(
        sampleRate: Double(Constants.SAMPLE_RATE),
        numChannels: 1,
        pcmf: .int16,
        isInterleaved: false
    )
    
    var outputFormat = CAStreamBasicDescription(
        sampleRate: Double(16000),
        numChannels: 1,
        pcmf: .int16,
        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 delegate = unsafeBitCast(inAudioConverter, to: AudioUnitDataChannelCallbackDelegate.self)
线程1:EXC\u错误访问(代码=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
}
func performConversion(ioNumberDataPackets:UnsafeMutablePointer,ioData:UnsafeMutablePointer,outDataPacketDescription:UnsafeMutablePointer?,inUserData:UnsafeMutableRawPointer?->OSStatus{
let retained=inUserData!.AssumingMemoryBind(到:AudioBufferList.self)
让maxPackets=retained.pointee.mBuffers.mDataByteSize/2
如果ioNumberDataPackets.pointee>maxPackets{
ioNumberDataPackets.pointee=maxPackets
}
打印(“正在运行转换…”)
让ioDataPtr=UnsafemutabalAudioBufferListPointer(ioData)
ioDataPtr[0].mData=UnsafemtableRawPointer(inputBufferList?.mBuffers.mData)
ioDataPtr[0]。mDataByteSize=1280
ioDataPtr[0]。mNumberChannels=inputBufferList!.mBuffers.mNumberChannels
打印(“ioDataPtr:\(ioDataPtr[0].mDataByteSize)”)
返回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!,
        conversionAudioController_Callback,
        UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),
        &ioOutputDataPackets,
        &fillBufferList,
        nil
    )

    if status != noErr {
        print("ERROR HERE CONVERSION: \(status)")
    }
    
    print("MONOSAMPLE DATA \(monoSamples.count) and \(ioOutputDataPackets) and \(fillBufferList.mBuffers.mDataByteSize)")
    
    return err
}
func performRecording(\ioActionFlags:Unsafemtablepointer,inTimeStamp:UnsafePointer,inBufNumber:UInt32,inNumberFrames:UInt32,ioData:Unsafemtablepointer)->OSStatus{
打印(“*******************”)
变量err:OSStatus=noErr
err=AudioUnitRender(audioUnit!、ioActionFlags、inTimeStamp、1、inNumberFrames、ioData)
var monoSamples=[Int16]()
让rawAudioPointer=ioData[0].mBuffers.mData?.bindMemory(to:Int16.self,capacity:Int(inNumberFrames))
如果rawAudioPointer==nil{
返回noErr
}
append(contentsOf:UnsafeBufferPointer(start:rawAudioPointer,count:Int(inNumberFrames)))
inputBufferList=ioData.pointee
let outputBuffer=UnsafeMutablePointer.allocate(容量:684)
延迟{outputBuffer.deallocate()}
var fillBufferList=AudioBufferList()
fillBufferList.mNumberBuffers=1
fillBufferList.mBuffers.mNumberChannels=1
fillBufferList.mBuffers.mDataByteSize=684
fillBufferList.mBuffers.mData=UnsafemtableRawPointer(outputBuffer)
var ioOutputDataPackets:UInt32=384
inputBufferList=ioData.pointee
let status=AudioConverterFillComplexBuffer(
转换器48到16!,
conversionAudioController\u回调,
UnsafeMutableRawPointer(Unmanaged.passUnretained(self.toOpaque()),
&ioOutputDataPackets,
&填充列表,
无
)
如果状态!=noErr{
打印(“此处转换错误:\(状态)”)
}
打印(“单样本数据\(monoSamples.count)和\(ioOutputDataPackets)和\(fillBufferList.mBuffers.mDataByteSize)”)
返回错误
}

录制没有问题,但当我的输出与mDataByteSize=684不匹配时,我会在此处得到错误转换:1768846202

您应该在
inUserData
上执行
未安全比特广播
,而不是
inAudioConverter
。是的,我将其更改为inUserData,但现在AudioConverterFillComplexBuffer线程1:EXC_断点(代码=1,子代码=0x1bc238ff4)出现错误。您能否显示
performConversion
并更新问题?我将更新我的问题。我已编辑了我的问题
 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!,
        conversionAudioController_Callback,
        UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),
        &ioOutputDataPackets,
        &fillBufferList,
        nil
    )

    if status != noErr {
        print("ERROR HERE CONVERSION: \(status)")
    }
    
    print("MONOSAMPLE DATA \(monoSamples.count) and \(ioOutputDataPackets) and \(fillBufferList.mBuffers.mDataByteSize)")
    
    return err
}