AVSampleRateKey 在更改采样率时崩溃 - 如何解决

问题描述 投票:0回答:1

AVSampleRateKey 用于指定使用 AVFoundation 处理音频时所需的采样率。但是,将 AVSampleRateKey 设置为某些值可能会导致崩溃,特别是在使用 44100 以外的值时。

  func manualAudioRender(effect: Effect) throws {
        prepareAudioEngine(forEffect: effect)
        
        audioPlayerNode.scheduleFile(avAudioFile, at: nil)
        try audioEngine.enableManualRenderingMode(.offline, format: avAudioFile.processingFormat, maximumFrameCount: maxNumberOfFrames)
        
        try audioEngine.start()
        audioPlayerNode.play()
        
        let outputFile: AVAudioFile
        let url = try PersistenceManager.shared.urlForEffect(named: effect.name)
        var recordSettings = avAudioFile.fileFormat.settings
        
        print("------>>>. \(recordSettings)")
        
        recordSettings[AVSampleRateKey] = 48000.0
        
        print("------>>>. \(recordSettings)")
      
//        var bitRate = audioBitrate
//        var sampleRate = 44100.0
//        var channels = 1
//
//        let settings: [String: AnyObject] = [
//                    AVFormatIDKey : NSNumber(value: Int32(kAudioFormatAppleLossless) as Int32),
//                    AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue as AnyObject,
//                    AVEncoderBitRateKey: bitRate as AnyObject,
//                    AVNumberOfChannelsKey: channels as AnyObject,
//                    AVSampleRateKey: sampleRate as AnyObject
//                ]
        
        
        outputFile = try AVAudioFile(forWriting: url, settings: recordSettings)
        
        let buffer = AVAudioPCMBuffer(pcmFormat: audioEngine.manualRenderingFormat, frameCapacity: audioEngine.manualRenderingMaximumFrameCount)!
        
        // Adjust the file size based on the effect rate
        let outputFileLength = Int64(Double(avAudioFile.length) / effect.rate)
        
        while audioEngine.manualRenderingSampleTime < outputFileLength {
            let framesToRender = min(buffer.frameCapacity, AVAudioFrameCount(outputFileLength - audioEngine.manualRenderingSampleTime))
            let status = try audioEngine.renderOffline(framesToRender, to: buffer)
            switch status {
            case .success:
                try outputFile.write(from: buffer)
            case .error:
                print("Error rendering offline audio")
                return
            default:
                break
            }
        }
        
        audioPlayerNode.stop()
        audioEngine.stop()
        audioEngine.disableManualRenderingMode()
    }
swift crash avfoundation avkit
1个回答
0
投票

正如本讨论中所指出的,您无法直接使用

AVAudioEngine
节点或抽头转换采样率。

播放缓冲区时,有一个隐含的假设,即缓冲区的采样率与节点的输出格式相同。

您需要使用

AVAudioConverter
这个答案中找到了一个例子。

© www.soinside.com 2019 - 2024. All rights reserved.