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

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

我一直在尝试使用 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),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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?