当前位置:   article > 正文

Android Framework 音频子系统(13)音量调节之基础_setstreamvolume

setstreamvolume

该系列文章总纲链接:专题分纲目录 Android Framework 音频子系统​​​​​​​


本章关键点总结 & 说明:

本章节主要关注➕ 以上思维导图左上 音量调节 部分 即可。说明了音量的基础知识和AudioFlinger调节音量流程,主要包括:

  • AudioFlinger对master volume, stream volume的初始化设置流程
  • AudioFlinger的setMasterVolume 主音量设置流程
  • AudioFlinger 的setStreamVolume 流音量设置流程
  • 播放线程 加载音量设置 流程

1 音量基础知识

@1 四大类Volume音量

  • master volume:设置它等于设置所有的stream volume和track volume。它可以写到声卡里面去,控制所有声音的音量。也可以不写到声卡里面去,而是作为一个乘数因子来影响所有的音量。换句话说:master volume 可以设置所有的AudioTrack volume和stream volume。
  • stream volume:设置某一stream的音量,Android系统中支持10种stream。各种stream的音量也可以单独设置、互不影响。比如"音乐音量"不应该影响到"来电振铃"、"闹钟"、"通话"的音量。
  • stream volume alias:设置的是同一组stream音量,分组在Android源码中称之为"别名",即alias。比如在电话中,5种stream(STREAM_SYSTEM、STREAM_RING、STREAM_NOTIFICATION、STREAM_SYSTEM_ENFORCED、STREAM_DTMF)的alias都是STREAM_RING,那么对应的滑动条即可控制这5种stream的音量。
  • AudioTrack  volume: 单个App设置音量时设置的是这个,它只影响本App的音量。

@2 十种stream

Android系统中有10种stream,在system/core/include/system/audio.h中定义,但把这10种stream分成组,属于同一组的stream具有相同的别名(alias)。在我们设置音量时,一个音量调节滑动条具有一个alias,具有相同alias的stream都会受到这个滑动条的影响。stream与alias的关系(参考)如下所示:

@3 声音播放的两种路径

  • MixerThread:APP对音量的设置不会影响到声卡的硬件音量,而只会影响APP的音频数据的幅值(变小或放大),这些音频数据最终被混合后传给声卡。
  • DirectOutputThread(比如HDMI,单个音频应用程序单独使用一个声卡):同一时间里只有一个APP、只有一个AudioTrack使用它,所以该AudioTrack的音量可以被DirectOutputThread直接用来设置硬件音量,这种声卡使用的不多。若配置文件中参数信息包含"flags AUDIO_OUTPUT_FLAG_DIRECT",则表示这个声卡可以被某个App独占。App就能以DirectOutputThread的形式来使用这个声卡。

@4 混音的逻辑

  • app1:混音数据1 =  音频数据1 * master_volume * stream1_volume * AudioTrack1_volume
  • app2:混音数据2 = 音频数据2 * master_volume * stream2_volume * AudioTrack2_volume
  • app3:混音数据3 = 音频数据3 * master_volume * stream3_volume * AudioTrack3_volume

混合在一起: 最终混音 =混音数据1+混音数据2+混音数据3,然后把混合后的数据写给硬件。

@5 音频系统中的一些关键变量说明:

AudioFlinger类中有关成员:

  1. stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
  2. float mMasterVolume; //存储master volume
  3. bool mMasterMute; //存储是否静音

playbackThread类中:

  1. //为DuplicatingThread的OutputTrack多出一项, DuplicatingThread可以用于在两个声卡上播放出同样的声音
  2. stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1];
  3. bool mMasterMute;
  4. float mMasterVolume; //来源于AudioFlinger中的同名的变量

AudioTrack类中(App端):

float mVolume[2]; //两项,分别表示App设置的左右声道的音量

说明:stream volume和audioTreack中的volume只是软件上的处理,masterVolue中保存的值若HAL提供了相应的写函数就会写给硬件。


2 AudioFlinger调节音量流程

2.1 AudioFlinger音量设置流程说明

音量设置是通过逻辑运算将音量值存放在变量中,之后再播放中重新进行一轮逻辑运算,最终和声音数据一起写入到声卡中,进而播放出合理的声音。

@1 AudioFlinger对master volume, stream volume的初始化设置流程

最开始MasterVolume,、MasterMute、StreamVolume、StreamMute的初始化是在AudioFlinger对象创建时初始化的,MasterVolume,、MasterMute是在构造器中直接初始化,代码如下:

  1. AudioFlinger::AudioFlinger()
  2. : BnAudioFlinger(),
  3. mPrimaryHardwareDev(NULL),
  4. mAudioHwDevs(NULL),
  5. mHardwareStatus(AUDIO_HW_IDLE),
  6. mMasterVolume(1.0f),//初值1.0f
  7. mMasterMute(false),//静音初值
  8. mNextUniqueId(1),
  9. mMode(AUDIO_MODE_INVALID),
  10. mBtNrecIsOff(false),
  11. mIsLowRamDevice(true),
  12. mIsDeviceTypeKnown(false),
  13. mGlobalEffectEnableTime(0),
  14. mPrimaryOutputSampleRate(0)
  15. {
  16. //...
  17. }

而StreamVolume、StreamMute的初始化则是在成员变量结构体中初始化的,代码如下:

  1. //在创建结构体的时候 直接初始化
  2. struct stream_type_t {
  3. stream_type_t()
  4. : volume(1.0f),
  5. mute(false)
  6. {
  7. }
  8. float volume;
  9. bool mute;
  10. };

这一阶段初始化后,在加载音频库的时候执行loadHwModule,代码如下:

  1. audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
  2. {
  3. if (name == NULL) {
  4. return 0;
  5. }
  6. if (!settingsAllowed()) {
  7. return 0;
  8. }
  9. Mutex::Autolock _l(mLock);
  10. return loadHwModule_l(name);
  11. }

继续分析loadHwModule_l,代码实现如下:

  1. // loadHwModule_l() must be called with AudioFlinger::mLock held
  2. audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
  3. {
  4. for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
  5. if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
  6. ALOGW("loadHwModule() module %s already loaded", name);
  7. return mAudioHwDevs.keyAt(i);
  8. }
  9. }
  10. audio_hw_device_t *dev;
  11. //获取audio_hw_device_t类型设备dev,可以直接操作HAL层
  12. int rc = load_audio_interface(name, &dev);
  13. mHardwareStatus = AUDIO_HW_INIT;
  14. rc = dev->init_check(dev);
  15. mHardwareStatus = AUDIO_HW_IDLE;
  16. AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
  17. { // scope for auto-lock pattern
  18. AutoMutex lock(mHardwareLock);
  19. if (0 == mAudioHwDevs.size()) {
  20. mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
  21. //只要dev中含有get_master_volume,表明可以从库中获取master_volume的初值
  22. if (NULL != dev->get_master_volume) {
  23. float mv;
  24. if (OK == dev->get_master_volume(dev, &mv)) {
  25. mMasterVolume = mv;
  26. }
  27. }
  28. mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
  29. //只要dev中含有get_master_mute,表明可以从库中获取master_mute的初值
  30. if (NULL != dev->get_master_mute) {
  31. bool mm;
  32. if (OK == dev->get_master_mute(dev, &mm)) {
  33. mMasterMute = mm;
  34. }
  35. }
  36. }
  37. mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
  38. //设置master_volume的初值 到硬件中
  39. if ((NULL != dev->set_master_volume) &&
  40. (OK == dev->set_master_volume(dev, mMasterVolume))) {
  41. flags = static_cast<AudioHwDevice::Flags>(flags |
  42. AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
  43. }
  44. mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
  45. //设置master_mute的初值 到硬件中
  46. if ((NULL != dev->set_master_mute) &&
  47. (OK == dev->set_master_mute(dev, mMasterMute))) {
  48. flags = static_cast<AudioHwDevice::Flags>(flags |
  49. AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
  50. }
  51. mHardwareStatus = AUDIO_HW_IDLE;
  52. }
  53. audio_module_handle_t handle = nextUniqueId();
  54. mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
  55. return handle;
  56. }

这里对MasterVolume,、MasterMute进行二次初始化,即如果音频库是支持初值设置的,则以音频库中的值为主,否则就是AudioFlinger创建时的初始值。

@2 AudioFlinger::setMasterVolume 主音量设置流程

AudioFlinger::setMasterVolume的代码实现如下:

  1. status_t AudioFlinger::setMasterVolume(float value)
  2. {
  3. status_t ret = initCheck();
  4. //...
  5. Mutex::Autolock _l(mLock);
  6. mMasterVolume = value;
  7. for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
  8. AutoMutex lock(mHardwareLock);
  9. AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
  10. mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
  11. //直接将master_volume的值设置到硬件中
  12. if (dev->canSetMasterVolume()) {
  13. dev->hwDevice()->set_master_volume(dev->hwDevice(), value);
  14. }
  15. mHardwareStatus = AUDIO_HW_IDLE;
  16. }
  17. //将master_volume的值设置到各个播放线程中
  18. for (size_t i = 0; i < mPlaybackThreads.size(); i++)
  19. mPlaybackThreads.valueAt(i)->setMasterVolume(value);
  20. return NO_ERROR;
  21. }

这里PlaybackThread::setMasterVolume的代码实现如下:

  1. void AudioFlinger::PlaybackThread::setMasterVolume(float value)
  2. {
  3. Mutex::Autolock _l(mLock);
  4. // Don't apply master volume in SW if our HAL can do it for us.
  5. if (mOutput && mOutput->audioHwDev &&
  6. mOutput->audioHwDev->canSetMasterVolume()) {
  7. mMasterVolume = 1.0;
  8. } else {
  9. mMasterVolume = value;
  10. }
  11. }

可以看到都是直接操作HAL层的接口进行参数设置。

@3 AudioFlinger::setStreamVolume 流音量设置流程

 AudioFlinger::setStreamVolume的 代码实现如下:

  1. status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
  2. audio_io_handle_t output)
  3. {
  4. status_t status = checkStreamType(stream);
  5. AutoMutex lock(mLock);
  6. PlaybackThread *thread = NULL;
  7. if (output != AUDIO_IO_HANDLE_NONE) {
  8. thread = checkPlaybackThread_l(output);
  9. if (thread == NULL) {
  10. return BAD_VALUE;
  11. }
  12. }
  13. mStreamTypes[stream].volume = value;
  14. if (thread == NULL) {
  15. //未指定线程则全部播放线程 均设置
  16. for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
  17. mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
  18. }
  19. } else {
  20. //指定线程则直接设置
  21. thread->setStreamVolume(stream, value);
  22. }
  23. return NO_ERROR;
  24. }

继续分析播放线程的setStreamVolume方法,代码实现如下:

  1. void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
  2. {
  3. Mutex::Autolock _l(mLock);
  4. mStreamTypes[stream].volume = value;//赋值
  5. broadcast_l();
  6. }

实际上 每个播放线程中都有 mStreamTypes[stream].volume,和 AudioFlinger的mStreamTypes[stream].volume是一致的。

@4 AudioTrack volume的设置

 AudioTrack::setVolume的代码实现如下:

  1. status_t AudioTrack::setVolume(float volume)
  2. {
  3. return setVolume(volume, volume);
  4. }
  5. status_t AudioTrack::setVolume(float left, float right)
  6. {
  7. //...
  8. AutoMutex lock(mLock);
  9. mVolume[AUDIO_INTERLEAVE_LEFT] = left;
  10. mVolume[AUDIO_INTERLEAVE_RIGHT] = right;
  11. //这里会通过ClientProxy将音量参数设置到共享内存中
  12. //这里的mProxy =
  13. //new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF);
  14. mProxy->setVolumeLR(gain_minifloat_pack(gain_from_float(left), gain_from_float(right)));
  15. if (isOffloaded_l()) {
  16. mAudioTrack->signal();
  17. }
  18. return NO_ERROR;
  19. }

这里是把这个数据记录在mVolumeLR域中,创建Proxy时传递的Cblk参数就是共享内存的头部。

2.2 播放线程 加载音量设置 流程

@1 源码流程分析说明

这里分析时主要针对音量部分相关代码进行分析,代码实现如下:

  1. // prepareTracks_l() must be called with ThreadBase::mLock held
  2. AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
  3. Vector< sp<Track> > *tracksToRemove)
  4. {
  5. //...
  6. float masterVolume = mMasterVolume;
  7. bool masterMute = mMasterMute;
  8. if (masterMute) {//如果静音条件为真,则设置masterVolume=0
  9. masterVolume = 0;
  10. }
  11. //...
  12. mMixerBufferValid = false; // mMixerBuffer has no valid data until appropriate tracks found.
  13. mEffectBufferValid = false; // mEffectBuffer has no valid data until tracks found.
  14. for (size_t i=0 ; i<count ; i++) {
  15. const sp<Track> t = mActiveTracks[i].promote();
  16. if (t == 0) {
  17. continue;
  18. }
  19. // this const just means the local variable doesn't change
  20. Track* const track = t.get();
  21. //...
  22. { // local variable scope to avoid goto warning
  23. audio_track_cblk_t* cblk = track->cblk();
  24. int name = track->name();
  25. size_t desiredFrames;
  26. uint32_t sr = track->sampleRate();
  27. if (sr == mSampleRate) {
  28. desiredFrames = mNormalFrameCount;
  29. } else {
  30. // +1 for rounding and +1 for additional sample needed for interpolation
  31. desiredFrames = (mNormalFrameCount * sr) / mSampleRate + 1 + 1;
  32. desiredFrames += mAudioMixer->getUnreleasedFrames(track->name());
  33. }
  34. uint32_t minFrames = 1;
  35. if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing() &&
  36. (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY)) {
  37. minFrames = desiredFrames;
  38. }
  39. size_t framesReady = track->framesReady();
  40. if ((framesReady >= minFrames) && track->isReady() &&
  41. !track->isPaused() && !track->isTerminated())
  42. {
  43. mixedTracks++;
  44. //...
  45. // compute volume for this track
  46. uint32_t vl, vr; // in U8.24 integer format
  47. float vlf, vrf, vaf; // in [0.0, 1.0] float format
  48. if (track->isPausing() || mStreamTypes[track->streamType()].mute) {
  49. vl = vr = 0;
  50. vlf = vrf = vaf = 0.;
  51. if (track->isPausing()) {
  52. track->setPaused();
  53. }
  54. } else {
  55. // read original volumes with volume control
  56. //获取 StreamType Volume
  57. float typeVolume = mStreamTypes[track->streamType()].volume;
  58. float v = masterVolume * typeVolume;
  59. //获取共享内存代理
  60. AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy;
  61. //从共享内存中获得左右声道
  62. gain_minifloat_packed_t vlr = proxy->getVolumeLR();
  63. vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
  64. vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
  65. // track volumes come from shared memory, so can't be trusted and must be clamped
  66. //边界判断
  67. if (vlf > GAIN_FLOAT_UNITY) {
  68. ALOGV("Track left volume out of range: %.3g", vlf);
  69. vlf = GAIN_FLOAT_UNITY;
  70. }
  71. if (vrf > GAIN_FLOAT_UNITY) {
  72. ALOGV("Track right volume out of range: %.3g", vrf);
  73. vrf = GAIN_FLOAT_UNITY;
  74. }
  75. // now apply the master volume and stream type volume
  76. //放大系数:master_volume * stream_volume * AudioTrack_volume
  77. vlf *= v;
  78. vrf *= v;
  79. // assuming master volume and stream type volume each go up to 1.0,
  80. // then derive vl and vr as U8.24 versions for the effect chain
  81. //下面主要是左右声道转换成AUX单声道的一些逻辑运算
  82. const float scaleto8_24 = MAX_GAIN_INT * MAX_GAIN_INT;
  83. vl = (uint32_t) (scaleto8_24 * vlf);
  84. vr = (uint32_t) (scaleto8_24 * vrf);
  85. // vl and vr are now in U8.24 format
  86. uint16_t sendLevel = proxy->getSendLevel_U4_12();
  87. // send level comes from shared memory and so may be corrupt
  88. if (sendLevel > MAX_GAIN_INT) {
  89. ALOGV("Track send level out of range: %04X", sendLevel);
  90. sendLevel = MAX_GAIN_INT;
  91. }
  92. // vaf is represented as [0.0, 1.0] float by rescaling sendLevel
  93. vaf = v * sendLevel * (1. / MAX_GAIN_INT);
  94. }
  95. // Delegate volume control to effect in track effect chain if needed
  96. if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
  97. // Do not ramp volume if volume is controlled by effect
  98. param = AudioMixer::VOLUME;
  99. // Update remaining floating point volume levels
  100. vlf = (float)vl / (1 << 24);
  101. vrf = (float)vr / (1 << 24);
  102. track->mHasVolumeController = true;
  103. } else {
  104. // force no volume ramp when volume controller was just disabled or removed
  105. // from effect chain to avoid volume spike
  106. if (track->mHasVolumeController) {
  107. param = AudioMixer::VOLUME;
  108. }
  109. track->mHasVolumeController = false;
  110. }
  111. // XXX: these things DON'T need to be done each time
  112. mAudioMixer->setBufferProvider(name, track);
  113. mAudioMixer->enable(name);
  114. //关键点:通过参数设置将音量信息传递出去
  115. mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, &vlf);
  116. mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, &vrf);
  117. mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, &vaf);
  118. //设置其他参数
  119. //...
  120. // reset retry count
  121. track->mRetryCount = kMaxTrackRetries;
  122. if (mMixerStatusIgnoringFastTracks != MIXER_TRACKS_READY ||
  123. mixerStatus != MIXER_TRACKS_ENABLED) {
  124. mixerStatus = MIXER_TRACKS_READY;
  125. }
  126. } else {
  127. //...
  128. }
  129. } // local variable scope to avoid goto warning
  130. track_is_ready: ;
  131. }
  132. //...
  133. return mixerStatus;
  134. }

这里专注分析AudioMixer的 参数设置setParameter方法,代码实现如下:

  1. void AudioMixer::setParameter(int name, int target, int param, void *value)
  2. {
  3.     name -= TRACK0;
  4.     track_t& track = mState.tracks[name];
  5.     int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value));
  6.     int32_t *valueBuf = reinterpret_cast<int32_t*>(value);
  7.     switch (target) {
  8.     //...
  9.     case RAMP_VOLUME:
  10.     case VOLUME:
  11.         switch (param) {
  12.         case AUXLEVEL:
  13.             if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
  14.                     target == RAMP_VOLUME ? mState.frameCount : 0,
  15.                     &track.auxLevel, &track.prevAuxLevel, &track.auxInc,
  16.                     &track.mAuxLevel, &track.mPrevAuxLevel, &track.mAuxInc)) {
  17.                 invalidateState(1 << name);
  18.             }
  19.             break;
  20.         default:
  21.             if ((unsigned)param >= VOLUME0 && (unsigned)param < VOLUME0 + MAX_NUM_VOLUMES) {
  22.                 //setVolumeRampVariables主要是 float和int类型之间的转换的一些逻辑操作
  23.                 if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
  24.                         target == RAMP_VOLUME ? mState.frameCount : 0,
  25.                         &track.volume[param - VOLUME0], &track.prevVolume[param - VOLUME0],
  26.                         &track.volumeInc[param - VOLUME0],
  27.                         &track.mVolume[param - VOLUME0], &track.mPrevVolume[param - VOLUME0],
  28.                         &track.mVolumeInc[param - VOLUME0])) {
  29.                     invalidateState(1 << name);
  30.                 }
  31.             } else {
  32.                 LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
  33.             }
  34.         }
  35.         break;
  36.     default:
  37.         LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
  38.     }
  39. }

这里专注 invalidateState的实现,代码如下:

  1. void AudioMixer::invalidateState(uint32_t mask)
  2. {
  3.     if (mask != 0) {
  4.         mState.needsChanged |= mask;
  5.         mState.hook = process__validate;
  6.     }
  7. }

process__validate的实现如下:

  1. void AudioMixer::process__validate(state_t* state, int64_t pts)
  2. {
  3.     //...
  4.     // compute everything we need...
  5.     while (en) {
  6.         //...
  7.         if (n & NEEDS_MUTE) {
  8.             t.hook = track__nop;
  9.         } else {
  10.             if (n & NEEDS_AUX) {
  11.                 all16BitsStereoNoResample = false;
  12.             }
  13.             if (n & NEEDS_RESAMPLE) {
  14.                 all16BitsStereoNoResample = false;
  15.                 resampling = true;
  16.                 t.hook = getTrackHook(TRACKTYPE_RESAMPLE, t.mMixerChannelCount,
  17.                         t.mMixerInFormat, t.mMixerFormat);
  18.             } else {
  19.                 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
  20.                     t.hook = getTrackHook(
  21.                             t.mMixerChannelCount == 2 // TODO: MONO_HACK.
  22.                                 ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE,
  23.                             t.mMixerChannelCount,
  24.                             t.mMixerInFormat, t.mMixerFormat);
  25.                     all16BitsStereoNoResample = false;
  26.                 }
  27.                 if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
  28.                     t.hook = getTrackHook(TRACKTYPE_NORESAMPLE, t.mMixerChannelCount,
  29.                             t.mMixerInFormat, t.mMixerFormat);
  30.                 }
  31.             }
  32.         }
  33.     }
  34.     //...
  35. }

这里主要关注getTrackHook函数,代码实现如下:

  1. AudioMixer::hook_t AudioMixer::getTrackHook(int trackType, uint32_t channelCount,
  2.         audio_format_t mixerInFormat, audio_format_t mixerOutFormat __unused)
  3. {
  4.     if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
  5.         switch (trackType) {
  6.         //...
  7.         case TRACKTYPE_NORESAMPLE:
  8.             return track__16BitsStereo;
  9.         default:
  10.             break;
  11.         }
  12.     }
  13.     //...
  14.     return NULL;
  15. }

这里以关注TRACKTYPE_NORESAMPLE为例,最终会调用到track__16BitsStereo,代码实现如下:

  1. void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount,
  2.         int32_t* temp __unused, int32_t* aux)
  3. {
  4.     ALOGVV("track__16BitsStereo\n");
  5.     const int16_t *in = static_cast<const int16_t *>(t->in);
  6.     if (CC_UNLIKELY(aux != NULL)) {
  7.         //忽略AUX相关处理
  8.     } else {
  9.         // ramp gain
  10.         if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
  11.             int32_t vl = t->prevVolume[0];
  12.             int32_t vr = t->prevVolume[1];
  13.             const int32_t vlInc = t->volumeInc[0];左声道音量
  14.             const int32_t vrInc = t->volumeInc[1];右声道音量
  15.             do {
  16.                 *out++ += (vl >> 16) * (int32_t) *in++;
  17.                 *out++ += (vr >> 16) * (int32_t) *in++;
  18.                 vl += vlInc;
  19.                 vr += vrInc;
  20.             } while (--frameCount);
  21.             t->prevVolume[0] = vl;
  22.             t->prevVolume[1] = vr;
  23.             t->adjustVolumeRamp(false);
  24.         }
  25.         // constant gain
  26.         else {
  27.             const uint32_t vrl = t->volumeRL;
  28.             do {
  29.                 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
  30.                 in += 2;
  31.                 out[0] = mulAddRL(1, rl, vrl, out[0]);
  32.                 out[1] = mulAddRL(0, rl, vrl, out[1]);
  33.                 out += 2;
  34.             } while (--frameCount);
  35.         }
  36.     }
  37.     t->in = in;
  38. }

最终我们把数据存储到out中,这里的mulAddRL有三个,这里以下面的这个实现为例,代码如下:

  1. //另外2种实现模式类似
  2. static inline
  3. int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a)
  4. {
  5. #if USE_INLINE_ASSEMBLY
  6.     int32_t out;
  7.     if (left) {
  8.         asm( "smlawb %[out], %[v], %[inRL], %[a] \n"
  9.              : [out]"=r"(out)
  10.              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
  11.              : );
  12.     } else {
  13.         asm( "smlawt %[out], %[v], %[inRL], %[a] \n"
  14.              : [out]"=r"(out)
  15.              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
  16.              : );
  17.     }
  18.     return out;
  19. #else
  20.     int16_t s = left ? int16_t(inRL) : int16_t(inRL>>16);
  21.     return a + int32_t((int64_t(v) * s) >> 16);
  22. #endif
  23. }

虽然有可能会使用汇编语句来优化,但实际上逻辑是一致的(这里用outL表示左声道,outR表示右声道):

  • 左声道:outL = (inRL&0xffff * v) + outL //前16位
  • 右声道:outR = (inRL>>16    * v) + outR //后16位

最后outL 和 outR 合并成一个值(低16bit是左声道数据,高16bit是右声道数据)并返回。这里实际上是属于播放音频中MixerThread::prepareTracks_l中 tracks[x].hook中的一个操作,通过这操作有了prepareTrack_l设置的参数,在threadLoop_mix中进行混音。最后通过threadLoop_write用于混音后的音频输出,最后将填充好的Buffer写入到硬件中。

@2 关于MixerThread::prepareTracks_l涉及的track_t结构体的说明

代码实现如下:

  1. struct track_t {
  2. //...
  3. // TODO: Eventually remove legacy integer volume settings
  4. //int类型 普通声音
  5. union {
  6. int16_t volume[MAX_NUM_VOLUMES]; // U4.12 fixed point (top bit should be zero)
  7. int32_t volumeRL;
  8. };
  9. int32_t prevVolume[MAX_NUM_VOLUMES];
  10. int32_t volumeInc[MAX_NUM_VOLUMES];
  11. //...
  12. //int类型 aux声音
  13. int32_t auxInc;
  14. int32_t prevAuxLevel;
  15. int16_t auxLevel; // 0 <= auxLevel <= MAX_GAIN_INT, but signed for mul performance
  16. //...
  17. //float类型 普通声音
  18. float mVolume[MAX_NUM_VOLUMES]; // floating point set volume
  19. float mPrevVolume[MAX_NUM_VOLUMES]; // floating point previous volume
  20. float mVolumeInc[MAX_NUM_VOLUMES]; // floating point volume increment
  21. //...
  22. //float类型 aux声音
  23. float mAuxLevel; // floating point set aux level
  24. float mPrevAuxLevel; // floating point prev aux level
  25. float mAuxInc; // floating point aux increment
  26. //...
  27. };

这里aux的数据实际上就是 左右声道叠加在一起,通过特定处理后转换成 特定声道的方式。
这里我们可以发现,track_t结构体中共有4组音量变量。都是PreVolume,VolumeInc,Volume这种模式,这三种变量的意义如下图所示:

解读如下:

  • PreVolume:之前的音量初始值
  • VolumeInc:表示每次调节的步长
  • Volume:当前的音量 = master_volume * stream_volume * AudioTrack_volume
 
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/875961
推荐阅读
相关标签
  

闽ICP备14008679号