[Android] 混音器AudioMixer

本文详细介绍了Android中的AudioMixer如何创建及配置参数,包括设置混音源buffer、调整音量、设定采样率等,阐述了混音器在处理音频数据过程中的作用,以及如何进行重采样和混音操作。
摘要由CSDN通过智能技术生成

AudioMixer是Android的混音器,通过混音器可以把各个音轨的音频数据混合在一起,然后输出到音频设备。

 

创建AudioMixer

AudioMixer在MixerThread的构造函数内创建:

 AudioFlinger::MixerThread::MixerThread(...)
{
    ...
    mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
    ...
}

这说明了一个MixerThread对应一个AudioMixer。

而且MixerThread传了两个参数给AudioMixer:

  1. mNormalFrameCount,AudioMixer会根据传进来的mNormalFrameCount作为一次输送数据的长度,把源buffer的音频数据写入目的buffer
  2. mSampleRate,AudioMixer会把传进来的mSampleRate作为音频数据输出的采样率

 

 

 

配置AudioMixer参数

在上一篇描述MixerThread的时候说过,prepareTrack_l内会配置AudioMixer的参数,现在来详细分析一下各个参数的作用。

 

 

mAudioMixer->setBufferProvider(name, track);

设置混音的源buffer,name为传入的索引,track即从mActiveTracks取出来的Track

关于索引name,在这里深入分析,name的获取过程如下:

int name = track->name();                                             
+                                                                     
+--> int name() const { return mName; }                               
    +                                                                 
    +-->  mName = thread->getTrackName_l(channelMask, sessionId);     
        +                                                             
        +--> return mAudioMixer->getTrackName(channelMask, sessionId);
            +                                                         
            +--> uint32_t names = (~mTrackNames) & mConfiguredNames;  
            |                                                         
            +--> int n = __builtin_ctz(names);                        

 

names为索引的集合,names的每一个bit代表不同的索引,names上的某个bit为1,就代表该bit可以取出来作为索引,__builtin_ctz的作用是计算names的低位0的个数,即可以取出最低位为1的bit作为索引。如下:

11111111111111111111000000000000
                   ^            

低位有12个0,则取bit12作为索引,那么返回的索引值为1<<12

 

决定names的参数有两个:

  1. mTrackNames:用于记录当前的Track,初始值为0。当加入某个Track时,该Track对应的bit会被置为1.
  2. mConfiguredNames:用于表明该AudioMixer所支持最多的Track数目,如支持最多N个Track,那么mConfiguredNames = 1<<N – 1,此时mConfiguredNames低位的N个bit为1,高位的32-N个bit为0。mConfiguredNames的默认值为-1,即N = 32

 

 

mAudioMixer->enable(name);

enable方法只是把track的enabled置为true,然后调用invalidateState(1 << name);表明需要调用刷新函数。

 void AudioMixer::enable(int name)
 {
     name -= TRACK0;
     track_t& track = mState.tracks[name];
 
     if (!track.enabled) {
         track.enabled = true;
         invalidateState(1 << name);
     }
 }

 

 

 

mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)vl);                                                           
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)vr);

分别设置左右声道音量,然后调用invalidateState(1 << name);表明需要调用刷新函数。

         case VOLUME0:  
         case VOLUME1:  
             if (track.volume[param-VOLUME0] != valueInt) {  
                 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
                 track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16; 
                 track.volume[param-VOLUME0] = valueInt;   
                 if (target == VOLUME) {
                     track.prevVolume[param-VOLUME0] = valueInt << 16;  
                     track.volumeInc[param-VOLUME0] = 0;  
                 }

 

 

mAudioMixer->setParameter(                
    name,
    AudioMixer::TRACK,                   
    AudioMixer::FORMAT, (void *)track->format());

保证传进来的PCM数据为16bit

         case FORMAT:      
             ALOG_ASSERT(valueInt == AUDIO_FORMAT_PCM_16_BIT);      
             break;

 

 

 

mAudioMixer->setParameter(     
    name,   
    AudioMixer::TRACK, 
    AudioMixer::CHANNEL_MASK, (void *)track->channelMask());

 

设置通道数,mask:单音轨(mono),双音轨(stereo)…

         case CHANNEL_MASK: {
             audio_channel_mask_t mask = (audio_channel_mask_t) value;
             if (track.channelMask != mask) {
                 uint32_t channelCount = popcount(mask);
                 ALOG_ASSERT((cha
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值