我在记录时崩溃:“所需条件为假:format.sampleRate == hwFormat.sampleRate”afterweb rtc 调用

2023-11-29

我的记录工作正常,但问题是在 WebRTC 调用之后,我崩溃了

所需条件为 false:format.sampleRate == hwFormat.sampleRate

这是我开始崩溃和 installTap 的方式:

func startRecord() {
        self.filePath = nil
        
        print("last format: \(audioEngine.inputNode.inputFormat(forBus: 0).sampleRate)")
        let session = AVAudioSession.sharedInstance()
        do {
            try session.setCategory(.playAndRecord, options: .mixWithOthers)
        } catch {
            print("======== Error setting setCategory \(error.localizedDescription)")
        }
        do {
            try session.setPreferredSampleRate(44100.0)
        } catch {
            print("======== Error setting rate \(error.localizedDescription)")
        }
        do {
            try session.setPreferredIOBufferDuration(0.005)
        } catch {
            print("======== Error IOBufferDuration \(error.localizedDescription)")
        }
        do {
            try session.setActive(true, options: .notifyOthersOnDeactivation)
        } catch {
            print("========== Error starting session \(error.localizedDescription)")
        }
        let format = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16,
            sampleRate: 44100.0,
//            sampleRate: audioEngine.inputNode.inputFormat(forBus: 0).sampleRate,
            channels: 1,
            interleaved: true)
        audioEngine.connect(audioEngine.inputNode, to: mixer, format: format)
        audioEngine.connect(mixer, to: audioEngine.mainMixerNode, format: format)

        let dir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as String
        filePath =  dir.appending("/\(UUID.init().uuidString).wav")

        _ = ExtAudioFileCreateWithURL(URL(fileURLWithPath: filePath!) as CFURL,
            kAudioFileWAVEType,(format?.streamDescription)!,nil,AudioFileFlags.eraseFile.rawValue,&outref)

        mixer.installTap(onBus: 0, bufferSize: AVAudioFrameCount((format?.sampleRate)!), format: format, block: { (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in

            let audioBuffer : AVAudioBuffer = buffer
            _ = ExtAudioFileWrite(self.outref!, buffer.frameLength, audioBuffer.audioBufferList)
        })

        try! audioEngine.start()
        startMP3Rec(path: filePath!, rate: 128)
    }

    func stopRecord() {

        self.audioFilePlayer.stop()
        self.audioEngine.stop()
        self.mixer.removeTap(onBus: 0)

        self.stopMP3Rec()
        ExtAudioFileDispose(self.outref!)

        try? AVAudioSession.sharedInstance().setActive(false)
    }
    
    func startMP3Rec(path: String, rate: Int32) {

        self.isMP3Active = true
        var total = 0
        var read = 0
        var write: Int32 = 0

        let mp3path = path.replacingOccurrences(of: "wav", with: "mp3")
        var pcm: UnsafeMutablePointer<FILE> = fopen(path, "rb")
        fseek(pcm, 4*1024, SEEK_CUR)
        let mp3: UnsafeMutablePointer<FILE> = fopen(mp3path, "wb")
        let PCM_SIZE: Int = 8192
        let MP3_SIZE: Int32 = 8192
        let pcmbuffer = UnsafeMutablePointer<Int16>.allocate(capacity: Int(PCM_SIZE*2))
        let mp3buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(MP3_SIZE))

        let lame = lame_init()
        lame_set_num_channels(lame, 1)
        lame_set_mode(lame, MONO)
        lame_set_in_samplerate(lame, 44100)
        lame_set_brate(lame, rate)
        lame_set_VBR(lame, vbr_off)
        lame_init_params(lame)

        DispatchQueue.global(qos: .default).async {
            while true {
                pcm = fopen(path, "rb")
                fseek(pcm, 4*1024 + total, SEEK_CUR)
                read = fread(pcmbuffer, MemoryLayout<Int16>.size, PCM_SIZE, pcm)
                if read != 0 {
                    write = lame_encode_buffer(lame, pcmbuffer, nil, Int32(read), mp3buffer, MP3_SIZE)
                    fwrite(mp3buffer, Int(write), 1, mp3)
                    total += read * MemoryLayout<Int16>.size
                    fclose(pcm)
                } else if !self.isMP3Active {
                    _ = lame_encode_flush(lame, mp3buffer, MP3_SIZE)
                    _ = fwrite(mp3buffer, Int(write), 1, mp3)
                    break
                } else {
                    fclose(pcm)
                    usleep(50)
                }
            }
            lame_close(lame)
            fclose(mp3)
            fclose(pcm)
            self.filePathMP3 = mp3path
        }
    }
    
    func stopMP3Rec() {
        self.isMP3Active = false
    }

作为第一次运行应用程序,我使用记录最后的格式

print("last format: \(audioEngine.inputNode.inputFormat(forBus: 0).sampleRate)")

--> 返回0 -> 正常记录 下次返回44100 -> 正常记录

但是在 webrtc 调用之后,我得到了 48000,然后它在这一行崩溃了

self.audioEngine.connect(self.audioEngine.inputNode, to: self.mixer, format: format)

我在 stackoverflow 上花了 4 个小时,但没有解决方案适合我。

我不需要 48000 格式,因为我已将示例设置为

sampleRate: audioEngine.inputNode.inputFormat(forBus: 0).sampleRate,

-> 我的输出很难听清,我可以认出我的声音:(

所以我认为44100是最好的

有人可以给我一些建议吗?谢谢


下图部分,更生动地体现您的情况。

    let bus = 0
    let inputNode = audioEngine.inputNode
    let inputFormat = inputNode.outputFormat(forBus: bus)
        
    let outputFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: true)!

    let converter = AVAudioConverter(from: inputFormat, to: outputFormat)!

    inputNode.installTap(onBus: bus, bufferSize: 1024, format: inputFormat){ (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
                
                var newBufferAvailable = true
    
                let inputCallback: AVAudioConverterInputBlock = { inNumPackets, outStatus in
                    if newBufferAvailable {
                        outStatus.pointee = .haveData
                        newBufferAvailable = false
                        
                        return buffer
                    } else {
                        outStatus.pointee = .noDataNow
                        return nil
                    }
                }
    
                let convertedBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate))!
    
                var error: NSError?
                let status = converter.convert(to: convertedBuffer, error: &error, withInputFrom: inputCallback)
    
                // 44100 Hz buffer
                print(convertedBuffer.format)
                
            }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我在记录时崩溃:“所需条件为假:format.sampleRate == hwFormat.sampleRate”afterweb rtc 调用 的相关文章

随机推荐

  • AWS Elastic Beanstalk 给出“无法将主机名“db”翻译为地址”错误

    我一直在尝试部署由 Django Postgresql 和 Nginx 组成的 docker 当我这样做时效果很好 sudo docker compose up However when deploy it on AWS EB it giv
  • 条件运算符中的“错误:需要左值作为赋值的左操作数”

    我是 C 新手 今天我学会了 运算符是 if else 语句的短类型 但是 当我执行这段代码时 int b int x b 3 lt 2 x 12 x 34 我收到错误 错误 需要左值作为赋值的左操作数 我不明白为什么会这样 我的想法是 程
  • 无法使用 golang 解码 XML,始终为空结构

    我正在尝试使用 golang 解码 XML 但以下代码给出了一个空结构 有人可以帮忙吗 当我运行以下代码时 我总是得到 packet 附源码 package main import fmt encoding xml io ioutil ty
  • Android - 构建支持附加组件的应用程序

    在 NET 上 我可以使用 反射 在运行时加载 DLL 库 这允许我为我的应用程序构建一些附加组件 在Android上 有什么方法可以执行类似的操作吗 我想制作一个附加组件 安装后可以从我的 Android 应用程序调用 我的第一个想法是建
  • android:如何使用触摸和拖动创建不同的“屏幕”和它们之间的导航?

    我可以创建与主屏幕上相同类型的导航吗 也就是说 我想要可以使用触摸和拖动在不同的屏幕之间导航 我还没有看到任何相关内容 所以是时候问一下了 哦 我正在谈论 Android 的应用程序 没有任何内置内容 但您可以使用 ViewFlipper
  • 为什么当我打开 H2 控制台时,从 Java 添加的表不可见?

    我在Java中使用H2嵌入式数据库 在创建数据库并添加一些表和数据后 它被保存为我计算机目录中的文件 但是每当我使用 H2 控制台打开此文件时 它根本不显示任何表格 为什么桌子不在那里 我在我的 java 代码中使用这个 URL jdbc
  • Java QueryDsl代码生成不生成Q类

    我正在制作一个 Spring 项目 其中我使用 QueryDsl 作为实体 我从几个月前开始接手这个项目 其中我已经有 1 个生成的类 QUser 现在我创建了一个名为 Permission 的新实体 并修改了 User 实体 当我构建项目
  • 在 Dymola 中编译大型数组

    请考虑以下小型 Modelica 模型和功能 model VectorizeDemo parameter Integer na 5 final parameter Integer nb 2 na final parameter Real a
  • 如何将数组分割成块,但让它一个接一个地填充每个数组

    我使用这个函数来创建数组块 function chunkArray myArray chunk size let results while myArray length results push myArray splice 0 chun
  • iOS5 的 Json 解析器示例

    我在 iOS5 中创建了一个应用程序 我想在网络服务器上存储和检索数据 为此我想使用 JSON 解析器 我使用了 ray wenderlich 为 ios4 提供的演示 我听说ios 5 有一些现成的框架 那么有人对此有任何想法吗 我正在使
  • 将下拉列表的值传递到文本框

    我的视图中有一个下拉列表 一个提交按钮和一个文本框 我想在单击提交按钮或 dropdownlist 的 onChange 事件时将 dropdownlist 的选定值传递到文本框 我怎样才能实现这个目标 我解决如下 div Html Dro
  • 黑客挑战 - 定位代码中的漏洞

    我的朋友最近完成了一项黑客挑战并将其发送给我 二进制文件和源代码 在向他寻求建议之前我想先在这里问一下 因为我想自己做 我一直在经历它 但我正在努力寻找漏洞 include
  • mvc:将单选按钮的值添加到集合中并保存到数据库

    我有一个带有文本框的表单和一些带有单选按钮的问题 我希望此表单的用户检查每个单选按钮 这是强制性的 我想将检查是或否的值与每个问题的名称或 ID 一起使用实体框架写入数据库 如果我知道如何将此信息收集到集合中 我可以写入数据库 请问如何将这
  • 在单元测试代码中访问部署目标

    我需要知道单元测试用例中的部署目标 有没有办法以编程方式获取 iOS 部署目标 使用 Objective C This 可作为 Xcode 构建变量使用 called IPHONEOS DEPLOYMENT TARGET 您需要做的就是创建
  • 有没有人找到一种在 SQL 数据库中存储 BSON ObjectId 值的有效方法?

    我们正在将一些数据从 MySQL 迁移到 Mongo 并为一些数据库表添加了额外的字段ObjectId迁移的数据对象的值 目前我们将它们存储为 varchar 24 latin1 general ci 效果很好 然而 为了高效存储 索引 我
  • 响应式水平滚动菜单

    http healthunit com当您从移动电话设备查看时 屏幕顶部有一个干净的水平滚动菜单 由于我正在重新设计一个包含大量导航元素的网站 我正在尝试模仿相同的功能 要求 左右滚动单击选项 居中列表项选项在空间中居中 一次只能看到一个列
  • 使用 python 的 re 模块正确解析字符串文字

    我正在尝试为我用 Python 编写的 javascript 预处理器添加一些轻量级降价支持 在大多数情况下 它是有效的 但有时我使用的正则表达式表现得有点奇怪 我认为这与原始字符串和转义序列有关 正则表达式是
  • Echarts:绘制信号的方差

    我想在图表中绘制多个信号的方差 或者基本上填充上部信号和下部信号之间的空间 是否可以创建这样的图表 我看到了置信带示例 https echarts apache org examples en editor html c confidenc
  • 向 JPanel 添加椭圆形

    这是我的简单代码 我真的不知道如何将绘制的椭圆添加到JPanel 我以前画过一些画 但我从未使用过构造函数 所以我不知道 public class Buffer extends JPanel public JFrame frame publ
  • 我在记录时崩溃:“所需条件为假:format.sampleRate == hwFormat.sampleRate”afterweb rtc 调用

    我的记录工作正常 但问题是在 WebRTC 调用之后 我崩溃了 所需条件为 false format sampleRate hwFormat sampleRate 这是我开始崩溃和 installTap 的方式 func startReco