草庐IT

ios - AVAudioConverter float32/48khz -> int16/16khz 转换失败

coder 2023-09-04 原文

此方法处理来自 AVAudioEngine 输入节点上 installTap 的回调。我已确认我正在获取单声道 float32/48000hz 缓冲区数据,我想将其转换为单声道 int16/16000hz。

var converter: AVAudioConverter? = nil
var convertBuffer: AVAudioPCMBuffer? = nil
let targetFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: 16000, channels: 1, interleaved: false)

func recordCallback(buffer: AVAudioPCMBuffer, time: AVAudioTime) {
    if converter == nil {
        convertBuffer = AVAudioPCMBuffer(pcmFormat: targetFormat, frameCapacity: buffer.frameCapacity)
        convertBuffer?.frameLength = convertBuffer!.frameCapacity
        converter = AVAudioConverter(from: buffer.format, to: convertBuffer!.format)
        converter?.sampleRateConverterAlgorithm = AVSampleRateConverterAlgorithm_Normal
        converter?.sampleRateConverterQuality = .max
    }

    guard let convertBuffer = convertBuffer else { return }

    log.info("Converter: \(self.converter!)")
    log.info("Converter buffer: \(self.convertBuffer!)")
    log.info("Converter buffer format: \(self.convertBuffer!.format)")
    log.info("Source buffer: \(buffer)")
    log.info("Source buffer format: \(buffer.format)")

    do {
        try converter!.convert(to: convertBuffer, from: buffer)
    } catch let error {
        log.error("Conversion error: \(error)")
        observer?.onError(EngineRecordTaskError.ConversionError(error: error))
        return
    }

    …
}

这给了我有用的错误:

Conversion error: Error Domain=NSOSStatusErrorDomain Code=-50 "(null)"

如果我使用替代方法 .convert(to:error:withInputFrom:),它不会填充 NSError,也不会填充目标缓冲区 - 静默失败。

记录的信息:

Converter: <AVAudioConverter: 0x17001cd40>
Converter buffer: <AVAudioPCMBuffer@0x17021e310: 9600/9600 bytes>
Converter buffer format: <AVAudioFormat 0x17448ba90:  1 ch,  16000 Hz, Int16>
Source buffer: <AVAudioPCMBuffer@0x17021e1b0: 19200/19200 bytes>
Source buffer format: <AVAudioFormat 0x174480910:  1 ch,  48000 Hz, Float32>
Conversion error: Error Domain=NSOSStatusErrorDomain Code=-50 "(null)"

来自调试器的附加信息:

(lldb) po buffer.frameCapacity
4800

(lldb) po convertBuffer.frameCapacity
4800

(lldb) po buffer.frameLength
4800

(lldb) po convertBuffer.frameLength
4800

这是我尝试过的替代转换代码:

    var conversionError: NSError? = nil
    converter!.convert(to: convertBuffer, error: &conversionError, withInputFrom: { (_, _) in
        return buffer
    })

    if let conversionError = conversionError {
        log.error("Conversion error: \(conversionError)")
        observer?.onError(EngineRecordTaskError.ConversionError(error: conversionError))
        return
    }

最佳答案

来自头文件中convert的讨论:

The output buffer's frameCapacity should be at least at large as the inputBuffer's frameLength. If the conversion involves a codec or sample rate conversion, you instead must use convertToBuffer:error:withInputFromBlock:.

您正在从 48kHz 转换为 16kHz,这算作速率转换,因此您必须使用 convertToBuffer:

let inputBlock: AVAudioConverterInputBlock = { inNumPackets, outStatus in
    outStatus.pointee = AVAudioConverterInputStatus.haveData
    return buffer
}

var error: NSError? = nil
let status: AVAudioConverterOutputStatus = converter!.convert(to: convertBuffer, error: &error, withInputFrom: inputBlock)
// TODO: check status

附注在 apple 创建新的 NSError code'n'strings 一定非常昂贵 - 他们的预算无法支付“速率转换需要 convertToBuffer”消息。

关于ios - AVAudioConverter float32/48khz -> int16/16khz 转换失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42660859/

有关ios - AVAudioConverter float32/48khz -> int16/16khz 转换失败的更多相关文章

  1. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  4. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  5. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  6. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  7. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  8. ruby - 在 Ruby 中实现 to_int 和 to_str 的后果 - 2

    我haveaclass它公开了一个字符串值和一个int值(分别是命令输出和退出代码)。除了通过to_s和to_i公开它们之外,我还使用to_str和to_int,如下所示:classStatusdefto_s@outputendalias:to_str:to_sdefto_i@status.exitstatusendalias:to_int:to_iend我的想法是能够在尽可能多的情况下使用这个对象。将其强制转换为字符串或整数会增加可用性。例如,我可以将对象与字符串连接起来:a_string="Outputwas:"+results(我想用这个作为int强制转换的例子,但是Fixnum

  9. ruby-on-rails - ruby rails 将参数转换为 int 数组 - 2

    我正在通过get发送数据,我需要将其放入一个int数组中以便在查找中使用。这是我的代码:@found=Array.newparams['candidate'].eachdo|c|@found我的网址是这样的http://localhost:3000/export/candidate?candidate[]=3&candidate[]=4&commit=Export如果它有任何不同,我将它用于此查找@candidate=Candidate.find(:all,:conditions=>["candidates.idIN?",@found])但目前它并没有把它放在一个真正的数组中,因为我得

  10. 深度学习12. CNN经典网络 VGG16 - 2

    深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG

随机推荐