| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1 | /* | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 2 | ** | 
 | 3 | ** Copyright 2007, The Android Open Source Project | 
 | 4 | ** | 
 | 5 | ** Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 6 | ** you may not use this file except in compliance with the License. | 
 | 7 | ** You may obtain a copy of the License at | 
 | 8 | ** | 
 | 9 | **     http://www.apache.org/licenses/LICENSE-2.0 | 
 | 10 | ** | 
 | 11 | ** Unless required by applicable law or agreed to in writing, software | 
 | 12 | ** distributed under the License is distributed on an "AS IS" BASIS, | 
 | 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 14 | ** See the License for the specific language governing permissions and | 
 | 15 | ** limitations under the License. | 
 | 16 | */ | 
 | 17 |  | 
 | 18 | #define LOG_TAG "AudioMixer" | 
| Glenn Kasten | 7f5d335 | 2013-02-15 23:55:04 +0000 | [diff] [blame] | 19 | //#define LOG_NDEBUG 0 | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 20 |  | 
 | 21 | #include <stdint.h> | 
 | 22 | #include <string.h> | 
 | 23 | #include <stdlib.h> | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 24 | #include <math.h> | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 25 | #include <sys/types.h> | 
 | 26 |  | 
 | 27 | #include <utils/Errors.h> | 
 | 28 | #include <utils/Log.h> | 
 | 29 |  | 
| Glenn Kasten | f6b1678 | 2011-12-15 09:51:17 -0800 | [diff] [blame] | 30 | #include <cutils/compiler.h> | 
| Glenn Kasten | 5798d4e | 2012-03-08 12:18:35 -0800 | [diff] [blame] | 31 | #include <utils/Debug.h> | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 32 |  | 
 | 33 | #include <system/audio.h> | 
 | 34 |  | 
| Glenn Kasten | 3b21c50 | 2011-12-15 09:52:39 -0800 | [diff] [blame] | 35 | #include <audio_utils/primitives.h> | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 36 | #include <audio_utils/format.h> | 
| Andy Hung | 068561c | 2017-01-03 17:09:32 -0800 | [diff] [blame] | 37 | #include <media/AudioMixer.h> | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 38 |  | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 39 | #include "AudioMixerOps.h" | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 40 |  | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 41 | // The FCC_2 macro refers to the Fixed Channel Count of 2 for the legacy integer mixer. | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 42 | #ifndef FCC_2 | 
 | 43 | #define FCC_2 2 | 
 | 44 | #endif | 
 | 45 |  | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 46 | // Look for MONO_HACK for any Mono hack involving legacy mono channel to | 
 | 47 | // stereo channel conversion. | 
 | 48 |  | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 49 | /* VERY_VERY_VERBOSE_LOGGING will show exactly which process hook and track hook is | 
 | 50 |  * being used. This is a considerable amount of log spam, so don't enable unless you | 
 | 51 |  * are verifying the hook based code. | 
 | 52 |  */ | 
 | 53 | //#define VERY_VERY_VERBOSE_LOGGING | 
 | 54 | #ifdef VERY_VERY_VERBOSE_LOGGING | 
 | 55 | #define ALOGVV ALOGV | 
 | 56 | //define ALOGVV printf  // for test-mixer.cpp | 
 | 57 | #else | 
 | 58 | #define ALOGVV(a...) do { } while (0) | 
 | 59 | #endif | 
 | 60 |  | 
| Andy Hung | a08810b | 2014-07-16 21:53:43 -0700 | [diff] [blame] | 61 | #ifndef ARRAY_SIZE | 
 | 62 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) | 
 | 63 | #endif | 
 | 64 |  | 
| Andy Hung | 5b8fde7 | 2014-09-02 21:14:34 -0700 | [diff] [blame] | 65 | // Set kUseNewMixer to true to use the new mixer engine always. Otherwise the | 
 | 66 | // original code will be used for stereo sinks, the new mixer for multichannel. | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 67 | static constexpr bool kUseNewMixer = true; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 68 |  | 
 | 69 | // Set kUseFloat to true to allow floating input into the mixer engine. | 
 | 70 | // If kUseNewMixer is false, this is ignored or may be overridden internally | 
 | 71 | // because of downmix/upmix support. | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 72 | static constexpr bool kUseFloat = true; | 
 | 73 |  | 
 | 74 | #ifdef FLOAT_AUX | 
 | 75 | using TYPE_AUX = float; | 
 | 76 | static_assert(kUseNewMixer && kUseFloat, | 
 | 77 |         "kUseNewMixer and kUseFloat must be true for FLOAT_AUX option"); | 
 | 78 | #else | 
 | 79 | using TYPE_AUX = int32_t; // q4.27 | 
 | 80 | #endif | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 81 |  | 
| Andy Hung | 1b2fdcb | 2014-07-16 17:44:34 -0700 | [diff] [blame] | 82 | // Set to default copy buffer size in frames for input processing. | 
 | 83 | static const size_t kCopyBufferFrameCount = 256; | 
 | 84 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 85 | namespace android { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 86 |  | 
 | 87 | // ---------------------------------------------------------------------------- | 
| Andy Hung | 1b2fdcb | 2014-07-16 17:44:34 -0700 | [diff] [blame] | 88 |  | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 89 | static inline audio_format_t selectMixerInFormat(audio_format_t inputFormat __unused) { | 
 | 90 |     return kUseFloat && kUseNewMixer ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT; | 
 | 91 | } | 
 | 92 |  | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 93 | status_t AudioMixer::create( | 
 | 94 |         int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId) | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 95 | { | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 96 |     LOG_ALWAYS_FATAL_IF(exists(name), "name %d already exists", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 97 |  | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 98 |     if (!isValidChannelMask(channelMask)) { | 
 | 99 |         ALOGE("%s invalid channelMask: %#x", __func__, channelMask); | 
 | 100 |         return BAD_VALUE; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 101 |     } | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 102 |     if (!isValidFormat(format)) { | 
 | 103 |         ALOGE("%s invalid format: %#x", __func__, format); | 
 | 104 |         return BAD_VALUE; | 
 | 105 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 106 |  | 
 | 107 |     auto t = std::make_shared<Track>(); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 108 |     { | 
 | 109 |         // TODO: move initialization to the Track constructor. | 
| Glenn Kasten | deeb128 | 2012-03-25 11:59:31 -0700 | [diff] [blame] | 110 |         // assume default parameters for the track, except where noted below | 
| Glenn Kasten | deeb128 | 2012-03-25 11:59:31 -0700 | [diff] [blame] | 111 |         t->needs = 0; | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 112 |  | 
 | 113 |         // Integer volume. | 
 | 114 |         // Currently integer volume is kept for the legacy integer mixer. | 
 | 115 |         // Will be removed when the legacy mixer path is removed. | 
| Andy Hung | 97ae824 | 2014-05-30 10:35:47 -0700 | [diff] [blame] | 116 |         t->volume[0] = UNITY_GAIN_INT; | 
 | 117 |         t->volume[1] = UNITY_GAIN_INT; | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 118 |         t->prevVolume[0] = UNITY_GAIN_INT << 16; | 
 | 119 |         t->prevVolume[1] = UNITY_GAIN_INT << 16; | 
| Glenn Kasten | deeb128 | 2012-03-25 11:59:31 -0700 | [diff] [blame] | 120 |         t->volumeInc[0] = 0; | 
 | 121 |         t->volumeInc[1] = 0; | 
 | 122 |         t->auxLevel = 0; | 
 | 123 |         t->auxInc = 0; | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 124 |         t->prevAuxLevel = 0; | 
 | 125 |  | 
 | 126 |         // Floating point volume. | 
 | 127 |         t->mVolume[0] = UNITY_GAIN_FLOAT; | 
 | 128 |         t->mVolume[1] = UNITY_GAIN_FLOAT; | 
 | 129 |         t->mPrevVolume[0] = UNITY_GAIN_FLOAT; | 
 | 130 |         t->mPrevVolume[1] = UNITY_GAIN_FLOAT; | 
 | 131 |         t->mVolumeInc[0] = 0.; | 
 | 132 |         t->mVolumeInc[1] = 0.; | 
 | 133 |         t->mAuxLevel = 0.; | 
 | 134 |         t->mAuxInc = 0.; | 
 | 135 |         t->mPrevAuxLevel = 0.; | 
 | 136 |  | 
| Glenn Kasten | deeb128 | 2012-03-25 11:59:31 -0700 | [diff] [blame] | 137 |         // no initialization needed | 
| Glenn Kasten | deeb128 | 2012-03-25 11:59:31 -0700 | [diff] [blame] | 138 |         // t->frameCount | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 139 |         t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL; | 
 | 140 |         t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask); | 
 | 141 |         channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL; | 
| Andy Hung | 68112fc | 2014-05-14 14:13:23 -0700 | [diff] [blame] | 142 |         t->channelCount = audio_channel_count_from_out_mask(channelMask); | 
| Glenn Kasten | deeb128 | 2012-03-25 11:59:31 -0700 | [diff] [blame] | 143 |         t->enabled = false; | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 144 |         ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO, | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 145 |                 "Non-stereo channel mask: %d\n", channelMask); | 
| Andy Hung | 68112fc | 2014-05-14 14:13:23 -0700 | [diff] [blame] | 146 |         t->channelMask = channelMask; | 
| Jean-Michel Trivi | d06e132 | 2012-09-12 15:47:07 -0700 | [diff] [blame] | 147 |         t->sessionId = sessionId; | 
| Glenn Kasten | deeb128 | 2012-03-25 11:59:31 -0700 | [diff] [blame] | 148 |         // setBufferProvider(name, AudioBufferProvider *) is required before enable(name) | 
 | 149 |         t->bufferProvider = NULL; | 
 | 150 |         t->buffer.raw = NULL; | 
 | 151 |         // no initialization needed | 
 | 152 |         // t->buffer.frameCount | 
 | 153 |         t->hook = NULL; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 154 |         t->mIn = NULL; | 
| Glenn Kasten | deeb128 | 2012-03-25 11:59:31 -0700 | [diff] [blame] | 155 |         t->sampleRate = mSampleRate; | 
 | 156 |         // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name) | 
 | 157 |         t->mainBuffer = NULL; | 
 | 158 |         t->auxBuffer = NULL; | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 159 |         t->mInputBufferProvider = NULL; | 
| Andy Hung | 7882070 | 2014-02-28 16:23:02 -0800 | [diff] [blame] | 160 |         t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT; | 
| Andy Hung | e8a1ced | 2014-05-09 15:02:21 -0700 | [diff] [blame] | 161 |         t->mFormat = format; | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 162 |         t->mMixerInFormat = selectMixerInFormat(format); | 
 | 163 |         t->mDownmixRequiresFormat = AUDIO_FORMAT_INVALID; // no format required | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 164 |         t->mMixerChannelMask = audio_channel_mask_from_representation_and_bits( | 
 | 165 |                 AUDIO_CHANNEL_REPRESENTATION_POSITION, AUDIO_CHANNEL_OUT_STEREO); | 
 | 166 |         t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask); | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 167 |         t->mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT; | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 168 |         // haptic | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 169 |         t->mHapticPlaybackEnabled = false; | 
| jiabin | 77270b8 | 2018-12-18 15:41:29 -0800 | [diff] [blame] | 170 |         t->mHapticIntensity = HAPTIC_SCALE_NONE; | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 171 |         t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE; | 
 | 172 |         t->mMixerHapticChannelCount = 0; | 
 | 173 |         t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount; | 
 | 174 |         t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount; | 
 | 175 |         t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount; | 
 | 176 |         t->mAdjustNonDestructiveOutChannelCount = t->channelCount; | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 177 |         t->mKeepContractedChannels = false; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 178 |         // Check the downmixing (or upmixing) requirements. | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 179 |         status_t status = t->prepareForDownmix(); | 
| Andy Hung | 68112fc | 2014-05-14 14:13:23 -0700 | [diff] [blame] | 180 |         if (status != OK) { | 
 | 181 |             ALOGE("AudioMixer::getTrackName invalid channelMask (%#x)", channelMask); | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 182 |             return BAD_VALUE; | 
| Jean-Michel Trivi | 9bd2322 | 2012-04-16 13:43:48 -0700 | [diff] [blame] | 183 |         } | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 184 |         // prepareForDownmix() may change mDownmixRequiresFormat | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 185 |         ALOGVV("mMixerFormat:%#x  mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat); | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 186 |         t->prepareForReformat(); | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 187 |         t->prepareForAdjustChannelsNonDestructive(mFrameCount); | 
 | 188 |         t->prepareForAdjustChannels(); | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 189 |  | 
 | 190 |         mTracks[name] = t; | 
 | 191 |         return OK; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 192 |     } | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 193 | } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 194 |  | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 195 | // Called when channel masks have changed for a track name | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 196 | // TODO: Fix DownmixerBufferProvider not to (possibly) change mixer input format, | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 197 | // which will simplify this logic. | 
 | 198 | bool AudioMixer::setChannelMasks(int name, | 
 | 199 |         audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask) { | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 200 |     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 201 |     const std::shared_ptr<Track> &track = mTracks[name]; | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 202 |  | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 203 |     if (trackChannelMask == (track->channelMask | track->mHapticChannelMask) | 
 | 204 |             && mixerChannelMask == (track->mMixerChannelMask | track->mMixerHapticChannelMask)) { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 205 |         return false;  // no need to change | 
| Jean-Michel Trivi | 9bd2322 | 2012-04-16 13:43:48 -0700 | [diff] [blame] | 206 |     } | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 207 |     const audio_channel_mask_t hapticChannelMask = trackChannelMask & AUDIO_CHANNEL_HAPTIC_ALL; | 
 | 208 |     trackChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL; | 
 | 209 |     const audio_channel_mask_t mixerHapticChannelMask = mixerChannelMask & AUDIO_CHANNEL_HAPTIC_ALL; | 
 | 210 |     mixerChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL; | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 211 |     // always recompute for both channel masks even if only one has changed. | 
 | 212 |     const uint32_t trackChannelCount = audio_channel_count_from_out_mask(trackChannelMask); | 
 | 213 |     const uint32_t mixerChannelCount = audio_channel_count_from_out_mask(mixerChannelMask); | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 214 |     const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(hapticChannelMask); | 
 | 215 |     const uint32_t mixerHapticChannelCount = | 
 | 216 |             audio_channel_count_from_out_mask(mixerHapticChannelMask); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 217 |  | 
 | 218 |     ALOG_ASSERT((trackChannelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) | 
 | 219 |             && trackChannelCount | 
 | 220 |             && mixerChannelCount); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 221 |     track->channelMask = trackChannelMask; | 
 | 222 |     track->channelCount = trackChannelCount; | 
 | 223 |     track->mMixerChannelMask = mixerChannelMask; | 
 | 224 |     track->mMixerChannelCount = mixerChannelCount; | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 225 |     track->mHapticChannelMask = hapticChannelMask; | 
 | 226 |     track->mHapticChannelCount = hapticChannelCount; | 
 | 227 |     track->mMixerHapticChannelMask = mixerHapticChannelMask; | 
 | 228 |     track->mMixerHapticChannelCount = mixerHapticChannelCount; | 
 | 229 |  | 
 | 230 |     if (track->mHapticChannelCount > 0) { | 
 | 231 |         track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount; | 
 | 232 |         track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount; | 
 | 233 |         track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount; | 
 | 234 |         track->mAdjustNonDestructiveOutChannelCount = track->channelCount; | 
 | 235 |         track->mKeepContractedChannels = track->mHapticPlaybackEnabled; | 
 | 236 |     } else { | 
 | 237 |         track->mAdjustInChannelCount = 0; | 
 | 238 |         track->mAdjustOutChannelCount = 0; | 
 | 239 |         track->mAdjustNonDestructiveInChannelCount = 0; | 
 | 240 |         track->mAdjustNonDestructiveOutChannelCount = 0; | 
 | 241 |         track->mKeepContractedChannels = false; | 
 | 242 |     } | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 243 |  | 
 | 244 |     // channel masks have changed, does this track need a downmixer? | 
 | 245 |     // update to try using our desired format (if we aren't already using it) | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 246 |     const status_t status = track->prepareForDownmix(); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 247 |     ALOGE_IF(status != OK, | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 248 |             "prepareForDownmix error %d, track channel mask %#x, mixer channel mask %#x", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 249 |             status, track->channelMask, track->mMixerChannelMask); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 250 |  | 
| Yung Ti Su | 1a0ecc3 | 2018-05-07 11:09:15 +0800 | [diff] [blame] | 251 |     // always do reformat since channel mask changed, | 
 | 252 |     // do it after downmix since track format may change! | 
 | 253 |     track->prepareForReformat(); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 254 |  | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 255 |     track->prepareForAdjustChannelsNonDestructive(mFrameCount); | 
 | 256 |     track->prepareForAdjustChannels(); | 
 | 257 |  | 
| Yung Ti Su | b5d1195 | 2018-05-22 22:31:14 +0800 | [diff] [blame] | 258 |     if (track->mResampler.get() != nullptr) { | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 259 |         // resampler channels may have changed. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 260 |         const uint32_t resetToSampleRate = track->sampleRate; | 
 | 261 |         track->mResampler.reset(nullptr); | 
 | 262 |         track->sampleRate = mSampleRate; // without resampler, track rate is device sample rate. | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 263 |         // recreate the resampler with updated format, channels, saved sampleRate. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 264 |         track->setResampler(resetToSampleRate /*trackSampleRate*/, mSampleRate /*devSampleRate*/); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 265 |     } | 
 | 266 |     return true; | 
 | 267 | } | 
 | 268 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 269 | void AudioMixer::Track::unprepareForDownmix() { | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 270 |     ALOGV("AudioMixer::unprepareForDownmix(%p)", this); | 
| Jean-Michel Trivi | 9bd2322 | 2012-04-16 13:43:48 -0700 | [diff] [blame] | 271 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 272 |     if (mPostDownmixReformatBufferProvider.get() != nullptr) { | 
| Andy Hung | 8539589 | 2017-04-25 16:47:52 -0700 | [diff] [blame] | 273 |         // release any buffers held by the mPostDownmixReformatBufferProvider | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 274 |         // before deallocating the mDownmixerBufferProvider. | 
| Andy Hung | 8539589 | 2017-04-25 16:47:52 -0700 | [diff] [blame] | 275 |         mPostDownmixReformatBufferProvider->reset(); | 
 | 276 |     } | 
 | 277 |  | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 278 |     mDownmixRequiresFormat = AUDIO_FORMAT_INVALID; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 279 |     if (mDownmixerBufferProvider.get() != nullptr) { | 
| Jean-Michel Trivi | 9bd2322 | 2012-04-16 13:43:48 -0700 | [diff] [blame] | 280 |         // this track had previously been configured with a downmixer, delete it | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 281 |         mDownmixerBufferProvider.reset(nullptr); | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 282 |         reconfigureBufferProviders(); | 
| Jean-Michel Trivi | 9bd2322 | 2012-04-16 13:43:48 -0700 | [diff] [blame] | 283 |     } else { | 
 | 284 |         ALOGV(" nothing to do, no downmixer to delete"); | 
 | 285 |     } | 
 | 286 | } | 
 | 287 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 288 | status_t AudioMixer::Track::prepareForDownmix() | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 289 | { | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 290 |     ALOGV("AudioMixer::prepareForDownmix(%p) with mask 0x%x", | 
 | 291 |             this, channelMask); | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 292 |  | 
| Jean-Michel Trivi | 9bd2322 | 2012-04-16 13:43:48 -0700 | [diff] [blame] | 293 |     // discard the previous downmixer if there was one | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 294 |     unprepareForDownmix(); | 
| Andy Hung | 73e62e2 | 2015-04-20 12:06:38 -0700 | [diff] [blame] | 295 |     // MONO_HACK Only remix (upmix or downmix) if the track and mixer/device channel masks | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 296 |     // are not the same and not handled internally, as mono -> stereo currently is. | 
 | 297 |     if (channelMask == mMixerChannelMask | 
 | 298 |             || (channelMask == AUDIO_CHANNEL_OUT_MONO | 
 | 299 |                     && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO)) { | 
 | 300 |         return NO_ERROR; | 
 | 301 |     } | 
| Andy Hung | 650ceb9 | 2015-01-29 13:31:12 -0800 | [diff] [blame] | 302 |     // DownmixerBufferProvider is only used for position masks. | 
 | 303 |     if (audio_channel_mask_get_representation(channelMask) | 
 | 304 |                 == AUDIO_CHANNEL_REPRESENTATION_POSITION | 
 | 305 |             && DownmixerBufferProvider::isMultichannelCapable()) { | 
| Andy Hung | 6694255 | 2018-12-21 16:07:12 -0800 | [diff] [blame] | 306 |  | 
 | 307 |         // Check if we have a float or int16 downmixer, in that order. | 
 | 308 |         for (const audio_format_t format : { AUDIO_FORMAT_PCM_FLOAT, AUDIO_FORMAT_PCM_16_BIT }) { | 
 | 309 |             mDownmixerBufferProvider.reset(new DownmixerBufferProvider( | 
 | 310 |                     channelMask, mMixerChannelMask, | 
 | 311 |                     format, | 
 | 312 |                     sampleRate, sessionId, kCopyBufferFrameCount)); | 
 | 313 |             if (static_cast<DownmixerBufferProvider *>(mDownmixerBufferProvider.get()) | 
 | 314 |                     ->isValid()) { | 
 | 315 |                 mDownmixRequiresFormat = format; | 
 | 316 |                 reconfigureBufferProviders(); | 
 | 317 |                 return NO_ERROR; | 
 | 318 |             } | 
| Andy Hung | 34803d5 | 2014-07-16 21:41:35 -0700 | [diff] [blame] | 319 |         } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 320 |         // mDownmixerBufferProvider reset below. | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 321 |     } | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 322 |  | 
 | 323 |     // Effect downmixer does not accept the channel conversion.  Let's use our remixer. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 324 |     mDownmixerBufferProvider.reset(new RemixBufferProvider(channelMask, | 
 | 325 |             mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount)); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 326 |     // Remix always finds a conversion whereas Downmixer effect above may fail. | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 327 |     reconfigureBufferProviders(); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 328 |     return NO_ERROR; | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 329 | } | 
 | 330 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 331 | void AudioMixer::Track::unprepareForReformat() { | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 332 |     ALOGV("AudioMixer::unprepareForReformat(%p)", this); | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 333 |     bool requiresReconfigure = false; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 334 |     if (mReformatBufferProvider.get() != nullptr) { | 
 | 335 |         mReformatBufferProvider.reset(nullptr); | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 336 |         requiresReconfigure = true; | 
 | 337 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 338 |     if (mPostDownmixReformatBufferProvider.get() != nullptr) { | 
 | 339 |         mPostDownmixReformatBufferProvider.reset(nullptr); | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 340 |         requiresReconfigure = true; | 
 | 341 |     } | 
 | 342 |     if (requiresReconfigure) { | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 343 |         reconfigureBufferProviders(); | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 344 |     } | 
 | 345 | } | 
 | 346 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 347 | status_t AudioMixer::Track::prepareForReformat() | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 348 | { | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 349 |     ALOGV("AudioMixer::prepareForReformat(%p) with format %#x", this, mFormat); | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 350 |     // discard previous reformatters | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 351 |     unprepareForReformat(); | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 352 |     // only configure reformatters as needed | 
 | 353 |     const audio_format_t targetFormat = mDownmixRequiresFormat != AUDIO_FORMAT_INVALID | 
 | 354 |             ? mDownmixRequiresFormat : mMixerInFormat; | 
 | 355 |     bool requiresReconfigure = false; | 
 | 356 |     if (mFormat != targetFormat) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 357 |         mReformatBufferProvider.reset(new ReformatBufferProvider( | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 358 |                 audio_channel_count_from_out_mask(channelMask), | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 359 |                 mFormat, | 
 | 360 |                 targetFormat, | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 361 |                 kCopyBufferFrameCount)); | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 362 |         requiresReconfigure = true; | 
| Kevin Rocard | e053bfa | 2017-11-09 22:07:34 -0800 | [diff] [blame] | 363 |     } else if (mFormat == AUDIO_FORMAT_PCM_FLOAT) { | 
 | 364 |         // Input and output are floats, make sure application did not provide > 3db samples | 
 | 365 |         // that would break volume application (b/68099072) | 
 | 366 |         // TODO: add a trusted source flag to avoid the overhead | 
 | 367 |         mReformatBufferProvider.reset(new ClampFloatBufferProvider( | 
 | 368 |                 audio_channel_count_from_out_mask(channelMask), | 
 | 369 |                 kCopyBufferFrameCount)); | 
 | 370 |         requiresReconfigure = true; | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 371 |     } | 
 | 372 |     if (targetFormat != mMixerInFormat) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 373 |         mPostDownmixReformatBufferProvider.reset(new ReformatBufferProvider( | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 374 |                 audio_channel_count_from_out_mask(mMixerChannelMask), | 
 | 375 |                 targetFormat, | 
 | 376 |                 mMixerInFormat, | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 377 |                 kCopyBufferFrameCount)); | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 378 |         requiresReconfigure = true; | 
 | 379 |     } | 
 | 380 |     if (requiresReconfigure) { | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 381 |         reconfigureBufferProviders(); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 382 |     } | 
 | 383 |     return NO_ERROR; | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 384 | } | 
 | 385 |  | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 386 | void AudioMixer::Track::unprepareForAdjustChannels() | 
 | 387 | { | 
 | 388 |     ALOGV("AUDIOMIXER::unprepareForAdjustChannels"); | 
 | 389 |     if (mAdjustChannelsBufferProvider.get() != nullptr) { | 
 | 390 |         mAdjustChannelsBufferProvider.reset(nullptr); | 
 | 391 |         reconfigureBufferProviders(); | 
 | 392 |     } | 
 | 393 | } | 
 | 394 |  | 
 | 395 | status_t AudioMixer::Track::prepareForAdjustChannels() | 
 | 396 | { | 
 | 397 |     ALOGV("AudioMixer::prepareForAdjustChannels(%p) with inChannelCount: %u, outChannelCount: %u", | 
 | 398 |             this, mAdjustInChannelCount, mAdjustOutChannelCount); | 
 | 399 |     unprepareForAdjustChannels(); | 
 | 400 |     if (mAdjustInChannelCount != mAdjustOutChannelCount) { | 
 | 401 |         mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider( | 
 | 402 |                 mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, kCopyBufferFrameCount)); | 
 | 403 |         reconfigureBufferProviders(); | 
 | 404 |     } | 
 | 405 |     return NO_ERROR; | 
 | 406 | } | 
 | 407 |  | 
 | 408 | void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive() | 
 | 409 | { | 
 | 410 |     ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive"); | 
 | 411 |     if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) { | 
 | 412 |         mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr); | 
 | 413 |         reconfigureBufferProviders(); | 
 | 414 |     } | 
 | 415 | } | 
 | 416 |  | 
 | 417 | status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames) | 
 | 418 | { | 
 | 419 |     ALOGV("AudioMixer::prepareForAdjustChannelsNonDestructive(%p) with inChannelCount: %u, " | 
 | 420 |           "outChannelCount: %u, keepContractedChannels: %d", | 
 | 421 |             this, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount, | 
 | 422 |             mKeepContractedChannels); | 
 | 423 |     unprepareForAdjustChannelsNonDestructive(); | 
 | 424 |     if (mAdjustNonDestructiveInChannelCount != mAdjustNonDestructiveOutChannelCount) { | 
 | 425 |         uint8_t* buffer = mKeepContractedChannels | 
 | 426 |                 ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame( | 
 | 427 |                         mMixerChannelCount, mMixerFormat) | 
 | 428 |                 : NULL; | 
 | 429 |         mAdjustChannelsNonDestructiveBufferProvider.reset( | 
 | 430 |                 new AdjustChannelsNonDestructiveBufferProvider( | 
 | 431 |                         mFormat, | 
 | 432 |                         mAdjustNonDestructiveInChannelCount, | 
 | 433 |                         mAdjustNonDestructiveOutChannelCount, | 
 | 434 |                         mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID, | 
 | 435 |                         frames, | 
 | 436 |                         buffer)); | 
 | 437 |         reconfigureBufferProviders(); | 
 | 438 |     } | 
 | 439 |     return NO_ERROR; | 
 | 440 | } | 
 | 441 |  | 
 | 442 | void AudioMixer::Track::clearContractedBuffer() | 
 | 443 | { | 
 | 444 |     if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) { | 
 | 445 |         static_cast<AdjustChannelsNonDestructiveBufferProvider*>( | 
 | 446 |                 mAdjustChannelsNonDestructiveBufferProvider.get())->clearContractedFrames(); | 
 | 447 |     } | 
 | 448 | } | 
 | 449 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 450 | void AudioMixer::Track::reconfigureBufferProviders() | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 451 | { | 
| Andy Hung | 3a34df9 | 2018-08-21 12:32:30 -0700 | [diff] [blame] | 452 |     // configure from upstream to downstream buffer providers. | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 453 |     bufferProvider = mInputBufferProvider; | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 454 |     if (mAdjustChannelsBufferProvider.get() != nullptr) { | 
 | 455 |         mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider); | 
 | 456 |         bufferProvider = mAdjustChannelsBufferProvider.get(); | 
 | 457 |     } | 
 | 458 |     if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) { | 
 | 459 |         mAdjustChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider); | 
 | 460 |         bufferProvider = mAdjustChannelsNonDestructiveBufferProvider.get(); | 
 | 461 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 462 |     if (mReformatBufferProvider.get() != nullptr) { | 
| Andy Hung | 0f451e9 | 2014-08-04 21:28:47 -0700 | [diff] [blame] | 463 |         mReformatBufferProvider->setBufferProvider(bufferProvider); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 464 |         bufferProvider = mReformatBufferProvider.get(); | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 465 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 466 |     if (mDownmixerBufferProvider.get() != nullptr) { | 
 | 467 |         mDownmixerBufferProvider->setBufferProvider(bufferProvider); | 
 | 468 |         bufferProvider = mDownmixerBufferProvider.get(); | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 469 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 470 |     if (mPostDownmixReformatBufferProvider.get() != nullptr) { | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 471 |         mPostDownmixReformatBufferProvider->setBufferProvider(bufferProvider); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 472 |         bufferProvider = mPostDownmixReformatBufferProvider.get(); | 
| Andy Hung | 7f47549 | 2014-08-25 16:36:37 -0700 | [diff] [blame] | 473 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 474 |     if (mTimestretchBufferProvider.get() != nullptr) { | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 475 |         mTimestretchBufferProvider->setBufferProvider(bufferProvider); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 476 |         bufferProvider = mTimestretchBufferProvider.get(); | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 477 |     } | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 478 | } | 
 | 479 |  | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 480 | void AudioMixer::destroy(int name) | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 481 | { | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 482 |     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name); | 
| Glenn Kasten | 237a624 | 2011-12-15 15:32:27 -0800 | [diff] [blame] | 483 |     ALOGV("deleteTrackName(%d)", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 484 |  | 
 | 485 |     if (mTracks[name]->enabled) { | 
 | 486 |         invalidate(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 487 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 488 |     mTracks.erase(name); // deallocate track | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 489 | } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 490 |  | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 491 | void AudioMixer::enable(int name) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 492 | { | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 493 |     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 494 |     const std::shared_ptr<Track> &track = mTracks[name]; | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 495 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 496 |     if (!track->enabled) { | 
 | 497 |         track->enabled = true; | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 498 |         ALOGV("enable(%d)", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 499 |         invalidate(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 500 |     } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 501 | } | 
 | 502 |  | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 503 | void AudioMixer::disable(int name) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 504 | { | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 505 |     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 506 |     const std::shared_ptr<Track> &track = mTracks[name]; | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 507 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 508 |     if (track->enabled) { | 
 | 509 |         track->enabled = false; | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 510 |         ALOGV("disable(%d)", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 511 |         invalidate(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 512 |     } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 513 | } | 
 | 514 |  | 
| Andy Hung | 5866a3b | 2014-05-29 21:33:13 -0700 | [diff] [blame] | 515 | /* Sets the volume ramp variables for the AudioMixer. | 
 | 516 |  * | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 517 |  * The volume ramp variables are used to transition from the previous | 
 | 518 |  * volume to the set volume.  ramp controls the duration of the transition. | 
 | 519 |  * Its value is typically one state framecount period, but may also be 0, | 
 | 520 |  * meaning "immediate." | 
| Andy Hung | 5866a3b | 2014-05-29 21:33:13 -0700 | [diff] [blame] | 521 |  * | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 522 |  * FIXME: 1) Volume ramp is enabled only if there is a nonzero integer increment | 
 | 523 |  * even if there is a nonzero floating point increment (in that case, the volume | 
 | 524 |  * change is immediate).  This restriction should be changed when the legacy mixer | 
 | 525 |  * is removed (see #2). | 
 | 526 |  * FIXME: 2) Integer volume variables are used for Legacy mixing and should be removed | 
 | 527 |  * when no longer needed. | 
 | 528 |  * | 
 | 529 |  * @param newVolume set volume target in floating point [0.0, 1.0]. | 
 | 530 |  * @param ramp number of frames to increment over. if ramp is 0, the volume | 
 | 531 |  * should be set immediately.  Currently ramp should not exceed 65535 (frames). | 
 | 532 |  * @param pIntSetVolume pointer to the U4.12 integer target volume, set on return. | 
 | 533 |  * @param pIntPrevVolume pointer to the U4.28 integer previous volume, set on return. | 
 | 534 |  * @param pIntVolumeInc pointer to the U4.28 increment per output audio frame, set on return. | 
 | 535 |  * @param pSetVolume pointer to the float target volume, set on return. | 
 | 536 |  * @param pPrevVolume pointer to the float previous volume, set on return. | 
 | 537 |  * @param pVolumeInc pointer to the float increment per output audio frame, set on return. | 
| Andy Hung | 5866a3b | 2014-05-29 21:33:13 -0700 | [diff] [blame] | 538 |  * @return true if the volume has changed, false if volume is same. | 
 | 539 |  */ | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 540 | static inline bool setVolumeRampVariables(float newVolume, int32_t ramp, | 
 | 541 |         int16_t *pIntSetVolume, int32_t *pIntPrevVolume, int32_t *pIntVolumeInc, | 
 | 542 |         float *pSetVolume, float *pPrevVolume, float *pVolumeInc) { | 
| Andy Hung | e09c994 | 2015-05-08 16:58:13 -0700 | [diff] [blame] | 543 |     // check floating point volume to see if it is identical to the previously | 
 | 544 |     // set volume. | 
 | 545 |     // We do not use a tolerance here (and reject changes too small) | 
 | 546 |     // as it may be confusing to use a different value than the one set. | 
 | 547 |     // If the resulting volume is too small to ramp, it is a direct set of the volume. | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 548 |     if (newVolume == *pSetVolume) { | 
| Andy Hung | 5866a3b | 2014-05-29 21:33:13 -0700 | [diff] [blame] | 549 |         return false; | 
 | 550 |     } | 
| Andy Hung | e09c994 | 2015-05-08 16:58:13 -0700 | [diff] [blame] | 551 |     if (newVolume < 0) { | 
 | 552 |         newVolume = 0; // should not have negative volumes | 
| Andy Hung | 5866a3b | 2014-05-29 21:33:13 -0700 | [diff] [blame] | 553 |     } else { | 
| Andy Hung | e09c994 | 2015-05-08 16:58:13 -0700 | [diff] [blame] | 554 |         switch (fpclassify(newVolume)) { | 
 | 555 |         case FP_SUBNORMAL: | 
 | 556 |         case FP_NAN: | 
 | 557 |             newVolume = 0; | 
 | 558 |             break; | 
 | 559 |         case FP_ZERO: | 
 | 560 |             break; // zero volume is fine | 
 | 561 |         case FP_INFINITE: | 
 | 562 |             // Infinite volume could be handled consistently since | 
 | 563 |             // floating point math saturates at infinities, | 
 | 564 |             // but we limit volume to unity gain float. | 
 | 565 |             // ramp = 0; break; | 
 | 566 |             // | 
 | 567 |             newVolume = AudioMixer::UNITY_GAIN_FLOAT; | 
 | 568 |             break; | 
 | 569 |         case FP_NORMAL: | 
 | 570 |         default: | 
 | 571 |             // Floating point does not have problems with overflow wrap | 
 | 572 |             // that integer has.  However, we limit the volume to | 
 | 573 |             // unity gain here. | 
 | 574 |             // TODO: Revisit the volume limitation and perhaps parameterize. | 
 | 575 |             if (newVolume > AudioMixer::UNITY_GAIN_FLOAT) { | 
 | 576 |                 newVolume = AudioMixer::UNITY_GAIN_FLOAT; | 
 | 577 |             } | 
 | 578 |             break; | 
 | 579 |         } | 
| Andy Hung | 5866a3b | 2014-05-29 21:33:13 -0700 | [diff] [blame] | 580 |     } | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 581 |  | 
| Andy Hung | e09c994 | 2015-05-08 16:58:13 -0700 | [diff] [blame] | 582 |     // set floating point volume ramp | 
 | 583 |     if (ramp != 0) { | 
 | 584 |         // when the ramp completes, *pPrevVolume is set to *pSetVolume, so there | 
 | 585 |         // is no computational mismatch; hence equality is checked here. | 
 | 586 |         ALOGD_IF(*pPrevVolume != *pSetVolume, "previous float ramp hasn't finished," | 
 | 587 |                 " prev:%f  set_to:%f", *pPrevVolume, *pSetVolume); | 
 | 588 |         const float inc = (newVolume - *pPrevVolume) / ramp; // could be inf, nan, subnormal | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 589 |         // could be inf, cannot be nan, subnormal | 
 | 590 |         const float maxv = std::max(newVolume, *pPrevVolume); | 
| Andy Hung | e09c994 | 2015-05-08 16:58:13 -0700 | [diff] [blame] | 591 |  | 
 | 592 |         if (isnormal(inc) // inc must be a normal number (no subnormals, infinite, nan) | 
 | 593 |                 && maxv + inc != maxv) { // inc must make forward progress | 
 | 594 |             *pVolumeInc = inc; | 
 | 595 |             // ramp is set now. | 
 | 596 |             // Note: if newVolume is 0, then near the end of the ramp, | 
 | 597 |             // it may be possible that the ramped volume may be subnormal or | 
 | 598 |             // temporarily negative by a small amount or subnormal due to floating | 
 | 599 |             // point inaccuracies. | 
 | 600 |         } else { | 
 | 601 |             ramp = 0; // ramp not allowed | 
 | 602 |         } | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 603 |     } | 
| Andy Hung | e09c994 | 2015-05-08 16:58:13 -0700 | [diff] [blame] | 604 |  | 
 | 605 |     // compute and check integer volume, no need to check negative values | 
 | 606 |     // The integer volume is limited to "unity_gain" to avoid wrapping and other | 
 | 607 |     // audio artifacts, so it never reaches the range limit of U4.28. | 
 | 608 |     // We safely use signed 16 and 32 bit integers here. | 
 | 609 |     const float scaledVolume = newVolume * AudioMixer::UNITY_GAIN_INT; // not neg, subnormal, nan | 
 | 610 |     const int32_t intVolume = (scaledVolume >= (float)AudioMixer::UNITY_GAIN_INT) ? | 
 | 611 |             AudioMixer::UNITY_GAIN_INT : (int32_t)scaledVolume; | 
 | 612 |  | 
 | 613 |     // set integer volume ramp | 
 | 614 |     if (ramp != 0) { | 
 | 615 |         // integer volume is U4.12 (to use 16 bit multiplies), but ramping uses U4.28. | 
 | 616 |         // when the ramp completes, *pIntPrevVolume is set to *pIntSetVolume << 16, so there | 
 | 617 |         // is no computational mismatch; hence equality is checked here. | 
 | 618 |         ALOGD_IF(*pIntPrevVolume != *pIntSetVolume << 16, "previous int ramp hasn't finished," | 
 | 619 |                 " prev:%d  set_to:%d", *pIntPrevVolume, *pIntSetVolume << 16); | 
 | 620 |         const int32_t inc = ((intVolume << 16) - *pIntPrevVolume) / ramp; | 
 | 621 |  | 
 | 622 |         if (inc != 0) { // inc must make forward progress | 
 | 623 |             *pIntVolumeInc = inc; | 
 | 624 |         } else { | 
 | 625 |             ramp = 0; // ramp not allowed | 
 | 626 |         } | 
 | 627 |     } | 
 | 628 |  | 
 | 629 |     // if no ramp, or ramp not allowed, then clear float and integer increments | 
 | 630 |     if (ramp == 0) { | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 631 |         *pVolumeInc = 0; | 
 | 632 |         *pPrevVolume = newVolume; | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 633 |         *pIntVolumeInc = 0; | 
 | 634 |         *pIntPrevVolume = intVolume << 16; | 
 | 635 |     } | 
| Andy Hung | e09c994 | 2015-05-08 16:58:13 -0700 | [diff] [blame] | 636 |     *pSetVolume = newVolume; | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 637 |     *pIntSetVolume = intVolume; | 
| Andy Hung | 5866a3b | 2014-05-29 21:33:13 -0700 | [diff] [blame] | 638 |     return true; | 
 | 639 | } | 
 | 640 |  | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 641 | void AudioMixer::setParameter(int name, int target, int param, void *value) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 642 | { | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 643 |     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 644 |     const std::shared_ptr<Track> &track = mTracks[name]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 645 |  | 
| Kévin PETIT | 377b2ec | 2014-02-03 12:35:36 +0000 | [diff] [blame] | 646 |     int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value)); | 
 | 647 |     int32_t *valueBuf = reinterpret_cast<int32_t*>(value); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 648 |  | 
 | 649 |     switch (target) { | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 650 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 651 |     case TRACK: | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 652 |         switch (param) { | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 653 |         case CHANNEL_MASK: { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 654 |             const audio_channel_mask_t trackChannelMask = | 
 | 655 |                 static_cast<audio_channel_mask_t>(valueInt); | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 656 |             if (setChannelMasks(name, trackChannelMask, | 
 | 657 |                     (track->mMixerChannelMask | track->mMixerHapticChannelMask))) { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 658 |                 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", trackChannelMask); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 659 |                 invalidate(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 660 |             } | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 661 |             } break; | 
 | 662 |         case MAIN_BUFFER: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 663 |             if (track->mainBuffer != valueBuf) { | 
 | 664 |                 track->mainBuffer = valueBuf; | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 665 |                 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf); | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 666 |                 if (track->mKeepContractedChannels) { | 
 | 667 |                     track->prepareForAdjustChannelsNonDestructive(mFrameCount); | 
 | 668 |                 } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 669 |                 invalidate(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 670 |             } | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 671 |             break; | 
 | 672 |         case AUX_BUFFER: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 673 |             if (track->auxBuffer != valueBuf) { | 
 | 674 |                 track->auxBuffer = valueBuf; | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 675 |                 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 676 |                 invalidate(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 677 |             } | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 678 |             break; | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 679 |         case FORMAT: { | 
 | 680 |             audio_format_t format = static_cast<audio_format_t>(valueInt); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 681 |             if (track->mFormat != format) { | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 682 |                 ALOG_ASSERT(audio_is_linear_pcm(format), "Invalid format %#x", format); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 683 |                 track->mFormat = format; | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 684 |                 ALOGV("setParameter(TRACK, FORMAT, %#x)", format); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 685 |                 track->prepareForReformat(); | 
 | 686 |                 invalidate(); | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 687 |             } | 
 | 688 |             } break; | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 689 |         // FIXME do we want to support setting the downmix type from AudioFlinger? | 
 | 690 |         //         for a specific track? or per mixer? | 
 | 691 |         /* case DOWNMIX_TYPE: | 
 | 692 |             break          */ | 
| Andy Hung | 7882070 | 2014-02-28 16:23:02 -0800 | [diff] [blame] | 693 |         case MIXER_FORMAT: { | 
| Andy Hung | a1ab7cc | 2014-02-24 19:26:52 -0800 | [diff] [blame] | 694 |             audio_format_t format = static_cast<audio_format_t>(valueInt); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 695 |             if (track->mMixerFormat != format) { | 
 | 696 |                 track->mMixerFormat = format; | 
| Andy Hung | 7882070 | 2014-02-28 16:23:02 -0800 | [diff] [blame] | 697 |                 ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format); | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 698 |                 if (track->mKeepContractedChannels) { | 
 | 699 |                     track->prepareForAdjustChannelsNonDestructive(mFrameCount); | 
 | 700 |                 } | 
| Andy Hung | a1ab7cc | 2014-02-24 19:26:52 -0800 | [diff] [blame] | 701 |             } | 
 | 702 |             } break; | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 703 |         case MIXER_CHANNEL_MASK: { | 
 | 704 |             const audio_channel_mask_t mixerChannelMask = | 
 | 705 |                     static_cast<audio_channel_mask_t>(valueInt); | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 706 |             if (setChannelMasks(name, track->channelMask | track->mHapticChannelMask, | 
 | 707 |                     mixerChannelMask)) { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 708 |                 ALOGV("setParameter(TRACK, MIXER_CHANNEL_MASK, %#x)", mixerChannelMask); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 709 |                 invalidate(); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 710 |             } | 
 | 711 |             } break; | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 712 |         case HAPTIC_ENABLED: { | 
 | 713 |             const bool hapticPlaybackEnabled = static_cast<bool>(valueInt); | 
 | 714 |             if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) { | 
 | 715 |                 track->mHapticPlaybackEnabled = hapticPlaybackEnabled; | 
 | 716 |                 track->mKeepContractedChannels = hapticPlaybackEnabled; | 
 | 717 |                 track->prepareForAdjustChannelsNonDestructive(mFrameCount); | 
 | 718 |                 track->prepareForAdjustChannels(); | 
 | 719 |             } | 
 | 720 |             } break; | 
| jiabin | 77270b8 | 2018-12-18 15:41:29 -0800 | [diff] [blame] | 721 |         case HAPTIC_INTENSITY: { | 
 | 722 |             const haptic_intensity_t hapticIntensity = static_cast<haptic_intensity_t>(valueInt); | 
 | 723 |             if (track->mHapticIntensity != hapticIntensity) { | 
 | 724 |                 track->mHapticIntensity = hapticIntensity; | 
 | 725 |             } | 
 | 726 |             } break; | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 727 |         default: | 
| Glenn Kasten | adad3d7 | 2014-02-21 14:51:43 -0800 | [diff] [blame] | 728 |             LOG_ALWAYS_FATAL("setParameter track: bad param %d", param); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 729 |         } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 730 |         break; | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 731 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 732 |     case RESAMPLE: | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 733 |         switch (param) { | 
 | 734 |         case SAMPLE_RATE: | 
| Glenn Kasten | 5798d4e | 2012-03-08 12:18:35 -0800 | [diff] [blame] | 735 |             ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 736 |             if (track->setResampler(uint32_t(valueInt), mSampleRate)) { | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 737 |                 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)", | 
 | 738 |                         uint32_t(valueInt)); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 739 |                 invalidate(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 740 |             } | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 741 |             break; | 
 | 742 |         case RESET: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 743 |             track->resetResampler(); | 
 | 744 |             invalidate(); | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 745 |             break; | 
| Glenn Kasten | 4e2293f | 2012-04-12 09:39:07 -0700 | [diff] [blame] | 746 |         case REMOVE: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 747 |             track->mResampler.reset(nullptr); | 
 | 748 |             track->sampleRate = mSampleRate; | 
 | 749 |             invalidate(); | 
| Glenn Kasten | 4e2293f | 2012-04-12 09:39:07 -0700 | [diff] [blame] | 750 |             break; | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 751 |         default: | 
| Glenn Kasten | adad3d7 | 2014-02-21 14:51:43 -0800 | [diff] [blame] | 752 |             LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param); | 
| Eric Laurent | 243f5f9 | 2011-02-28 16:52:51 -0800 | [diff] [blame] | 753 |         } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 754 |         break; | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 755 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 756 |     case RAMP_VOLUME: | 
 | 757 |     case VOLUME: | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 758 |         switch (param) { | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 759 |         case AUXLEVEL: | 
| Andy Hung | 6be4940 | 2014-05-30 10:42:03 -0700 | [diff] [blame] | 760 |             if (setVolumeRampVariables(*reinterpret_cast<float*>(value), | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 761 |                     target == RAMP_VOLUME ? mFrameCount : 0, | 
 | 762 |                     &track->auxLevel, &track->prevAuxLevel, &track->auxInc, | 
 | 763 |                     &track->mAuxLevel, &track->mPrevAuxLevel, &track->mAuxInc)) { | 
| Andy Hung | 5866a3b | 2014-05-29 21:33:13 -0700 | [diff] [blame] | 764 |                 ALOGV("setParameter(%s, AUXLEVEL: %04x)", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 765 |                         target == VOLUME ? "VOLUME" : "RAMP_VOLUME", track->auxLevel); | 
 | 766 |                 invalidate(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 767 |             } | 
| Glenn Kasten | 9c56d4a | 2011-12-19 15:06:39 -0800 | [diff] [blame] | 768 |             break; | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 769 |         default: | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 770 |             if ((unsigned)param >= VOLUME0 && (unsigned)param < VOLUME0 + MAX_NUM_VOLUMES) { | 
 | 771 |                 if (setVolumeRampVariables(*reinterpret_cast<float*>(value), | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 772 |                         target == RAMP_VOLUME ? mFrameCount : 0, | 
 | 773 |                         &track->volume[param - VOLUME0], | 
 | 774 |                         &track->prevVolume[param - VOLUME0], | 
 | 775 |                         &track->volumeInc[param - VOLUME0], | 
 | 776 |                         &track->mVolume[param - VOLUME0], | 
 | 777 |                         &track->mPrevVolume[param - VOLUME0], | 
 | 778 |                         &track->mVolumeInc[param - VOLUME0])) { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 779 |                     ALOGV("setParameter(%s, VOLUME%d: %04x)", | 
 | 780 |                             target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0, | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 781 |                                     track->volume[param - VOLUME0]); | 
 | 782 |                     invalidate(); | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 783 |                 } | 
 | 784 |             } else { | 
 | 785 |                 LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param); | 
 | 786 |             } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 787 |         } | 
 | 788 |         break; | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 789 |         case TIMESTRETCH: | 
 | 790 |             switch (param) { | 
 | 791 |             case PLAYBACK_RATE: { | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 792 |                 const AudioPlaybackRate *playbackRate = | 
 | 793 |                         reinterpret_cast<AudioPlaybackRate*>(value); | 
| Ricardo Garcia | 6c7f062 | 2015-04-30 18:39:16 -0700 | [diff] [blame] | 794 |                 ALOGW_IF(!isAudioPlaybackRateValid(*playbackRate), | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 795 |                         "bad parameters speed %f, pitch %f", | 
 | 796 |                         playbackRate->mSpeed, playbackRate->mPitch); | 
 | 797 |                 if (track->setPlaybackRate(*playbackRate)) { | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 798 |                     ALOGV("setParameter(TIMESTRETCH, PLAYBACK_RATE, STRETCH_MODE, FALLBACK_MODE " | 
 | 799 |                             "%f %f %d %d", | 
 | 800 |                             playbackRate->mSpeed, | 
 | 801 |                             playbackRate->mPitch, | 
 | 802 |                             playbackRate->mStretchMode, | 
 | 803 |                             playbackRate->mFallbackMode); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 804 |                     // invalidate();  (should not require reconfigure) | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 805 |                 } | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 806 |             } break; | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 807 |             default: | 
 | 808 |                 LOG_ALWAYS_FATAL("setParameter timestretch: bad param %d", param); | 
 | 809 |             } | 
 | 810 |             break; | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 811 |  | 
 | 812 |     default: | 
| Glenn Kasten | adad3d7 | 2014-02-21 14:51:43 -0800 | [diff] [blame] | 813 |         LOG_ALWAYS_FATAL("setParameter: bad target %d", target); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 814 |     } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 815 | } | 
 | 816 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 817 | bool AudioMixer::Track::setResampler(uint32_t trackSampleRate, uint32_t devSampleRate) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 818 | { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 819 |     if (trackSampleRate != devSampleRate || mResampler.get() != nullptr) { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 820 |         if (sampleRate != trackSampleRate) { | 
 | 821 |             sampleRate = trackSampleRate; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 822 |             if (mResampler.get() == nullptr) { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 823 |                 ALOGV("Creating resampler from track %d Hz to device %d Hz", | 
 | 824 |                         trackSampleRate, devSampleRate); | 
| Glenn Kasten | ac60205 | 2012-10-01 14:04:31 -0700 | [diff] [blame] | 825 |                 AudioResampler::src_quality quality; | 
 | 826 |                 // force lowest quality level resampler if use case isn't music or video | 
 | 827 |                 // FIXME this is flawed for dynamic sample rates, as we choose the resampler | 
 | 828 |                 // quality level based on the initial ratio, but that could change later. | 
 | 829 |                 // Should have a way to distinguish tracks with static ratios vs. dynamic ratios. | 
| Andy Hung | db4c031 | 2015-05-06 08:46:52 -0700 | [diff] [blame] | 830 |                 if (isMusicRate(trackSampleRate)) { | 
| Glenn Kasten | ac60205 | 2012-10-01 14:04:31 -0700 | [diff] [blame] | 831 |                     quality = AudioResampler::DEFAULT_QUALITY; | 
| Andy Hung | db4c031 | 2015-05-06 08:46:52 -0700 | [diff] [blame] | 832 |                 } else { | 
 | 833 |                     quality = AudioResampler::DYN_LOW_QUALITY; | 
| Glenn Kasten | ac60205 | 2012-10-01 14:04:31 -0700 | [diff] [blame] | 834 |                 } | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 835 |  | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 836 |                 // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer | 
 | 837 |                 // but if none exists, it is the channel count (1 for mono). | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 838 |                 const int resamplerChannelCount = mDownmixerBufferProvider.get() != nullptr | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 839 |                         ? mMixerChannelCount : channelCount; | 
| Andy Hung | 9a59276 | 2014-07-21 21:56:01 -0700 | [diff] [blame] | 840 |                 ALOGVV("Creating resampler:" | 
 | 841 |                         " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n", | 
 | 842 |                         mMixerInFormat, resamplerChannelCount, devSampleRate, quality); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 843 |                 mResampler.reset(AudioResampler::create( | 
| Andy Hung | 3348e36 | 2014-07-07 10:21:44 -0700 | [diff] [blame] | 844 |                         mMixerInFormat, | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 845 |                         resamplerChannelCount, | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 846 |                         devSampleRate, quality)); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 847 |             } | 
 | 848 |             return true; | 
 | 849 |         } | 
 | 850 |     } | 
 | 851 |     return false; | 
 | 852 | } | 
 | 853 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 854 | bool AudioMixer::Track::setPlaybackRate(const AudioPlaybackRate &playbackRate) | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 855 | { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 856 |     if ((mTimestretchBufferProvider.get() == nullptr && | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 857 |             fabs(playbackRate.mSpeed - mPlaybackRate.mSpeed) < AUDIO_TIMESTRETCH_SPEED_MIN_DELTA && | 
 | 858 |             fabs(playbackRate.mPitch - mPlaybackRate.mPitch) < AUDIO_TIMESTRETCH_PITCH_MIN_DELTA) || | 
 | 859 |             isAudioPlaybackRateEqual(playbackRate, mPlaybackRate)) { | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 860 |         return false; | 
 | 861 |     } | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 862 |     mPlaybackRate = playbackRate; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 863 |     if (mTimestretchBufferProvider.get() == nullptr) { | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 864 |         // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer | 
 | 865 |         // but if none exists, it is the channel count (1 for mono). | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 866 |         const int timestretchChannelCount = mDownmixerBufferProvider.get() != nullptr | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 867 |                 ? mMixerChannelCount : channelCount; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 868 |         mTimestretchBufferProvider.reset(new TimestretchBufferProvider(timestretchChannelCount, | 
 | 869 |                 mMixerInFormat, sampleRate, playbackRate)); | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 870 |         reconfigureBufferProviders(); | 
 | 871 |     } else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 872 |         static_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider.get()) | 
| Ricardo Garcia | 5a8a95d | 2015-04-18 14:47:04 -0700 | [diff] [blame] | 873 |                 ->setPlaybackRate(playbackRate); | 
| Andy Hung | c5656cc | 2015-03-26 19:04:33 -0700 | [diff] [blame] | 874 |     } | 
 | 875 |     return true; | 
 | 876 | } | 
 | 877 |  | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 878 | /* Checks to see if the volume ramp has completed and clears the increment | 
 | 879 |  * variables appropriately. | 
 | 880 |  * | 
 | 881 |  * FIXME: There is code to handle int/float ramp variable switchover should it not | 
 | 882 |  * complete within a mixer buffer processing call, but it is preferred to avoid switchover | 
 | 883 |  * due to precision issues.  The switchover code is included for legacy code purposes | 
 | 884 |  * and can be removed once the integer volume is removed. | 
 | 885 |  * | 
 | 886 |  * It is not sufficient to clear only the volumeInc integer variable because | 
 | 887 |  * if one channel requires ramping, all channels are ramped. | 
 | 888 |  * | 
 | 889 |  * There is a bit of duplicated code here, but it keeps backward compatibility. | 
 | 890 |  */ | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 891 | inline void AudioMixer::Track::adjustVolumeRamp(bool aux, bool useFloat) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 892 | { | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 893 |     if (useFloat) { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 894 |         for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) { | 
| Eric Laurent | 43412fc | 2015-05-08 16:14:36 -0700 | [diff] [blame] | 895 |             if ((mVolumeInc[i] > 0 && mPrevVolume[i] + mVolumeInc[i] >= mVolume[i]) || | 
 | 896 |                      (mVolumeInc[i] < 0 && mPrevVolume[i] + mVolumeInc[i] <= mVolume[i])) { | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 897 |                 volumeInc[i] = 0; | 
 | 898 |                 prevVolume[i] = volume[i] << 16; | 
 | 899 |                 mVolumeInc[i] = 0.; | 
 | 900 |                 mPrevVolume[i] = mVolume[i]; | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 901 |             } else { | 
 | 902 |                 //ALOGV("ramp: %f %f %f", mVolume[i], mPrevVolume[i], mVolumeInc[i]); | 
 | 903 |                 prevVolume[i] = u4_28_from_float(mPrevVolume[i]); | 
 | 904 |             } | 
 | 905 |         } | 
 | 906 |     } else { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 907 |         for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) { | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 908 |             if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) || | 
 | 909 |                     ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) { | 
 | 910 |                 volumeInc[i] = 0; | 
 | 911 |                 prevVolume[i] = volume[i] << 16; | 
 | 912 |                 mVolumeInc[i] = 0.; | 
 | 913 |                 mPrevVolume[i] = mVolume[i]; | 
 | 914 |             } else { | 
 | 915 |                 //ALOGV("ramp: %d %d %d", volume[i] << 16, prevVolume[i], volumeInc[i]); | 
 | 916 |                 mPrevVolume[i]  = float_from_u4_28(prevVolume[i]); | 
 | 917 |             } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 918 |         } | 
 | 919 |     } | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 920 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 921 |     if (aux) { | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 922 | #ifdef FLOAT_AUX | 
 | 923 |         if (useFloat) { | 
 | 924 |             if ((mAuxInc > 0.f && mPrevAuxLevel + mAuxInc >= mAuxLevel) || | 
 | 925 |                     (mAuxInc < 0.f && mPrevAuxLevel + mAuxInc <= mAuxLevel)) { | 
 | 926 |                 auxInc = 0; | 
 | 927 |                 prevAuxLevel = auxLevel << 16; | 
 | 928 |                 mAuxInc = 0.f; | 
 | 929 |                 mPrevAuxLevel = mAuxLevel; | 
 | 930 |             } | 
 | 931 |         } else | 
 | 932 | #endif | 
 | 933 |         if ((auxInc > 0 && ((prevAuxLevel + auxInc) >> 16) >= auxLevel) || | 
 | 934 |                 (auxInc < 0 && ((prevAuxLevel + auxInc) >> 16) <= auxLevel)) { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 935 |             auxInc = 0; | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 936 |             prevAuxLevel = auxLevel << 16; | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 937 |             mAuxInc = 0.f; | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 938 |             mPrevAuxLevel = mAuxLevel; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 939 |         } | 
 | 940 |     } | 
 | 941 | } | 
 | 942 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 943 | size_t AudioMixer::getUnreleasedFrames(int name) const | 
| Eric Laurent | 071ccd5 | 2011-12-22 16:08:41 -0800 | [diff] [blame] | 944 | { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 945 |     const auto it = mTracks.find(name); | 
 | 946 |     if (it != mTracks.end()) { | 
 | 947 |         return it->second->getUnreleasedFrames(); | 
| Eric Laurent | 071ccd5 | 2011-12-22 16:08:41 -0800 | [diff] [blame] | 948 |     } | 
 | 949 |     return 0; | 
 | 950 | } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 951 |  | 
| Glenn Kasten | 01c4ebf | 2012-02-22 10:47:35 -0800 | [diff] [blame] | 952 | void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 953 | { | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 954 |     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 955 |     const std::shared_ptr<Track> &track = mTracks[name]; | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 956 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 957 |     if (track->mInputBufferProvider == bufferProvider) { | 
| Andy Hung | 1d26ddf | 2014-05-29 15:53:09 -0700 | [diff] [blame] | 958 |         return; // don't reset any buffer providers if identical. | 
 | 959 |     } | 
| Andy Hung | 3a34df9 | 2018-08-21 12:32:30 -0700 | [diff] [blame] | 960 |     // reset order from downstream to upstream buffer providers. | 
 | 961 |     if (track->mTimestretchBufferProvider.get() != nullptr) { | 
 | 962 |         track->mTimestretchBufferProvider->reset(); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 963 |     } else if (track->mPostDownmixReformatBufferProvider.get() != nullptr) { | 
 | 964 |         track->mPostDownmixReformatBufferProvider->reset(); | 
| Andy Hung | 3a34df9 | 2018-08-21 12:32:30 -0700 | [diff] [blame] | 965 |     } else if (track->mDownmixerBufferProvider != nullptr) { | 
 | 966 |         track->mDownmixerBufferProvider->reset(); | 
 | 967 |     } else if (track->mReformatBufferProvider.get() != nullptr) { | 
 | 968 |         track->mReformatBufferProvider->reset(); | 
| jiabin | dce8f8c | 2018-12-10 17:49:31 -0800 | [diff] [blame] | 969 |     } else if (track->mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) { | 
 | 970 |         track->mAdjustChannelsNonDestructiveBufferProvider->reset(); | 
 | 971 |     } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) { | 
 | 972 |         track->mAdjustChannelsBufferProvider->reset(); | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 973 |     } | 
| Andy Hung | ef7c7fb | 2014-05-12 16:51:41 -0700 | [diff] [blame] | 974 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 975 |     track->mInputBufferProvider = bufferProvider; | 
 | 976 |     track->reconfigureBufferProviders(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 977 | } | 
 | 978 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 979 | void AudioMixer::process__validate() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 980 | { | 
| Andy Hung | 395db4b | 2014-08-25 17:15:29 -0700 | [diff] [blame] | 981 |     // TODO: fix all16BitsStereNoResample logic to | 
 | 982 |     // either properly handle muted tracks (it should ignore them) | 
 | 983 |     // or remove altogether as an obsolete optimization. | 
| Glenn Kasten | 4c340c6 | 2012-01-27 12:33:54 -0800 | [diff] [blame] | 984 |     bool all16BitsStereoNoResample = true; | 
 | 985 |     bool resampling = false; | 
 | 986 |     bool volumeRamp = false; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 987 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 988 |     mEnabled.clear(); | 
 | 989 |     mGroups.clear(); | 
 | 990 |     for (const auto &pair : mTracks) { | 
 | 991 |         const int name = pair.first; | 
 | 992 |         const std::shared_ptr<Track> &t = pair.second; | 
 | 993 |         if (!t->enabled) continue; | 
 | 994 |  | 
 | 995 |         mEnabled.emplace_back(name);  // we add to mEnabled in order of name. | 
 | 996 |         mGroups[t->mainBuffer].emplace_back(name); // mGroups also in order of name. | 
 | 997 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 998 |         uint32_t n = 0; | 
| Glenn Kasten | d6fadf0 | 2013-10-30 14:37:29 -0700 | [diff] [blame] | 999 |         // FIXME can overflow (mask is only 3 bits) | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1000 |         n |= NEEDS_CHANNEL_1 + t->channelCount - 1; | 
 | 1001 |         if (t->doesResample()) { | 
| Glenn Kasten | d6fadf0 | 2013-10-30 14:37:29 -0700 | [diff] [blame] | 1002 |             n |= NEEDS_RESAMPLE; | 
 | 1003 |         } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1004 |         if (t->auxLevel != 0 && t->auxBuffer != NULL) { | 
| Glenn Kasten | d6fadf0 | 2013-10-30 14:37:29 -0700 | [diff] [blame] | 1005 |             n |= NEEDS_AUX; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1006 |         } | 
 | 1007 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1008 |         if (t->volumeInc[0]|t->volumeInc[1]) { | 
| Glenn Kasten | 4c340c6 | 2012-01-27 12:33:54 -0800 | [diff] [blame] | 1009 |             volumeRamp = true; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1010 |         } else if (!t->doesResample() && t->volumeRL == 0) { | 
| Glenn Kasten | d6fadf0 | 2013-10-30 14:37:29 -0700 | [diff] [blame] | 1011 |             n |= NEEDS_MUTE; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1012 |         } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1013 |         t->needs = n; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1014 |  | 
| Glenn Kasten | d6fadf0 | 2013-10-30 14:37:29 -0700 | [diff] [blame] | 1015 |         if (n & NEEDS_MUTE) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1016 |             t->hook = &Track::track__nop; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1017 |         } else { | 
| Glenn Kasten | d6fadf0 | 2013-10-30 14:37:29 -0700 | [diff] [blame] | 1018 |             if (n & NEEDS_AUX) { | 
| Glenn Kasten | 4c340c6 | 2012-01-27 12:33:54 -0800 | [diff] [blame] | 1019 |                 all16BitsStereoNoResample = false; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1020 |             } | 
| Glenn Kasten | d6fadf0 | 2013-10-30 14:37:29 -0700 | [diff] [blame] | 1021 |             if (n & NEEDS_RESAMPLE) { | 
| Glenn Kasten | 4c340c6 | 2012-01-27 12:33:54 -0800 | [diff] [blame] | 1022 |                 all16BitsStereoNoResample = false; | 
 | 1023 |                 resampling = true; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1024 |                 t->hook = Track::getTrackHook(TRACKTYPE_RESAMPLE, t->mMixerChannelCount, | 
 | 1025 |                         t->mMixerInFormat, t->mMixerFormat); | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 1026 |                 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2, | 
| Chih-Hung Hsieh | 09f9c02 | 2018-07-27 10:22:35 -0700 | [diff] [blame] | 1027 |                         "Track %d needs downmix + resample", name); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1028 |             } else { | 
 | 1029 |                 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){ | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1030 |                     t->hook = Track::getTrackHook( | 
 | 1031 |                             (t->mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO  // TODO: MONO_HACK | 
 | 1032 |                                     && t->channelMask == AUDIO_CHANNEL_OUT_MONO) | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1033 |                                 ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE, | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1034 |                             t->mMixerChannelCount, | 
 | 1035 |                             t->mMixerInFormat, t->mMixerFormat); | 
| Glenn Kasten | 4c340c6 | 2012-01-27 12:33:54 -0800 | [diff] [blame] | 1036 |                     all16BitsStereoNoResample = false; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1037 |                 } | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 1038 |                 if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){ | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1039 |                     t->hook = Track::getTrackHook(TRACKTYPE_NORESAMPLE, t->mMixerChannelCount, | 
 | 1040 |                             t->mMixerInFormat, t->mMixerFormat); | 
| Jean-Michel Trivi | 7d5b262 | 2012-04-04 18:54:36 -0700 | [diff] [blame] | 1041 |                     ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2, | 
| Chih-Hung Hsieh | 09f9c02 | 2018-07-27 10:22:35 -0700 | [diff] [blame] | 1042 |                             "Track %d needs downmix", name); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1043 |                 } | 
 | 1044 |             } | 
 | 1045 |         } | 
 | 1046 |     } | 
 | 1047 |  | 
 | 1048 |     // select the processing hooks | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1049 |     mHook = &AudioMixer::process__nop; | 
 | 1050 |     if (mEnabled.size() > 0) { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1051 |         if (resampling) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1052 |             if (mOutputTemp.get() == nullptr) { | 
 | 1053 |                 mOutputTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1054 |             } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1055 |             if (mResampleTemp.get() == nullptr) { | 
 | 1056 |                 mResampleTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1057 |             } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1058 |             mHook = &AudioMixer::process__genericResampling; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1059 |         } else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1060 |             // we keep temp arrays around. | 
 | 1061 |             mHook = &AudioMixer::process__genericNoResampling; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1062 |             if (all16BitsStereoNoResample && !volumeRamp) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1063 |                 if (mEnabled.size() == 1) { | 
 | 1064 |                     const std::shared_ptr<Track> &t = mTracks[mEnabled[0]]; | 
 | 1065 |                     if ((t->needs & NEEDS_MUTE) == 0) { | 
| Andy Hung | 395db4b | 2014-08-25 17:15:29 -0700 | [diff] [blame] | 1066 |                         // The check prevents a muted track from acquiring a process hook. | 
 | 1067 |                         // | 
 | 1068 |                         // This is dangerous if the track is MONO as that requires | 
 | 1069 |                         // special case handling due to implicit channel duplication. | 
 | 1070 |                         // Stereo or Multichannel should actually be fine here. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1071 |                         mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK, | 
 | 1072 |                                 t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat); | 
| Andy Hung | 395db4b | 2014-08-25 17:15:29 -0700 | [diff] [blame] | 1073 |                     } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1074 |                 } | 
 | 1075 |             } | 
 | 1076 |         } | 
 | 1077 |     } | 
 | 1078 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1079 |     ALOGV("mixer configuration change: %zu " | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1080 |         "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1081 |         mEnabled.size(), all16BitsStereoNoResample, resampling, volumeRamp); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1082 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1083 |    process(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1084 |  | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 1085 |     // Now that the volume ramp has been done, set optimal state and | 
 | 1086 |     // track hooks for subsequent mixer process | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1087 |     if (mEnabled.size() > 0) { | 
| Glenn Kasten | 4c340c6 | 2012-01-27 12:33:54 -0800 | [diff] [blame] | 1088 |         bool allMuted = true; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1089 |  | 
 | 1090 |         for (const int name : mEnabled) { | 
 | 1091 |             const std::shared_ptr<Track> &t = mTracks[name]; | 
 | 1092 |             if (!t->doesResample() && t->volumeRL == 0) { | 
 | 1093 |                 t->needs |= NEEDS_MUTE; | 
 | 1094 |                 t->hook = &Track::track__nop; | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 1095 |             } else { | 
| Glenn Kasten | 4c340c6 | 2012-01-27 12:33:54 -0800 | [diff] [blame] | 1096 |                 allMuted = false; | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 1097 |             } | 
 | 1098 |         } | 
 | 1099 |         if (allMuted) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1100 |             mHook = &AudioMixer::process__nop; | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 1101 |         } else if (all16BitsStereoNoResample) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1102 |             if (mEnabled.size() == 1) { | 
 | 1103 |                 //const int i = 31 - __builtin_clz(enabledTracks); | 
 | 1104 |                 const std::shared_ptr<Track> &t = mTracks[mEnabled[0]]; | 
| Andy Hung | 395db4b | 2014-08-25 17:15:29 -0700 | [diff] [blame] | 1105 |                 // Muted single tracks handled by allMuted above. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1106 |                 mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK, | 
 | 1107 |                         t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat); | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 1108 |             } | 
 | 1109 |         } | 
 | 1110 |     } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1111 | } | 
 | 1112 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1113 | void AudioMixer::Track::track__genericResample( | 
 | 1114 |         int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1115 | { | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1116 |     ALOGVV("track__genericResample\n"); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1117 |     mResampler->setSampleRate(sampleRate); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1118 |  | 
 | 1119 |     // ramp gain - resample to temp buffer and scale/mix in 2nd step | 
 | 1120 |     if (aux != NULL) { | 
 | 1121 |         // always resample with unity gain when sending to auxiliary buffer to be able | 
 | 1122 |         // to apply send level after resampling | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1123 |         mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT); | 
 | 1124 |         memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(int32_t)); | 
 | 1125 |         mResampler->resample(temp, outFrameCount, bufferProvider); | 
 | 1126 |         if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) { | 
 | 1127 |             volumeRampStereo(out, outFrameCount, temp, aux); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1128 |         } else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1129 |             volumeStereo(out, outFrameCount, temp, aux); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1130 |         } | 
 | 1131 |     } else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1132 |         if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) { | 
 | 1133 |             mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1134 |             memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t)); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1135 |             mResampler->resample(temp, outFrameCount, bufferProvider); | 
 | 1136 |             volumeRampStereo(out, outFrameCount, temp, aux); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1137 |         } | 
 | 1138 |  | 
 | 1139 |         // constant gain | 
 | 1140 |         else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1141 |             mResampler->setVolume(mVolume[0], mVolume[1]); | 
 | 1142 |             mResampler->resample(out, outFrameCount, bufferProvider); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1143 |         } | 
 | 1144 |     } | 
 | 1145 | } | 
 | 1146 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1147 | void AudioMixer::Track::track__nop(int32_t* out __unused, | 
| Andy Hung | ee931ff | 2014-01-28 13:44:14 -0800 | [diff] [blame] | 1148 |         size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1149 | { | 
 | 1150 | } | 
 | 1151 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1152 | void AudioMixer::Track::volumeRampStereo( | 
 | 1153 |         int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1154 | { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1155 |     int32_t vl = prevVolume[0]; | 
 | 1156 |     int32_t vr = prevVolume[1]; | 
 | 1157 |     const int32_t vlInc = volumeInc[0]; | 
 | 1158 |     const int32_t vrInc = volumeInc[1]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1159 |  | 
| Steve Block | b8a8052 | 2011-12-20 16:23:08 +0000 | [diff] [blame] | 1160 |     //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1161 |     //        t, vlInc/65536.0f, vl/65536.0f, volume[0], | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1162 |     //       (vl + vlInc*frameCount)/65536.0f, frameCount); | 
 | 1163 |  | 
 | 1164 |     // ramp volume | 
| Glenn Kasten | f6b1678 | 2011-12-15 09:51:17 -0800 | [diff] [blame] | 1165 |     if (CC_UNLIKELY(aux != NULL)) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1166 |         int32_t va = prevAuxLevel; | 
 | 1167 |         const int32_t vaInc = auxInc; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1168 |         int32_t l; | 
 | 1169 |         int32_t r; | 
 | 1170 |  | 
 | 1171 |         do { | 
 | 1172 |             l = (*temp++ >> 12); | 
 | 1173 |             r = (*temp++ >> 12); | 
 | 1174 |             *out++ += (vl >> 16) * l; | 
 | 1175 |             *out++ += (vr >> 16) * r; | 
 | 1176 |             *aux++ += (va >> 17) * (l + r); | 
 | 1177 |             vl += vlInc; | 
 | 1178 |             vr += vrInc; | 
 | 1179 |             va += vaInc; | 
 | 1180 |         } while (--frameCount); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1181 |         prevAuxLevel = va; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1182 |     } else { | 
 | 1183 |         do { | 
 | 1184 |             *out++ += (vl >> 16) * (*temp++ >> 12); | 
 | 1185 |             *out++ += (vr >> 16) * (*temp++ >> 12); | 
 | 1186 |             vl += vlInc; | 
 | 1187 |             vr += vrInc; | 
 | 1188 |         } while (--frameCount); | 
 | 1189 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1190 |     prevVolume[0] = vl; | 
 | 1191 |     prevVolume[1] = vr; | 
 | 1192 |     adjustVolumeRamp(aux != NULL); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1193 | } | 
 | 1194 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1195 | void AudioMixer::Track::volumeStereo( | 
 | 1196 |         int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1197 | { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1198 |     const int16_t vl = volume[0]; | 
 | 1199 |     const int16_t vr = volume[1]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1200 |  | 
| Glenn Kasten | f6b1678 | 2011-12-15 09:51:17 -0800 | [diff] [blame] | 1201 |     if (CC_UNLIKELY(aux != NULL)) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1202 |         const int16_t va = auxLevel; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1203 |         do { | 
 | 1204 |             int16_t l = (int16_t)(*temp++ >> 12); | 
 | 1205 |             int16_t r = (int16_t)(*temp++ >> 12); | 
 | 1206 |             out[0] = mulAdd(l, vl, out[0]); | 
 | 1207 |             int16_t a = (int16_t)(((int32_t)l + r) >> 1); | 
 | 1208 |             out[1] = mulAdd(r, vr, out[1]); | 
 | 1209 |             out += 2; | 
 | 1210 |             aux[0] = mulAdd(a, va, aux[0]); | 
 | 1211 |             aux++; | 
 | 1212 |         } while (--frameCount); | 
 | 1213 |     } else { | 
 | 1214 |         do { | 
 | 1215 |             int16_t l = (int16_t)(*temp++ >> 12); | 
 | 1216 |             int16_t r = (int16_t)(*temp++ >> 12); | 
 | 1217 |             out[0] = mulAdd(l, vl, out[0]); | 
 | 1218 |             out[1] = mulAdd(r, vr, out[1]); | 
 | 1219 |             out += 2; | 
 | 1220 |         } while (--frameCount); | 
 | 1221 |     } | 
 | 1222 | } | 
 | 1223 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1224 | void AudioMixer::Track::track__16BitsStereo( | 
 | 1225 |         int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1226 | { | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1227 |     ALOGVV("track__16BitsStereo\n"); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1228 |     const int16_t *in = static_cast<const int16_t *>(mIn); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1229 |  | 
| Glenn Kasten | f6b1678 | 2011-12-15 09:51:17 -0800 | [diff] [blame] | 1230 |     if (CC_UNLIKELY(aux != NULL)) { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1231 |         int32_t l; | 
 | 1232 |         int32_t r; | 
 | 1233 |         // ramp gain | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1234 |         if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) { | 
 | 1235 |             int32_t vl = prevVolume[0]; | 
 | 1236 |             int32_t vr = prevVolume[1]; | 
 | 1237 |             int32_t va = prevAuxLevel; | 
 | 1238 |             const int32_t vlInc = volumeInc[0]; | 
 | 1239 |             const int32_t vrInc = volumeInc[1]; | 
 | 1240 |             const int32_t vaInc = auxInc; | 
| Steve Block | b8a8052 | 2011-12-20 16:23:08 +0000 | [diff] [blame] | 1241 |             // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1242 |             //        t, vlInc/65536.0f, vl/65536.0f, volume[0], | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1243 |             //        (vl + vlInc*frameCount)/65536.0f, frameCount); | 
 | 1244 |  | 
 | 1245 |             do { | 
 | 1246 |                 l = (int32_t)*in++; | 
 | 1247 |                 r = (int32_t)*in++; | 
 | 1248 |                 *out++ += (vl >> 16) * l; | 
 | 1249 |                 *out++ += (vr >> 16) * r; | 
 | 1250 |                 *aux++ += (va >> 17) * (l + r); | 
 | 1251 |                 vl += vlInc; | 
 | 1252 |                 vr += vrInc; | 
 | 1253 |                 va += vaInc; | 
 | 1254 |             } while (--frameCount); | 
 | 1255 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1256 |             prevVolume[0] = vl; | 
 | 1257 |             prevVolume[1] = vr; | 
 | 1258 |             prevAuxLevel = va; | 
 | 1259 |             adjustVolumeRamp(true); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1260 |         } | 
 | 1261 |  | 
 | 1262 |         // constant gain | 
 | 1263 |         else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1264 |             const uint32_t vrl = volumeRL; | 
 | 1265 |             const int16_t va = (int16_t)auxLevel; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1266 |             do { | 
| Glenn Kasten | 54c3b66 | 2012-01-06 07:46:30 -0800 | [diff] [blame] | 1267 |                 uint32_t rl = *reinterpret_cast<const uint32_t *>(in); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1268 |                 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1); | 
 | 1269 |                 in += 2; | 
 | 1270 |                 out[0] = mulAddRL(1, rl, vrl, out[0]); | 
 | 1271 |                 out[1] = mulAddRL(0, rl, vrl, out[1]); | 
 | 1272 |                 out += 2; | 
 | 1273 |                 aux[0] = mulAdd(a, va, aux[0]); | 
 | 1274 |                 aux++; | 
 | 1275 |             } while (--frameCount); | 
 | 1276 |         } | 
 | 1277 |     } else { | 
 | 1278 |         // ramp gain | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1279 |         if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) { | 
 | 1280 |             int32_t vl = prevVolume[0]; | 
 | 1281 |             int32_t vr = prevVolume[1]; | 
 | 1282 |             const int32_t vlInc = volumeInc[0]; | 
 | 1283 |             const int32_t vrInc = volumeInc[1]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1284 |  | 
| Steve Block | b8a8052 | 2011-12-20 16:23:08 +0000 | [diff] [blame] | 1285 |             // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1286 |             //        t, vlInc/65536.0f, vl/65536.0f, volume[0], | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1287 |             //        (vl + vlInc*frameCount)/65536.0f, frameCount); | 
 | 1288 |  | 
 | 1289 |             do { | 
 | 1290 |                 *out++ += (vl >> 16) * (int32_t) *in++; | 
 | 1291 |                 *out++ += (vr >> 16) * (int32_t) *in++; | 
 | 1292 |                 vl += vlInc; | 
 | 1293 |                 vr += vrInc; | 
 | 1294 |             } while (--frameCount); | 
 | 1295 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1296 |             prevVolume[0] = vl; | 
 | 1297 |             prevVolume[1] = vr; | 
 | 1298 |             adjustVolumeRamp(false); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1299 |         } | 
 | 1300 |  | 
 | 1301 |         // constant gain | 
 | 1302 |         else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1303 |             const uint32_t vrl = volumeRL; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1304 |             do { | 
| Glenn Kasten | 54c3b66 | 2012-01-06 07:46:30 -0800 | [diff] [blame] | 1305 |                 uint32_t rl = *reinterpret_cast<const uint32_t *>(in); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1306 |                 in += 2; | 
 | 1307 |                 out[0] = mulAddRL(1, rl, vrl, out[0]); | 
 | 1308 |                 out[1] = mulAddRL(0, rl, vrl, out[1]); | 
 | 1309 |                 out += 2; | 
 | 1310 |             } while (--frameCount); | 
 | 1311 |         } | 
 | 1312 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1313 |     mIn = in; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1314 | } | 
 | 1315 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1316 | void AudioMixer::Track::track__16BitsMono( | 
 | 1317 |         int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1318 | { | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1319 |     ALOGVV("track__16BitsMono\n"); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1320 |     const int16_t *in = static_cast<int16_t const *>(mIn); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1321 |  | 
| Glenn Kasten | f6b1678 | 2011-12-15 09:51:17 -0800 | [diff] [blame] | 1322 |     if (CC_UNLIKELY(aux != NULL)) { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1323 |         // ramp gain | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1324 |         if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) { | 
 | 1325 |             int32_t vl = prevVolume[0]; | 
 | 1326 |             int32_t vr = prevVolume[1]; | 
 | 1327 |             int32_t va = prevAuxLevel; | 
 | 1328 |             const int32_t vlInc = volumeInc[0]; | 
 | 1329 |             const int32_t vrInc = volumeInc[1]; | 
 | 1330 |             const int32_t vaInc = auxInc; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1331 |  | 
| Steve Block | b8a8052 | 2011-12-20 16:23:08 +0000 | [diff] [blame] | 1332 |             // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1333 |             //         t, vlInc/65536.0f, vl/65536.0f, volume[0], | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1334 |             //         (vl + vlInc*frameCount)/65536.0f, frameCount); | 
 | 1335 |  | 
 | 1336 |             do { | 
 | 1337 |                 int32_t l = *in++; | 
 | 1338 |                 *out++ += (vl >> 16) * l; | 
 | 1339 |                 *out++ += (vr >> 16) * l; | 
 | 1340 |                 *aux++ += (va >> 16) * l; | 
 | 1341 |                 vl += vlInc; | 
 | 1342 |                 vr += vrInc; | 
 | 1343 |                 va += vaInc; | 
 | 1344 |             } while (--frameCount); | 
 | 1345 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1346 |             prevVolume[0] = vl; | 
 | 1347 |             prevVolume[1] = vr; | 
 | 1348 |             prevAuxLevel = va; | 
 | 1349 |             adjustVolumeRamp(true); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1350 |         } | 
 | 1351 |         // constant gain | 
 | 1352 |         else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1353 |             const int16_t vl = volume[0]; | 
 | 1354 |             const int16_t vr = volume[1]; | 
 | 1355 |             const int16_t va = (int16_t)auxLevel; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1356 |             do { | 
 | 1357 |                 int16_t l = *in++; | 
 | 1358 |                 out[0] = mulAdd(l, vl, out[0]); | 
 | 1359 |                 out[1] = mulAdd(l, vr, out[1]); | 
 | 1360 |                 out += 2; | 
 | 1361 |                 aux[0] = mulAdd(l, va, aux[0]); | 
 | 1362 |                 aux++; | 
 | 1363 |             } while (--frameCount); | 
 | 1364 |         } | 
 | 1365 |     } else { | 
 | 1366 |         // ramp gain | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1367 |         if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) { | 
 | 1368 |             int32_t vl = prevVolume[0]; | 
 | 1369 |             int32_t vr = prevVolume[1]; | 
 | 1370 |             const int32_t vlInc = volumeInc[0]; | 
 | 1371 |             const int32_t vrInc = volumeInc[1]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1372 |  | 
| Steve Block | b8a8052 | 2011-12-20 16:23:08 +0000 | [diff] [blame] | 1373 |             // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1374 |             //         t, vlInc/65536.0f, vl/65536.0f, volume[0], | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1375 |             //         (vl + vlInc*frameCount)/65536.0f, frameCount); | 
 | 1376 |  | 
 | 1377 |             do { | 
 | 1378 |                 int32_t l = *in++; | 
 | 1379 |                 *out++ += (vl >> 16) * l; | 
 | 1380 |                 *out++ += (vr >> 16) * l; | 
 | 1381 |                 vl += vlInc; | 
 | 1382 |                 vr += vrInc; | 
 | 1383 |             } while (--frameCount); | 
 | 1384 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1385 |             prevVolume[0] = vl; | 
 | 1386 |             prevVolume[1] = vr; | 
 | 1387 |             adjustVolumeRamp(false); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1388 |         } | 
 | 1389 |         // constant gain | 
 | 1390 |         else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1391 |             const int16_t vl = volume[0]; | 
 | 1392 |             const int16_t vr = volume[1]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1393 |             do { | 
 | 1394 |                 int16_t l = *in++; | 
 | 1395 |                 out[0] = mulAdd(l, vl, out[0]); | 
 | 1396 |                 out[1] = mulAdd(l, vr, out[1]); | 
 | 1397 |                 out += 2; | 
 | 1398 |             } while (--frameCount); | 
 | 1399 |         } | 
 | 1400 |     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1401 |     mIn = in; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1402 | } | 
 | 1403 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1404 | // no-op case | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1405 | void AudioMixer::process__nop() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1406 | { | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1407 |     ALOGVV("process__nop\n"); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1408 |  | 
 | 1409 |     for (const auto &pair : mGroups) { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1410 |         // process by group of tracks with same output buffer to | 
 | 1411 |         // avoid multiple memset() on same buffer | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1412 |         const auto &group = pair.second; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1413 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1414 |         const std::shared_ptr<Track> &t = mTracks[group[0]]; | 
 | 1415 |         memset(t->mainBuffer, 0, | 
| jiabin | 245cdd9 | 2018-12-07 17:55:15 -0800 | [diff] [blame] | 1416 |                 mFrameCount * audio_bytes_per_frame( | 
 | 1417 |                         t->mMixerChannelCount + t->mMixerHapticChannelCount, t->mMixerFormat)); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1418 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1419 |         // now consume data | 
 | 1420 |         for (const int name : group) { | 
 | 1421 |             const std::shared_ptr<Track> &t = mTracks[name]; | 
 | 1422 |             size_t outFrames = mFrameCount; | 
 | 1423 |             while (outFrames) { | 
 | 1424 |                 t->buffer.frameCount = outFrames; | 
 | 1425 |                 t->bufferProvider->getNextBuffer(&t->buffer); | 
 | 1426 |                 if (t->buffer.raw == NULL) break; | 
 | 1427 |                 outFrames -= t->buffer.frameCount; | 
 | 1428 |                 t->bufferProvider->releaseBuffer(&t->buffer); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1429 |             } | 
 | 1430 |         } | 
 | 1431 |     } | 
 | 1432 | } | 
 | 1433 |  | 
 | 1434 | // generic code without resampling | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1435 | void AudioMixer::process__genericNoResampling() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1436 | { | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1437 |     ALOGVV("process__genericNoResampling\n"); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1438 |     int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32))); | 
 | 1439 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1440 |     for (const auto &pair : mGroups) { | 
 | 1441 |         // process by group of tracks with same output main buffer to | 
 | 1442 |         // avoid multiple memset() on same buffer | 
 | 1443 |         const auto &group = pair.second; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1444 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1445 |         // acquire buffer | 
 | 1446 |         for (const int name : group) { | 
 | 1447 |             const std::shared_ptr<Track> &t = mTracks[name]; | 
 | 1448 |             t->buffer.frameCount = mFrameCount; | 
 | 1449 |             t->bufferProvider->getNextBuffer(&t->buffer); | 
 | 1450 |             t->frameCount = t->buffer.frameCount; | 
 | 1451 |             t->mIn = t->buffer.raw; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1452 |         } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1453 |  | 
 | 1454 |         int32_t *out = (int *)pair.first; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1455 |         size_t numFrames = 0; | 
 | 1456 |         do { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1457 |             const size_t frameCount = std::min((size_t)BLOCKSIZE, mFrameCount - numFrames); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1458 |             memset(outTemp, 0, sizeof(outTemp)); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1459 |             for (const int name : group) { | 
 | 1460 |                 const std::shared_ptr<Track> &t = mTracks[name]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1461 |                 int32_t *aux = NULL; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1462 |                 if (CC_UNLIKELY(t->needs & NEEDS_AUX)) { | 
 | 1463 |                     aux = t->auxBuffer + numFrames; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1464 |                 } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1465 |                 for (int outFrames = frameCount; outFrames > 0; ) { | 
 | 1466 |                     // t->in == nullptr can happen if the track was flushed just after having | 
| Gaurav Kumar | 7e79cd2 | 2014-01-06 10:57:18 +0530 | [diff] [blame] | 1467 |                     // been enabled for mixing. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1468 |                     if (t->mIn == nullptr) { | 
| Gaurav Kumar | 7e79cd2 | 2014-01-06 10:57:18 +0530 | [diff] [blame] | 1469 |                         break; | 
 | 1470 |                     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1471 |                     size_t inFrames = (t->frameCount > outFrames)?outFrames:t->frameCount; | 
| Glenn Kasten | 34fca34 | 2013-08-13 09:48:14 -0700 | [diff] [blame] | 1472 |                     if (inFrames > 0) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1473 |                         (t.get()->*t->hook)( | 
 | 1474 |                                 outTemp + (frameCount - outFrames) * t->mMixerChannelCount, | 
 | 1475 |                                 inFrames, mResampleTemp.get() /* naked ptr */, aux); | 
 | 1476 |                         t->frameCount -= inFrames; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1477 |                         outFrames -= inFrames; | 
| Glenn Kasten | f6b1678 | 2011-12-15 09:51:17 -0800 | [diff] [blame] | 1478 |                         if (CC_UNLIKELY(aux != NULL)) { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1479 |                             aux += inFrames; | 
 | 1480 |                         } | 
 | 1481 |                     } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1482 |                     if (t->frameCount == 0 && outFrames) { | 
 | 1483 |                         t->bufferProvider->releaseBuffer(&t->buffer); | 
 | 1484 |                         t->buffer.frameCount = (mFrameCount - numFrames) - | 
| Yahan Zhou | c1c11b4 | 2018-01-16 12:44:04 -0800 | [diff] [blame] | 1485 |                                 (frameCount - outFrames); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1486 |                         t->bufferProvider->getNextBuffer(&t->buffer); | 
 | 1487 |                         t->mIn = t->buffer.raw; | 
 | 1488 |                         if (t->mIn == nullptr) { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1489 |                             break; | 
 | 1490 |                         } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1491 |                         t->frameCount = t->buffer.frameCount; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1492 |                     } | 
 | 1493 |                 } | 
 | 1494 |             } | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1495 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1496 |             const std::shared_ptr<Track> &t1 = mTracks[group[0]]; | 
 | 1497 |             convertMixerFormat(out, t1->mMixerFormat, outTemp, t1->mMixerInFormat, | 
 | 1498 |                     frameCount * t1->mMixerChannelCount); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1499 |             // TODO: fix ugly casting due to choice of out pointer type | 
 | 1500 |             out = reinterpret_cast<int32_t*>((uint8_t*)out | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1501 |                     + frameCount * t1->mMixerChannelCount | 
 | 1502 |                     * audio_bytes_per_sample(t1->mMixerFormat)); | 
| Yahan Zhou | c1c11b4 | 2018-01-16 12:44:04 -0800 | [diff] [blame] | 1503 |             numFrames += frameCount; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1504 |         } while (numFrames < mFrameCount); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1505 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1506 |         // release each track's buffer | 
 | 1507 |         for (const int name : group) { | 
 | 1508 |             const std::shared_ptr<Track> &t = mTracks[name]; | 
 | 1509 |             t->bufferProvider->releaseBuffer(&t->buffer); | 
 | 1510 |         } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1511 |     } | 
 | 1512 | } | 
 | 1513 |  | 
| Glenn Kasten | c5ac4cb | 2011-12-12 09:05:55 -0800 | [diff] [blame] | 1514 | // generic code with resampling | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1515 | void AudioMixer::process__genericResampling() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1516 | { | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1517 |     ALOGVV("process__genericResampling\n"); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1518 |     int32_t * const outTemp = mOutputTemp.get(); // naked ptr | 
 | 1519 |     size_t numFrames = mFrameCount; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1520 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1521 |     for (const auto &pair : mGroups) { | 
 | 1522 |         const auto &group = pair.second; | 
 | 1523 |         const std::shared_ptr<Track> &t1 = mTracks[group[0]]; | 
 | 1524 |  | 
 | 1525 |         // clear temp buffer | 
 | 1526 |         memset(outTemp, 0, sizeof(*outTemp) * t1->mMixerChannelCount * mFrameCount); | 
 | 1527 |         for (const int name : group) { | 
 | 1528 |             const std::shared_ptr<Track> &t = mTracks[name]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1529 |             int32_t *aux = NULL; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1530 |             if (CC_UNLIKELY(t->needs & NEEDS_AUX)) { | 
 | 1531 |                 aux = t->auxBuffer; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1532 |             } | 
 | 1533 |  | 
 | 1534 |             // this is a little goofy, on the resampling case we don't | 
 | 1535 |             // acquire/release the buffers because it's done by | 
 | 1536 |             // the resampler. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1537 |             if (t->needs & NEEDS_RESAMPLE) { | 
 | 1538 |                 (t.get()->*t->hook)(outTemp, numFrames, mResampleTemp.get() /* naked ptr */, aux); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1539 |             } else { | 
 | 1540 |  | 
 | 1541 |                 size_t outFrames = 0; | 
 | 1542 |  | 
 | 1543 |                 while (outFrames < numFrames) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1544 |                     t->buffer.frameCount = numFrames - outFrames; | 
 | 1545 |                     t->bufferProvider->getNextBuffer(&t->buffer); | 
 | 1546 |                     t->mIn = t->buffer.raw; | 
 | 1547 |                     // t->mIn == nullptr can happen if the track was flushed just after having | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1548 |                     // been enabled for mixing. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1549 |                     if (t->mIn == nullptr) break; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1550 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1551 |                     (t.get()->*t->hook)( | 
 | 1552 |                             outTemp + outFrames * t->mMixerChannelCount, t->buffer.frameCount, | 
| Andy Hung | a601889 | 2018-02-21 14:32:16 -0800 | [diff] [blame] | 1553 |                             mResampleTemp.get() /* naked ptr */, | 
 | 1554 |                             aux != nullptr ? aux + outFrames : nullptr); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1555 |                     outFrames += t->buffer.frameCount; | 
| Andy Hung | a601889 | 2018-02-21 14:32:16 -0800 | [diff] [blame] | 1556 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1557 |                     t->bufferProvider->releaseBuffer(&t->buffer); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1558 |                 } | 
 | 1559 |             } | 
 | 1560 |         } | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1561 |         convertMixerFormat(t1->mainBuffer, t1->mMixerFormat, | 
 | 1562 |                 outTemp, t1->mMixerInFormat, numFrames * t1->mMixerChannelCount); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1563 |     } | 
 | 1564 | } | 
 | 1565 |  | 
 | 1566 | // one track, 16 bits stereo without resampling is the most common case | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1567 | void AudioMixer::process__oneTrack16BitsStereoNoResampling() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1568 | { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1569 |     ALOGVV("process__oneTrack16BitsStereoNoResampling\n"); | 
 | 1570 |     LOG_ALWAYS_FATAL_IF(mEnabled.size() != 0, | 
 | 1571 |             "%zu != 1 tracks enabled", mEnabled.size()); | 
 | 1572 |     const int name = mEnabled[0]; | 
 | 1573 |     const std::shared_ptr<Track> &t = mTracks[name]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1574 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1575 |     AudioBufferProvider::Buffer& b(t->buffer); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1576 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1577 |     int32_t* out = t->mainBuffer; | 
| Andy Hung | f8a106a | 2014-05-29 18:52:38 -0700 | [diff] [blame] | 1578 |     float *fout = reinterpret_cast<float*>(out); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1579 |     size_t numFrames = mFrameCount; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1580 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1581 |     const int16_t vl = t->volume[0]; | 
 | 1582 |     const int16_t vr = t->volume[1]; | 
 | 1583 |     const uint32_t vrl = t->volumeRL; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1584 |     while (numFrames) { | 
 | 1585 |         b.frameCount = numFrames; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1586 |         t->bufferProvider->getNextBuffer(&b); | 
| Glenn Kasten | 54c3b66 | 2012-01-06 07:46:30 -0800 | [diff] [blame] | 1587 |         const int16_t *in = b.i16; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1588 |  | 
 | 1589 |         // in == NULL can happen if the track was flushed just after having | 
 | 1590 |         // been enabled for mixing. | 
| Andy Hung | f8a106a | 2014-05-29 18:52:38 -0700 | [diff] [blame] | 1591 |         if (in == NULL || (((uintptr_t)in) & 3)) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1592 |             if ( AUDIO_FORMAT_PCM_FLOAT == t->mMixerFormat ) { | 
| Jinguang Dong | 7c5ec03 | 2016-11-14 19:57:14 +0800 | [diff] [blame] | 1593 |                  memset((char*)fout, 0, numFrames | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1594 |                          * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat)); | 
| Jinguang Dong | 7c5ec03 | 2016-11-14 19:57:14 +0800 | [diff] [blame] | 1595 |             } else { | 
 | 1596 |                  memset((char*)out, 0, numFrames | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1597 |                          * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat)); | 
| Jinguang Dong | 7c5ec03 | 2016-11-14 19:57:14 +0800 | [diff] [blame] | 1598 |             } | 
| Andy Hung | 395db4b | 2014-08-25 17:15:29 -0700 | [diff] [blame] | 1599 |             ALOGE_IF((((uintptr_t)in) & 3), | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1600 |                     "process__oneTrack16BitsStereoNoResampling: misaligned buffer" | 
| Andy Hung | 395db4b | 2014-08-25 17:15:29 -0700 | [diff] [blame] | 1601 |                     " %p track %d, channels %d, needs %08x, volume %08x vfl %f vfr %f", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1602 |                     in, name, t->channelCount, t->needs, vrl, t->mVolume[0], t->mVolume[1]); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1603 |             return; | 
 | 1604 |         } | 
 | 1605 |         size_t outFrames = b.frameCount; | 
 | 1606 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1607 |         switch (t->mMixerFormat) { | 
| Andy Hung | f8a106a | 2014-05-29 18:52:38 -0700 | [diff] [blame] | 1608 |         case AUDIO_FORMAT_PCM_FLOAT: | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1609 |             do { | 
| Glenn Kasten | 54c3b66 | 2012-01-06 07:46:30 -0800 | [diff] [blame] | 1610 |                 uint32_t rl = *reinterpret_cast<const uint32_t *>(in); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1611 |                 in += 2; | 
| Andy Hung | a1ab7cc | 2014-02-24 19:26:52 -0800 | [diff] [blame] | 1612 |                 int32_t l = mulRL(1, rl, vrl); | 
 | 1613 |                 int32_t r = mulRL(0, rl, vrl); | 
| Andy Hung | 84a0c6e | 2014-04-02 11:24:53 -0700 | [diff] [blame] | 1614 |                 *fout++ = float_from_q4_27(l); | 
 | 1615 |                 *fout++ = float_from_q4_27(r); | 
| Andy Hung | 3375bde | 2014-02-28 15:51:47 -0800 | [diff] [blame] | 1616 |                 // Note: In case of later int16_t sink output, | 
 | 1617 |                 // conversion and clamping is done by memcpy_to_i16_from_float(). | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1618 |             } while (--outFrames); | 
| Andy Hung | f8a106a | 2014-05-29 18:52:38 -0700 | [diff] [blame] | 1619 |             break; | 
| Andy Hung | a1ab7cc | 2014-02-24 19:26:52 -0800 | [diff] [blame] | 1620 |         case AUDIO_FORMAT_PCM_16_BIT: | 
| Andy Hung | 97ae824 | 2014-05-30 10:35:47 -0700 | [diff] [blame] | 1621 |             if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) { | 
| Andy Hung | a1ab7cc | 2014-02-24 19:26:52 -0800 | [diff] [blame] | 1622 |                 // volume is boosted, so we might need to clamp even though | 
 | 1623 |                 // we process only one track. | 
 | 1624 |                 do { | 
 | 1625 |                     uint32_t rl = *reinterpret_cast<const uint32_t *>(in); | 
 | 1626 |                     in += 2; | 
 | 1627 |                     int32_t l = mulRL(1, rl, vrl) >> 12; | 
 | 1628 |                     int32_t r = mulRL(0, rl, vrl) >> 12; | 
 | 1629 |                     // clamping... | 
 | 1630 |                     l = clamp16(l); | 
 | 1631 |                     r = clamp16(r); | 
 | 1632 |                     *out++ = (r<<16) | (l & 0xFFFF); | 
 | 1633 |                 } while (--outFrames); | 
 | 1634 |             } else { | 
 | 1635 |                 do { | 
 | 1636 |                     uint32_t rl = *reinterpret_cast<const uint32_t *>(in); | 
 | 1637 |                     in += 2; | 
 | 1638 |                     int32_t l = mulRL(1, rl, vrl) >> 12; | 
 | 1639 |                     int32_t r = mulRL(0, rl, vrl) >> 12; | 
 | 1640 |                     *out++ = (r<<16) | (l & 0xFFFF); | 
 | 1641 |                 } while (--outFrames); | 
 | 1642 |             } | 
 | 1643 |             break; | 
 | 1644 |         default: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1645 |             LOG_ALWAYS_FATAL("bad mixer format: %d", t->mMixerFormat); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1646 |         } | 
 | 1647 |         numFrames -= b.frameCount; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1648 |         t->bufferProvider->releaseBuffer(&b); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1649 |     } | 
 | 1650 | } | 
 | 1651 |  | 
| Glenn Kasten | 52008f8 | 2012-03-18 09:34:41 -0700 | [diff] [blame] | 1652 | /*static*/ pthread_once_t AudioMixer::sOnceControl = PTHREAD_ONCE_INIT; | 
 | 1653 |  | 
 | 1654 | /*static*/ void AudioMixer::sInitRoutine() | 
 | 1655 | { | 
| Andy Hung | 34803d5 | 2014-07-16 21:41:35 -0700 | [diff] [blame] | 1656 |     DownmixerBufferProvider::init(); // for the downmixer | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 1657 | } | 
 | 1658 |  | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1659 | /* TODO: consider whether this level of optimization is necessary. | 
 | 1660 |  * Perhaps just stick with a single for loop. | 
 | 1661 |  */ | 
 | 1662 |  | 
 | 1663 | // Needs to derive a compile time constant (constexpr).  Could be targeted to go | 
 | 1664 | // to a MONOVOL mixtype based on MAX_NUM_VOLUMES, but that's an unnecessary complication. | 
| Chih-Hung Hsieh | bf29173 | 2016-05-17 15:16:07 -0700 | [diff] [blame] | 1665 | #define MIXTYPE_MONOVOL(mixtype) ((mixtype) == MIXTYPE_MULTI ? MIXTYPE_MULTI_MONOVOL : \ | 
 | 1666 |         (mixtype) == MIXTYPE_MULTI_SAVEONLY ? MIXTYPE_MULTI_SAVEONLY_MONOVOL : (mixtype)) | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1667 |  | 
 | 1668 | /* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration) | 
 | 1669 |  * TO: int32_t (Q4.27) or float | 
 | 1670 |  * TI: int32_t (Q4.27) or int16_t (Q0.15) or float | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1671 |  * TA: int32_t (Q4.27) or float | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1672 |  */ | 
 | 1673 | template <int MIXTYPE, | 
 | 1674 |         typename TO, typename TI, typename TV, typename TA, typename TAV> | 
 | 1675 | static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount, | 
 | 1676 |         const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc) | 
 | 1677 | { | 
 | 1678 |     switch (channels) { | 
 | 1679 |     case 1: | 
 | 1680 |         volumeRampMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, volinc, vola, volainc); | 
 | 1681 |         break; | 
 | 1682 |     case 2: | 
 | 1683 |         volumeRampMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, volinc, vola, volainc); | 
 | 1684 |         break; | 
 | 1685 |     case 3: | 
 | 1686 |         volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, | 
 | 1687 |                 frameCount, in, aux, vol, volinc, vola, volainc); | 
 | 1688 |         break; | 
 | 1689 |     case 4: | 
 | 1690 |         volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, | 
 | 1691 |                 frameCount, in, aux, vol, volinc, vola, volainc); | 
 | 1692 |         break; | 
 | 1693 |     case 5: | 
 | 1694 |         volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, | 
 | 1695 |                 frameCount, in, aux, vol, volinc, vola, volainc); | 
 | 1696 |         break; | 
 | 1697 |     case 6: | 
 | 1698 |         volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, | 
 | 1699 |                 frameCount, in, aux, vol, volinc, vola, volainc); | 
 | 1700 |         break; | 
 | 1701 |     case 7: | 
 | 1702 |         volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, | 
 | 1703 |                 frameCount, in, aux, vol, volinc, vola, volainc); | 
 | 1704 |         break; | 
 | 1705 |     case 8: | 
 | 1706 |         volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, | 
 | 1707 |                 frameCount, in, aux, vol, volinc, vola, volainc); | 
 | 1708 |         break; | 
 | 1709 |     } | 
 | 1710 | } | 
 | 1711 |  | 
 | 1712 | /* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration) | 
 | 1713 |  * TO: int32_t (Q4.27) or float | 
 | 1714 |  * TI: int32_t (Q4.27) or int16_t (Q0.15) or float | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1715 |  * TA: int32_t (Q4.27) or float | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1716 |  */ | 
 | 1717 | template <int MIXTYPE, | 
 | 1718 |         typename TO, typename TI, typename TV, typename TA, typename TAV> | 
 | 1719 | static void volumeMulti(uint32_t channels, TO* out, size_t frameCount, | 
 | 1720 |         const TI* in, TA* aux, const TV *vol, TAV vola) | 
 | 1721 | { | 
 | 1722 |     switch (channels) { | 
 | 1723 |     case 1: | 
 | 1724 |         volumeMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, vola); | 
 | 1725 |         break; | 
 | 1726 |     case 2: | 
 | 1727 |         volumeMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, vola); | 
 | 1728 |         break; | 
 | 1729 |     case 3: | 
 | 1730 |         volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, frameCount, in, aux, vol, vola); | 
 | 1731 |         break; | 
 | 1732 |     case 4: | 
 | 1733 |         volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, frameCount, in, aux, vol, vola); | 
 | 1734 |         break; | 
 | 1735 |     case 5: | 
 | 1736 |         volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, frameCount, in, aux, vol, vola); | 
 | 1737 |         break; | 
 | 1738 |     case 6: | 
 | 1739 |         volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, frameCount, in, aux, vol, vola); | 
 | 1740 |         break; | 
 | 1741 |     case 7: | 
 | 1742 |         volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, frameCount, in, aux, vol, vola); | 
 | 1743 |         break; | 
 | 1744 |     case 8: | 
 | 1745 |         volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, frameCount, in, aux, vol, vola); | 
 | 1746 |         break; | 
 | 1747 |     } | 
 | 1748 | } | 
 | 1749 |  | 
 | 1750 | /* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration) | 
 | 1751 |  * USEFLOATVOL (set to true if float volume is used) | 
 | 1752 |  * ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards) | 
 | 1753 |  * TO: int32_t (Q4.27) or float | 
 | 1754 |  * TI: int32_t (Q4.27) or int16_t (Q0.15) or float | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1755 |  * TA: int32_t (Q4.27) or float | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1756 |  */ | 
 | 1757 | template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL, | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1758 |     typename TO, typename TI, typename TA> | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1759 | void AudioMixer::Track::volumeMix(TO *out, size_t outFrames, | 
 | 1760 |         const TI *in, TA *aux, bool ramp) | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1761 | { | 
 | 1762 |     if (USEFLOATVOL) { | 
 | 1763 |         if (ramp) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1764 |             volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux, | 
 | 1765 |                     mPrevVolume, mVolumeInc, | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1766 | #ifdef FLOAT_AUX | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1767 |                     &mPrevAuxLevel, mAuxInc | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1768 | #else | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1769 |                     &prevAuxLevel, auxInc | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1770 | #endif | 
 | 1771 |                 ); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1772 |             if (ADJUSTVOL) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1773 |                 adjustVolumeRamp(aux != NULL, true); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1774 |             } | 
 | 1775 |         } else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1776 |             volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux, | 
 | 1777 |                     mVolume, | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1778 | #ifdef FLOAT_AUX | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1779 |                     mAuxLevel | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1780 | #else | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1781 |                     auxLevel | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1782 | #endif | 
 | 1783 |             ); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1784 |         } | 
 | 1785 |     } else { | 
 | 1786 |         if (ramp) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1787 |             volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux, | 
 | 1788 |                     prevVolume, volumeInc, &prevAuxLevel, auxInc); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1789 |             if (ADJUSTVOL) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1790 |                 adjustVolumeRamp(aux != NULL); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1791 |             } | 
 | 1792 |         } else { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1793 |             volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux, | 
 | 1794 |                     volume, auxLevel); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1795 |         } | 
 | 1796 |     } | 
 | 1797 | } | 
 | 1798 |  | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1799 | /* This process hook is called when there is a single track without | 
 | 1800 |  * aux buffer, volume ramp, or resampling. | 
 | 1801 |  * TODO: Update the hook selection: this can properly handle aux and ramp. | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1802 |  * | 
 | 1803 |  * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration) | 
 | 1804 |  * TO: int32_t (Q4.27) or float | 
 | 1805 |  * TI: int32_t (Q4.27) or int16_t (Q0.15) or float | 
 | 1806 |  * TA: int32_t (Q4.27) | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1807 |  */ | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1808 | template <int MIXTYPE, typename TO, typename TI, typename TA> | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1809 | void AudioMixer::process__noResampleOneTrack() | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1810 | { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1811 |     ALOGVV("process__noResampleOneTrack\n"); | 
 | 1812 |     LOG_ALWAYS_FATAL_IF(mEnabled.size() != 1, | 
 | 1813 |             "%zu != 1 tracks enabled", mEnabled.size()); | 
 | 1814 |     const std::shared_ptr<Track> &t = mTracks[mEnabled[0]]; | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1815 |     const uint32_t channels = t->mMixerChannelCount; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1816 |     TO* out = reinterpret_cast<TO*>(t->mainBuffer); | 
 | 1817 |     TA* aux = reinterpret_cast<TA*>(t->auxBuffer); | 
 | 1818 |     const bool ramp = t->needsRamp(); | 
 | 1819 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1820 |     for (size_t numFrames = mFrameCount; numFrames > 0; ) { | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1821 |         AudioBufferProvider::Buffer& b(t->buffer); | 
 | 1822 |         // get input buffer | 
 | 1823 |         b.frameCount = numFrames; | 
| Glenn Kasten | d79072e | 2016-01-06 08:41:20 -0800 | [diff] [blame] | 1824 |         t->bufferProvider->getNextBuffer(&b); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1825 |         const TI *in = reinterpret_cast<TI*>(b.raw); | 
 | 1826 |  | 
 | 1827 |         // in == NULL can happen if the track was flushed just after having | 
 | 1828 |         // been enabled for mixing. | 
 | 1829 |         if (in == NULL || (((uintptr_t)in) & 3)) { | 
 | 1830 |             memset(out, 0, numFrames | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1831 |                     * channels * audio_bytes_per_sample(t->mMixerFormat)); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1832 |             ALOGE_IF((((uintptr_t)in) & 3), "process__noResampleOneTrack: bus error: " | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1833 |                     "buffer %p track %p, channels %d, needs %#x", | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1834 |                     in, &t, t->channelCount, t->needs); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1835 |             return; | 
 | 1836 |         } | 
 | 1837 |  | 
 | 1838 |         const size_t outFrames = b.frameCount; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1839 |         t->volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, false /* ADJUSTVOL */> ( | 
 | 1840 |                 out, outFrames, in, aux, ramp); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1841 |  | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1842 |         out += outFrames * channels; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1843 |         if (aux != NULL) { | 
| Andy Hung | a601889 | 2018-02-21 14:32:16 -0800 | [diff] [blame] | 1844 |             aux += outFrames; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1845 |         } | 
 | 1846 |         numFrames -= b.frameCount; | 
 | 1847 |  | 
 | 1848 |         // release buffer | 
 | 1849 |         t->bufferProvider->releaseBuffer(&b); | 
 | 1850 |     } | 
 | 1851 |     if (ramp) { | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1852 |         t->adjustVolumeRamp(aux != NULL, is_same<TI, float>::value); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1853 |     } | 
 | 1854 | } | 
 | 1855 |  | 
| jiabin | 77270b8 | 2018-12-18 15:41:29 -0800 | [diff] [blame] | 1856 | void AudioMixer::processHapticData() | 
 | 1857 | { | 
 | 1858 |     // Need to keep consistent with VibrationEffect.scale(int, float, int) | 
 | 1859 |     for (const auto &pair : mGroups) { | 
 | 1860 |         // process by group of tracks with same output main buffer. | 
 | 1861 |         const auto &group = pair.second; | 
 | 1862 |         for (const int name : group) { | 
 | 1863 |             const std::shared_ptr<Track> &t = mTracks[name]; | 
 | 1864 |             if (t->mHapticPlaybackEnabled) { | 
 | 1865 |                 size_t sampleCount = mFrameCount * t->mMixerHapticChannelCount; | 
 | 1866 |                 float gamma = t->getHapticScaleGamma(); | 
 | 1867 |                 float maxAmplitudeRatio = t->getHapticMaxAmplitudeRatio(); | 
 | 1868 |                 uint8_t* buffer = (uint8_t*)pair.first + mFrameCount * audio_bytes_per_frame( | 
 | 1869 |                         t->mMixerChannelCount, t->mMixerFormat); | 
 | 1870 |                 switch (t->mMixerFormat) { | 
 | 1871 |                 // Mixer format should be AUDIO_FORMAT_PCM_FLOAT. | 
 | 1872 |                 case AUDIO_FORMAT_PCM_FLOAT: { | 
 | 1873 |                     float* fout = (float*) buffer; | 
 | 1874 |                     for (size_t i = 0; i < sampleCount; i++) { | 
 | 1875 |                         float mul = fout[i] >= 0 ? 1.0 : -1.0; | 
 | 1876 |                         fout[i] = powf(fabsf(fout[i] / HAPTIC_MAX_AMPLITUDE_FLOAT), gamma) | 
 | 1877 |                                 * maxAmplitudeRatio * HAPTIC_MAX_AMPLITUDE_FLOAT * mul; | 
 | 1878 |                     } | 
 | 1879 |                 } break; | 
 | 1880 |                 default: | 
 | 1881 |                     LOG_ALWAYS_FATAL("bad mMixerFormat: %#x", t->mMixerFormat); | 
 | 1882 |                     break; | 
 | 1883 |                 } | 
 | 1884 |                 break; | 
 | 1885 |             } | 
 | 1886 |         } | 
 | 1887 |     } | 
 | 1888 | } | 
 | 1889 |  | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1890 | /* This track hook is called to do resampling then mixing, | 
 | 1891 |  * pulling from the track's upstream AudioBufferProvider. | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1892 |  * | 
 | 1893 |  * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration) | 
 | 1894 |  * TO: int32_t (Q4.27) or float | 
 | 1895 |  * TI: int32_t (Q4.27) or int16_t (Q0.15) or float | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1896 |  * TA: int32_t (Q4.27) or float | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1897 |  */ | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1898 | template <int MIXTYPE, typename TO, typename TI, typename TA> | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1899 | void AudioMixer::Track::track__Resample(TO* out, size_t outFrameCount, TO* temp, TA* aux) | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1900 | { | 
 | 1901 |     ALOGVV("track__Resample\n"); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1902 |     mResampler->setSampleRate(sampleRate); | 
 | 1903 |     const bool ramp = needsRamp(); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1904 |     if (ramp || aux != NULL) { | 
 | 1905 |         // if ramp:        resample with unity gain to temp buffer and scale/mix in 2nd step. | 
 | 1906 |         // if aux != NULL: resample with unity gain to temp buffer then apply send level. | 
 | 1907 |  | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1908 |         mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT); | 
 | 1909 |         memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(TO)); | 
 | 1910 |         mResampler->resample((int32_t*)temp, outFrameCount, bufferProvider); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1911 |  | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1912 |         volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>( | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1913 |                 out, outFrameCount, temp, aux, ramp); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1914 |  | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1915 |     } else { // constant volume gain | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1916 |         mResampler->setVolume(mVolume[0], mVolume[1]); | 
 | 1917 |         mResampler->resample((int32_t*)out, outFrameCount, bufferProvider); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1918 |     } | 
 | 1919 | } | 
 | 1920 |  | 
 | 1921 | /* This track hook is called to mix a track, when no resampling is required. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1922 |  * The input buffer should be present in in. | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1923 |  * | 
 | 1924 |  * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration) | 
 | 1925 |  * TO: int32_t (Q4.27) or float | 
 | 1926 |  * TI: int32_t (Q4.27) or int16_t (Q0.15) or float | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1927 |  * TA: int32_t (Q4.27) or float | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1928 |  */ | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1929 | template <int MIXTYPE, typename TO, typename TI, typename TA> | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1930 | void AudioMixer::Track::track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux) | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1931 | { | 
 | 1932 |     ALOGVV("track__NoResample\n"); | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1933 |     const TI *in = static_cast<const TI *>(mIn); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1934 |  | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 1935 |     volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>( | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1936 |             out, frameCount, in, aux, needsRamp()); | 
| Andy Hung | 5e58b0a | 2014-06-23 19:07:29 -0700 | [diff] [blame] | 1937 |  | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1938 |     // MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels. | 
 | 1939 |     // MIXTYPE_MULTI reads NCHAN input channels and places to NCHAN output channels. | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1940 |     in += (MIXTYPE == MIXTYPE_MONOEXPAND) ? frameCount : frameCount * mMixerChannelCount; | 
 | 1941 |     mIn = in; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1942 | } | 
 | 1943 |  | 
 | 1944 | /* The Mixer engine generates either int32_t (Q4_27) or float data. | 
 | 1945 |  * We use this function to convert the engine buffers | 
 | 1946 |  * to the desired mixer output format, either int16_t (Q.15) or float. | 
 | 1947 |  */ | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1948 | /* static */ | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1949 | void AudioMixer::convertMixerFormat(void *out, audio_format_t mixerOutFormat, | 
 | 1950 |         void *in, audio_format_t mixerInFormat, size_t sampleCount) | 
 | 1951 | { | 
 | 1952 |     switch (mixerInFormat) { | 
 | 1953 |     case AUDIO_FORMAT_PCM_FLOAT: | 
 | 1954 |         switch (mixerOutFormat) { | 
 | 1955 |         case AUDIO_FORMAT_PCM_FLOAT: | 
 | 1956 |             memcpy(out, in, sampleCount * sizeof(float)); // MEMCPY. TODO optimize out | 
 | 1957 |             break; | 
 | 1958 |         case AUDIO_FORMAT_PCM_16_BIT: | 
 | 1959 |             memcpy_to_i16_from_float((int16_t*)out, (float*)in, sampleCount); | 
 | 1960 |             break; | 
 | 1961 |         default: | 
 | 1962 |             LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat); | 
 | 1963 |             break; | 
 | 1964 |         } | 
 | 1965 |         break; | 
 | 1966 |     case AUDIO_FORMAT_PCM_16_BIT: | 
 | 1967 |         switch (mixerOutFormat) { | 
 | 1968 |         case AUDIO_FORMAT_PCM_FLOAT: | 
| Andy Hung | 5effdf6 | 2017-11-27 13:51:40 -0800 | [diff] [blame] | 1969 |             memcpy_to_float_from_q4_27((float*)out, (const int32_t*)in, sampleCount); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1970 |             break; | 
 | 1971 |         case AUDIO_FORMAT_PCM_16_BIT: | 
| Andy Hung | 5effdf6 | 2017-11-27 13:51:40 -0800 | [diff] [blame] | 1972 |             memcpy_to_i16_from_q4_27((int16_t*)out, (const int32_t*)in, sampleCount); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1973 |             break; | 
 | 1974 |         default: | 
 | 1975 |             LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat); | 
 | 1976 |             break; | 
 | 1977 |         } | 
 | 1978 |         break; | 
 | 1979 |     default: | 
 | 1980 |         LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); | 
 | 1981 |         break; | 
 | 1982 |     } | 
 | 1983 | } | 
 | 1984 |  | 
 | 1985 | /* Returns the proper track hook to use for mixing the track into the output buffer. | 
 | 1986 |  */ | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1987 | /* static */ | 
 | 1988 | AudioMixer::hook_t AudioMixer::Track::getTrackHook(int trackType, uint32_t channelCount, | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1989 |         audio_format_t mixerInFormat, audio_format_t mixerOutFormat __unused) | 
 | 1990 | { | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 1991 |     if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) { | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1992 |         switch (trackType) { | 
 | 1993 |         case TRACKTYPE_NOP: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1994 |             return &Track::track__nop; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1995 |         case TRACKTYPE_RESAMPLE: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1996 |             return &Track::track__genericResample; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1997 |         case TRACKTYPE_NORESAMPLEMONO: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 1998 |             return &Track::track__16BitsMono; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 1999 |         case TRACKTYPE_NORESAMPLE: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2000 |             return &Track::track__16BitsStereo; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2001 |         default: | 
 | 2002 |             LOG_ALWAYS_FATAL("bad trackType: %d", trackType); | 
 | 2003 |             break; | 
 | 2004 |         } | 
 | 2005 |     } | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 2006 |     LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2007 |     switch (trackType) { | 
 | 2008 |     case TRACKTYPE_NOP: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2009 |         return &Track::track__nop; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2010 |     case TRACKTYPE_RESAMPLE: | 
 | 2011 |         switch (mixerInFormat) { | 
 | 2012 |         case AUDIO_FORMAT_PCM_FLOAT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2013 |             return (AudioMixer::hook_t) &Track::track__Resample< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2014 |                     MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2015 |         case AUDIO_FORMAT_PCM_16_BIT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2016 |             return (AudioMixer::hook_t) &Track::track__Resample< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2017 |                     MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2018 |         default: | 
 | 2019 |             LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); | 
 | 2020 |             break; | 
 | 2021 |         } | 
 | 2022 |         break; | 
 | 2023 |     case TRACKTYPE_NORESAMPLEMONO: | 
 | 2024 |         switch (mixerInFormat) { | 
 | 2025 |         case AUDIO_FORMAT_PCM_FLOAT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2026 |             return (AudioMixer::hook_t) &Track::track__NoResample< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2027 |                             MIXTYPE_MONOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2028 |         case AUDIO_FORMAT_PCM_16_BIT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2029 |             return (AudioMixer::hook_t) &Track::track__NoResample< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2030 |                             MIXTYPE_MONOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2031 |         default: | 
 | 2032 |             LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); | 
 | 2033 |             break; | 
 | 2034 |         } | 
 | 2035 |         break; | 
 | 2036 |     case TRACKTYPE_NORESAMPLE: | 
 | 2037 |         switch (mixerInFormat) { | 
 | 2038 |         case AUDIO_FORMAT_PCM_FLOAT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2039 |             return (AudioMixer::hook_t) &Track::track__NoResample< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2040 |                     MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2041 |         case AUDIO_FORMAT_PCM_16_BIT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2042 |             return (AudioMixer::hook_t) &Track::track__NoResample< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2043 |                     MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2044 |         default: | 
 | 2045 |             LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); | 
 | 2046 |             break; | 
 | 2047 |         } | 
 | 2048 |         break; | 
 | 2049 |     default: | 
 | 2050 |         LOG_ALWAYS_FATAL("bad trackType: %d", trackType); | 
 | 2051 |         break; | 
 | 2052 |     } | 
 | 2053 |     return NULL; | 
 | 2054 | } | 
 | 2055 |  | 
 | 2056 | /* Returns the proper process hook for mixing tracks. Currently works only for | 
 | 2057 |  * PROCESSTYPE_NORESAMPLEONETRACK, a mix involving one track, no resampling. | 
| Andy Hung | 395db4b | 2014-08-25 17:15:29 -0700 | [diff] [blame] | 2058 |  * | 
 | 2059 |  * TODO: Due to the special mixing considerations of duplicating to | 
 | 2060 |  * a stereo output track, the input track cannot be MONO.  This should be | 
 | 2061 |  * prevented by the caller. | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2062 |  */ | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2063 | /* static */ | 
 | 2064 | AudioMixer::process_hook_t AudioMixer::getProcessHook( | 
 | 2065 |         int processType, uint32_t channelCount, | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2066 |         audio_format_t mixerInFormat, audio_format_t mixerOutFormat) | 
 | 2067 | { | 
 | 2068 |     if (processType != PROCESSTYPE_NORESAMPLEONETRACK) { // Only NORESAMPLEONETRACK | 
 | 2069 |         LOG_ALWAYS_FATAL("bad processType: %d", processType); | 
 | 2070 |         return NULL; | 
 | 2071 |     } | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 2072 |     if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) { | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2073 |         return &AudioMixer::process__oneTrack16BitsStereoNoResampling; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2074 |     } | 
| Andy Hung | e93b6b7 | 2014-07-17 21:30:53 -0700 | [diff] [blame] | 2075 |     LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS); | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2076 |     switch (mixerInFormat) { | 
 | 2077 |     case AUDIO_FORMAT_PCM_FLOAT: | 
 | 2078 |         switch (mixerOutFormat) { | 
 | 2079 |         case AUDIO_FORMAT_PCM_FLOAT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2080 |             return &AudioMixer::process__noResampleOneTrack< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2081 |                     MIXTYPE_MULTI_SAVEONLY, float /*TO*/, float /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2082 |         case AUDIO_FORMAT_PCM_16_BIT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2083 |             return &AudioMixer::process__noResampleOneTrack< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2084 |                     MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, float /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2085 |         default: | 
 | 2086 |             LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat); | 
 | 2087 |             break; | 
 | 2088 |         } | 
 | 2089 |         break; | 
 | 2090 |     case AUDIO_FORMAT_PCM_16_BIT: | 
 | 2091 |         switch (mixerOutFormat) { | 
 | 2092 |         case AUDIO_FORMAT_PCM_FLOAT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2093 |             return &AudioMixer::process__noResampleOneTrack< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2094 |                     MIXTYPE_MULTI_SAVEONLY, float /*TO*/, int16_t /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2095 |         case AUDIO_FORMAT_PCM_16_BIT: | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 2096 |             return &AudioMixer::process__noResampleOneTrack< | 
| Andy Hung | 116a498 | 2017-11-30 10:15:08 -0800 | [diff] [blame] | 2097 |                     MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; | 
| Andy Hung | 296b741 | 2014-06-17 15:25:47 -0700 | [diff] [blame] | 2098 |         default: | 
 | 2099 |             LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat); | 
 | 2100 |             break; | 
 | 2101 |         } | 
 | 2102 |         break; | 
 | 2103 |     default: | 
 | 2104 |         LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); | 
 | 2105 |         break; | 
 | 2106 |     } | 
 | 2107 |     return NULL; | 
 | 2108 | } | 
 | 2109 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 2110 | // ---------------------------------------------------------------------------- | 
| Glenn Kasten | 63238ef | 2015-03-02 15:50:29 -0800 | [diff] [blame] | 2111 | } // namespace android |