新闻资讯

新闻资讯 行业动态

使用 AVAudioEngine, 播放与实时音效处理

编辑:008     时间:2020-02-26

AVAudioEngine 可以做实时的音效处理,用 Effect Unit 加效果

4.1 播放先

设置 AudioEngine,添加节点,连接节点

func setupAudioEngine(){
        // 添加节点
        attachNodes()

        // 连接节点
        connectNodes()

        // 准备 AudioEngine
        engine.prepare()
        
        // AVAudioEngine 的数据流,采用推 push 模型
        // 使用计时器,每隔 0.1 秒左右,调度播放资源 let interval = 1 / (readFormat.sampleRate / Double(readBufferSize)) let timer = Timer(timeInterval: interval / 2, repeats: true) {
            [weak self] _ in guard self?.state != .stopped else { return }
            // 分配缓冲 buffer, 调度播放资源
            self?.scheduleNextBuffer()
            self?.handleTimeUpdate()
            self?.notifyTimeUpdated()
        }
        RunLoop.current.add(timer, forMode: .common)
    }

    // 添加播放节点
    open func attachNodes() {
        engine.attach(playerNode)
    }

    // 播放节点,连通到输出
    open func connectNodes() {
        engine.connect(playerNode, to: engine.mainMixerNode, format: readFormat)
    } 

调度播放资源,将数据 ( 上步创建的音频缓冲 buffer )交给 AudioEngine 的播放节点 playerNode

func scheduleNextBuffer(){
        guard let reader = reader else { return }
        //  通过状态记录,管理播放
        // 播放状态,就是一个开关
        guard !isFileSchedulingComplete || repeats else { return } do {
            // 拿到,上步创建音频缓冲 buffer let nextScheduledBuffer = try reader.read(readBufferSize)
            // playerNode 播放消费掉
            playerNode.scheduleBuffer(nextScheduledBuffer)
        } catch ReaderError.reachedEndOfFile {
            isFileSchedulingComplete = true } catch {  }
    } 

开启播放

public func play() {
        // 没播放,才开启
        guard !playerNode.isPlaying else { return } if !engine.isRunning { do {
                try engine.start()
            } catch { }
        }
        
        // 提升用户体验,播放前,先静音 let lastVolume = volumeRampTargetValue ?? volume
        volume = 0
        
        //  播放节点播放
        playerNode.play()
        
        // 250 毫秒后,正常音量播放
        swellVolume(to: lastVolume)
        
        // 更新播放状态
        state = .playing
    } 

4.2 音效后

添加实时的音高、播放速度效果

// 使用 AVAudioUnitTimePitch 单元,调节播放速度和音高效果 let timePitchNode = AVAudioUnitTimePitch()
    

    override func attachNodes() {
        // 添加播放节点
        super.attachNodes()
        // 添加音效节点
        engine.attach(timePitchNode)
    }
    
// 相当于在播放节点和输出节点中间,插入音效节点
    override func connectNodes() {
        engine.connect(playerNode, to: timePitchNode, format: readFormat)
        engine.connect(timePitchNode, to: engine.mainMixerNode, format: readFormat)
    }


原文链接:https://juejin.im/post/5e52a5c55188254940670156
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐