insert effect 和 aux effect的区别和场景还有部分代码解析

目录

引文

正文

buffer相关代码分析

1. 从AudioFlinger::createEffect()开始:

2. 从AudioFlinger::createTrack()开始

总结


引文

为什么effect会有insert和aux这两种,一直困扰了我很久,后来无意中看到了调音台上面的概念,感觉概念应该是来自于这里,在android里面,insert effect是直接对播放的声音进行添加音效,而aux则是用在混音的场景,aux就相当于干声的另外一股数据,进行另外的数据,但是最终都是要跟原来的声音叠加在一起的。

我在bilibili上看到了个调音台知识的视频,截取了其中的一张图,如下,fx return是接到aux 1和aux2 output。这边的区别是aux模块的接入点跟代码可能有些不同,不够我觉得不影响理解。

正文

先考虑两种场景:

  1. 一种是这个track有自己的insert track和一个aux的全局音效
  2. 另外一种是这个track没有insert track,但是有一个aux的全局音效

第一种情况:

Thread::track有非全局的insert effect,其inBuffer的独立分配的,outBuffer中externalData指向的是thread::mEffectBuffer,aux同非全局的,其inBuffer也是独立分配的,outBuffer中externalData指向的是thread::mEffectBuffer。

mix结束之后,

aux effect的inbuffer里面存放了aux level以及resample之后的数据,

insert effect的inbuffer里面存放的是mix音量以及resample之后的数据,

接下来是进行effect的process的处理,

aux effect处理完的数据放到了thread::mEffectBuffer

insert effect处理完的数据也放到了thread::mEffectBuffer,这两者的数据是进行叠加的。

第二种情况:

Thread::track有全局的aux effect和没有非全局的insert effect,那在prepareTracks_l的时候,audioMixer会将AudioMixer::track->mainBuffer()指向Thread::mMixerBuffer, 这样mixer出来的数据一份是在mMixerBuffer,一份数据是在auxBuffer。

threadLoop_mix()结束之后,会将数据从Thread::mMixerBuffer拷贝到Thread::mEffectBuffer,而aux effect的InBuffer中存放着mix之后的aux数据,他的outBuffer其实是指向全局音效链的halOutBuffer的,也就是Thread::mEffectBuffer,所以在处理完aux effect的时候,两股数据流已经在这里完成合并了,不同于第一种情况,是在处理完之后才合并的。

buffer相关代码分析

梳理下effect相关的buffer情况:

1. 从AudioFlinger::createEffect()开始:

A. 创建effectchain并且添加到thread中来,在addEffectChain_l中,会申请mEffectBuffer的镜像halInBuffer,里mAudioBuffer是其中申请出来新的空间,这个halInBuffer中的externalData指向的是thread的mEffectBuffer.

        如果不是全局音效链,并且不在DIRECT output中,则会重新分配halInBuffer,不过这个时候的externalBuffer则是为null。buffer指向新创建的mAudioBuffer.raw。然后更新该线程下所有这个sessionId相同的track的mainbuffer的指向,指向mAudioBuffer.raw。

接下来是设置chain的inBuffer指向halInBuffer,chain的OutBuffer指向halOutBuffer,在全局音效的情况下halInBuffer等于halOutBuffer,在非全局音效情况下,halInBuffer是指向后来申请的对象的。

接下来是对音效链进行排序,sessionId从大到小排序。从0开始遍历,找到比我小的,占用他的位置,比如说第0个就比我小,那就占用了第0位置。所以是从大到小的排序。

所以从上面可以知道,对于全局音效链的buffer信息差不多如下:

x effects for session 0
        In buffer                         Out buffer                           Active tracks:
        0xb400007bbe921000 -> 0x7bbeba2000   0x7bbeba2000 -> 0xb400007bbe921000   0
        Thread::mEffectBuffer -> 新申请的空间   新申请的空间 -> Thread::mEffectBuffer

Effect ID 163:
                - Input configuration:
                        Buffer     Frames  Smp rate Channels Format
                        0x7bbeba2000 00960   48000    00000003      5 (AUDIO_FORMAT_PCM_FLOAT)
                - Output configuration:
                        Buffer     Frames  Smp rate Channels Format
                        0x7bbeba2000 00960   48000    00000003      5 (AUDIO_FORMAT_PCM_FLOAT)
                - HAL buffers:
                        In(0xb400007bbe921000 -> 0x7bbeba2000) InConversion(nullptr) Out(0x7bbeba2000 -> 0xb400007bbe921000) OutConversion(nullptr)

B. 在effectChain中创建effect, chain::createEffect_l 

    B.1 new EffectModule

    B.2 addEffect_ll(effect)

         B.2.1 如果这个音效是AUX,则将该音效插入到音效链的第0位置,并且申请halBuffer,externalData为null的,然后effect inBuffer指向新申请的buffer,outBuffer指向chain的inBuffer,这个inBuffer,AUX必须是全局音效,这个inBuffer指向的halInBuffer是带有externalData的。所以对于AUX音效的话,其buffer信息如下:

全局音效链
In buffer                         Out buffer                           
0xb400007bbe921000 -> 0x7bbeba2000   0x7bbeba2000 -> 0xb400007bbe921000 

AUX音效,放在第一个节点,下面是buffer信息:
HAL buffers:
In(0x7bbeba1000) InConversion(nullptr) Out(0x7bbeba2000 -> 0xb400007bbe921000) OutConversion(nullptr)
In是新申请的空间 Out是Chain的halOutBuffer,即从链申请的buffer到externalData即Thread::mEffectBuffer

其他全局音效的buffer信息:
HAL buffers:
In(0xb400007bbe921000 -> 0x7bbeba2000) InConversion(nullptr) Out(0x7bbeba2000 -> 0xb400007bbe921000) OutConversion(nullptr)
其中的inBuffer和outBuffer都指向全局的halInBuffer和halOutBuffer,而这两个值相等。

                  如果这个音效不是AUX,则对这个effect也进行排序,这个音效的inBuffer指向chain的inBuffer,而outBuffer则是看他处在第几个位置,如果是最后一个位置,则指向chain的OutBuffer,如果不是的话,则指向mInBuffer。所以如果是全局音效链的话,那inBuffer跟outBuffer是一样的,不是全局的话,则inBuffer指向的是不带有externalData的halInBuffer。所以如果不是Aux音效的话,其中的buffer信息如下:

全局的非AUX音效的buffer信息如下(每个effect都是如此):
HAL buffers:
In(0xb400007bbe921000 -> 0x7bbeba2000) InConversion(nullptr) Out(0x7bbeba2000 -> 0xb400007bbe921000) OutConversion(nullptr)
In和Out都是和chain的一致

非全局的音效的buffer信息则是:
In buffer             Out buffer                     Active tracks:
0x76c8e0c000   0x76c8e7b000 -> 0x7641bc91c0               1
Effect ID 259:
HAL buffers:
In(0x76c8e0c000) InConversion(nullptr) Out(0x76c8e0c000) OutConversion(nullptr)

Effect ID 267:
HAL buffers:
In(0x76c8e0c000) InConversion(nullptr) Out(0x76c8e0c000) OutConversion(nullptr)

Effect ID 283:
HAL buffers:
In(0x76c8e0c000) InConversion(nullptr) Out(0x76c8e7b000 -> 0x7641bc91c0) OutConversion(nullptr)

         B.2.2 effect->configure() 将配置信息发送到HAL层的effect去,包括inbuffer和outbuffer等信息。

2. 从AudioFlinger::createTrack()开始

-》thread::createTrack_l() 中会通过sessionId获取effectChain,而这个sessionId是不为0(0是全局音效),然后会将chain->inBuffer设置到track的mainBuffer。

所以平时如果该track有非全局的effect的话,那他的main指向的是chain的inBuffer应该是没有externalData的halInBuffer的。那如果没有非全局的effect的话,track的mainBuffer指向的是mSinkBuffer(这个在TrackBase构造函数里面设定的)。不过这个mainBuffer虽然指向sinkBuffer,但是在mixerThread中,最后配置到Mixer中的mainBuffer是Thread::mMixerBuffer

而对于track的auxBuffer是在audioTrack调用attachAuxEffect的时候才会进行设置,是根据effectId进行查找effect,小心不是sessionId,获取到对应的effect之后,会将该effect的InBuffer设置到track的auxBuffer。按照上面auxEffect的inBuffer是自己开辟的一个新的buffer。

总结

到这边,我们对于buffer的部分也比较清晰了,

全局音效的inBuffer和outBuffer,指向halInBuffer和halOutBuffer,这两个值相等,但是有方向之说。

链里面不管有没有aux存在,其处理结束的数据都是在mEffectBuffer中,其处理前的数据是存放在各自的inBuffer,这部分的数据是mix之后的数据,aux是直接放到自己的空间,而其他音效则是在mEffectBuffer中。

对于非全局音效的话,则他的InBuffer是自己申请的空间,outBuffer是halOutBuffer也就是external指向mEffectBuffer,链内部的effect的InBuffer和outBuffer都是指向自己创建的空间,最后一个effect的outBuffer才会指向halOutBuffer。mix的数据是送到InBuffer中的。

另外这边备注一段代码:

frameworks/av/services/audioflinger/Effects.h

class EffctModule : public EffectBase {

    int16_t     *inBuffer() const {
        return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
    }
    int16_t     *outBuffer() const {
        return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
    }

}

frameworks/av/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h

class EffectBufferHalInterface : public RefBase
{
  public:
    virtual audio_buffer_t* audioBuffer() = 0;
    virtual void* externalData() const = 0;
    virtual void* ptr() {
        return externalData() != nullptr ? externalData() : audioBuffer()->raw;
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值