首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当AVAudioUnitTimePitch改变播放速率时,如何使用AVAudioEngine进行离线音频处理?

当AVAudioUnitTimePitch改变播放速率时,如何使用AVAudioEngine进行离线音频处理?
EN

Stack Overflow用户
提问于 2020-09-29 22:21:10
回答 1查看 264关注 0票数 0

我学习了如何使用AVAudioEngine将音频处理成文件,只要我不用AVAudioUnitTimePitch改变播放速率,我的代码就可以工作。

当速率改变时,渲染的音频与原始音频的长度相同(速率不变)。因此,如果音频变慢(速率< 1),它的一部分将被修剪,如果它被加速(速率> 1),渲染的音频的最后一部分将是静默的。

代码如下:

代码语言:javascript
运行
复制
// engine: AVAudioEngine
// playerNode: AVAudioPlayerNode
// audioFile: AVAudioFile

open func render(to destinationFile: AVAudioFile) throws {
    
    playerNode.scheduleFile(audioFile, at: nil)
    
    do {
        let buffCapacity: AVAudioFrameCount = 4096
        try engine.enableManualRenderingMode(.offline, format: audioFile.processingFormat, maximumFrameCount: buffCapacity)
    }
    catch {
        print("Failed to enable manual rendering mode: \(error)")
        throw error
    }
    
    do {
        try engine.start()
    }
    catch {
        print("Failed to start the engine: \(error)")
    }
    
    playerNode.play()
    
    let outputBuff = AVAudioPCMBuffer(pcmFormat: engine.manualRenderingFormat,
                                      frameCapacity: engine.manualRenderingMaximumFrameCount)!
    
    while engine.manualRenderingSampleTime < audioFile.length {
        let remainingSamples = audioFile.length - engine.manualRenderingSampleTime
        let framesToRender = min(outputBuff.frameCapacity, AVAudioFrameCount(remainingSamples))
        
        do {
            let renderingStatus = try engine.renderOffline(framesToRender, to: outputBuff)
            
            switch renderingStatus {
            
            case .success:
                do {
                    try destinationFile.write(from: outputBuff)
                }
                catch {
                    print("Failed to write from file to buffer: \(error)")
                    throw error
                }
                
            case .insufficientDataFromInputNode:
                break
            
            case.cannotDoInCurrentContext:
                break
            
            case .error:
                print("An error occured during rendering.")
                throw AudioPlayer.ExportError.renderingError
            
            @unknown default:
                fatalError("engine.renderOffline() returned an unknown value.")
            }
        }
        catch {
            print("Failed to render offline manually: \(error)")
            throw error
        }
    }
    
    playerNode.stop()
    engine.stop()
    engine.disableManualRenderingMode()
}

我试图通过渲染与回放速率成反比的采样量来解决这个问题。这仅修复了速率大于1时的问题。

EN

回答 1

Stack Overflow用户

发布于 2020-10-11 04:15:39

由于没有人应答,而且已经过去了很多天,我将分享我是如何解决这个问题的。

呈现与回放速率成反比的采样量被证明是有效的。最初,这种方法不起作用,因为我做错了。

下面是如何获得要渲染的正确数量的样本:

代码语言:javascript
运行
复制
let framesToRenderCount = AVAudioFramePosition(Float(audioFile.length) * 1 / rate)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64121563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档