blob: 2567b3b23878de6f0ad981aafafc34c7c00e4de0 [file] [log] [blame]
Glenn Kasten99e53b82012-01-19 08:59:58 -08001/*
Mathias Agopian65ab4712010-07-14 17:59:35 -07002**
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 Kasten7f5d3352013-02-15 23:55:04 +000019//#define LOG_NDEBUG 0
Mathias Agopian65ab4712010-07-14 17:59:35 -070020
21#include <stdint.h>
22#include <string.h>
23#include <stdlib.h>
Andy Hung5e58b0a2014-06-23 19:07:29 -070024#include <math.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070025#include <sys/types.h>
26
27#include <utils/Errors.h>
28#include <utils/Log.h>
29
Glenn Kastenf6b16782011-12-15 09:51:17 -080030#include <cutils/compiler.h>
Glenn Kasten5798d4e2012-03-08 12:18:35 -080031#include <utils/Debug.h>
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070032
33#include <system/audio.h>
34
Glenn Kasten3b21c502011-12-15 09:52:39 -080035#include <audio_utils/primitives.h>
Andy Hungef7c7fb2014-05-12 16:51:41 -070036#include <audio_utils/format.h>
Andy Hung068561c2017-01-03 17:09:32 -080037#include <media/AudioMixer.h>
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070038
Andy Hung296b7412014-06-17 15:25:47 -070039#include "AudioMixerOps.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070040
Andy Hunge93b6b72014-07-17 21:30:53 -070041// The FCC_2 macro refers to the Fixed Channel Count of 2 for the legacy integer mixer.
Andy Hung296b7412014-06-17 15:25:47 -070042#ifndef FCC_2
43#define FCC_2 2
44#endif
45
Andy Hunge93b6b72014-07-17 21:30:53 -070046// Look for MONO_HACK for any Mono hack involving legacy mono channel to
47// stereo channel conversion.
48
Andy Hung296b7412014-06-17 15:25:47 -070049/* 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 Hunga08810b2014-07-16 21:53:43 -070061#ifndef ARRAY_SIZE
62#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
63#endif
64
Andy Hung5b8fde72014-09-02 21:14:34 -070065// 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 Hung116a4982017-11-30 10:15:08 -080067static constexpr bool kUseNewMixer = true;
Andy Hung296b7412014-06-17 15:25:47 -070068
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 Hung116a4982017-11-30 10:15:08 -080072static constexpr bool kUseFloat = true;
73
74#ifdef FLOAT_AUX
75using TYPE_AUX = float;
76static_assert(kUseNewMixer && kUseFloat,
77 "kUseNewMixer and kUseFloat must be true for FLOAT_AUX option");
78#else
79using TYPE_AUX = int32_t; // q4.27
80#endif
Andy Hung296b7412014-06-17 15:25:47 -070081
Andy Hung1b2fdcb2014-07-16 17:44:34 -070082// Set to default copy buffer size in frames for input processing.
83static const size_t kCopyBufferFrameCount = 256;
84
Mathias Agopian65ab4712010-07-14 17:59:35 -070085namespace android {
Mathias Agopian65ab4712010-07-14 17:59:35 -070086
87// ----------------------------------------------------------------------------
Andy Hung1b2fdcb2014-07-16 17:44:34 -070088
Andy Hung7f475492014-08-25 16:36:37 -070089static 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 Hung1bc088a2018-02-09 15:57:31 -080093status_t AudioMixer::create(
94 int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId)
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080095{
Andy Hung1bc088a2018-02-09 15:57:31 -080096 LOG_ALWAYS_FATAL_IF(exists(name), "name %d already exists", name);
Andy Hung8ed196a2018-01-05 13:21:11 -080097
Andy Hung1bc088a2018-02-09 15:57:31 -080098 if (!isValidChannelMask(channelMask)) {
99 ALOGE("%s invalid channelMask: %#x", __func__, channelMask);
100 return BAD_VALUE;
Andy Hung8ed196a2018-01-05 13:21:11 -0800101 }
Andy Hung1bc088a2018-02-09 15:57:31 -0800102 if (!isValidFormat(format)) {
103 ALOGE("%s invalid format: %#x", __func__, format);
104 return BAD_VALUE;
105 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800106
107 auto t = std::make_shared<Track>();
Andy Hung8ed196a2018-01-05 13:21:11 -0800108 {
109 // TODO: move initialization to the Track constructor.
Glenn Kastendeeb1282012-03-25 11:59:31 -0700110 // assume default parameters for the track, except where noted below
Glenn Kastendeeb1282012-03-25 11:59:31 -0700111 t->needs = 0;
Andy Hung5e58b0a2014-06-23 19:07:29 -0700112
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 Hung97ae8242014-05-30 10:35:47 -0700116 t->volume[0] = UNITY_GAIN_INT;
117 t->volume[1] = UNITY_GAIN_INT;
Andy Hung5e58b0a2014-06-23 19:07:29 -0700118 t->prevVolume[0] = UNITY_GAIN_INT << 16;
119 t->prevVolume[1] = UNITY_GAIN_INT << 16;
Glenn Kastendeeb1282012-03-25 11:59:31 -0700120 t->volumeInc[0] = 0;
121 t->volumeInc[1] = 0;
122 t->auxLevel = 0;
123 t->auxInc = 0;
Andy Hung5e58b0a2014-06-23 19:07:29 -0700124 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 Kastendeeb1282012-03-25 11:59:31 -0700137 // no initialization needed
Glenn Kastendeeb1282012-03-25 11:59:31 -0700138 // t->frameCount
jiabin245cdd92018-12-07 17:55:15 -0800139 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 Hung68112fc2014-05-14 14:13:23 -0700142 t->channelCount = audio_channel_count_from_out_mask(channelMask);
Glenn Kastendeeb1282012-03-25 11:59:31 -0700143 t->enabled = false;
Andy Hunge93b6b72014-07-17 21:30:53 -0700144 ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
Andy Hungef7c7fb2014-05-12 16:51:41 -0700145 "Non-stereo channel mask: %d\n", channelMask);
Andy Hung68112fc2014-05-14 14:13:23 -0700146 t->channelMask = channelMask;
Jean-Michel Trivid06e1322012-09-12 15:47:07 -0700147 t->sessionId = sessionId;
Glenn Kastendeeb1282012-03-25 11:59:31 -0700148 // 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 Hung8ed196a2018-01-05 13:21:11 -0800154 t->mIn = NULL;
Glenn Kastendeeb1282012-03-25 11:59:31 -0700155 t->sampleRate = mSampleRate;
156 // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
157 t->mainBuffer = NULL;
158 t->auxBuffer = NULL;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700159 t->mInputBufferProvider = NULL;
Andy Hung78820702014-02-28 16:23:02 -0800160 t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
Andy Hunge8a1ced2014-05-09 15:02:21 -0700161 t->mFormat = format;
Andy Hung7f475492014-08-25 16:36:37 -0700162 t->mMixerInFormat = selectMixerInFormat(format);
163 t->mDownmixRequiresFormat = AUDIO_FORMAT_INVALID; // no format required
Andy Hunge93b6b72014-07-17 21:30:53 -0700164 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 Garcia5a8a95d2015-04-18 14:47:04 -0700167 t->mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
jiabindce8f8c2018-12-10 17:49:31 -0800168 // haptic
jiabin245cdd92018-12-07 17:55:15 -0800169 t->mHapticPlaybackEnabled = false;
170 t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
171 t->mMixerHapticChannelCount = 0;
172 t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
173 t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
174 t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
175 t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
jiabindce8f8c2018-12-10 17:49:31 -0800176 t->mKeepContractedChannels = false;
Andy Hung296b7412014-06-17 15:25:47 -0700177 // Check the downmixing (or upmixing) requirements.
Andy Hung0f451e92014-08-04 21:28:47 -0700178 status_t status = t->prepareForDownmix();
Andy Hung68112fc2014-05-14 14:13:23 -0700179 if (status != OK) {
180 ALOGE("AudioMixer::getTrackName invalid channelMask (%#x)", channelMask);
Andy Hung1bc088a2018-02-09 15:57:31 -0800181 return BAD_VALUE;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700182 }
Andy Hung7f475492014-08-25 16:36:37 -0700183 // prepareForDownmix() may change mDownmixRequiresFormat
Andy Hung296b7412014-06-17 15:25:47 -0700184 ALOGVV("mMixerFormat:%#x mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
Andy Hung0f451e92014-08-04 21:28:47 -0700185 t->prepareForReformat();
jiabindce8f8c2018-12-10 17:49:31 -0800186 t->prepareForAdjustChannelsNonDestructive(mFrameCount);
187 t->prepareForAdjustChannels();
Andy Hung1bc088a2018-02-09 15:57:31 -0800188
189 mTracks[name] = t;
190 return OK;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700191 }
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800192}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700193
Andy Hunge93b6b72014-07-17 21:30:53 -0700194// Called when channel masks have changed for a track name
Andy Hung7f475492014-08-25 16:36:37 -0700195// TODO: Fix DownmixerBufferProvider not to (possibly) change mixer input format,
Andy Hunge93b6b72014-07-17 21:30:53 -0700196// which will simplify this logic.
197bool AudioMixer::setChannelMasks(int name,
198 audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask) {
Andy Hung1bc088a2018-02-09 15:57:31 -0800199 LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
Andy Hung8ed196a2018-01-05 13:21:11 -0800200 const std::shared_ptr<Track> &track = mTracks[name];
Andy Hunge93b6b72014-07-17 21:30:53 -0700201
jiabin245cdd92018-12-07 17:55:15 -0800202 if (trackChannelMask == (track->channelMask | track->mHapticChannelMask)
203 && mixerChannelMask == (track->mMixerChannelMask | track->mMixerHapticChannelMask)) {
Andy Hunge93b6b72014-07-17 21:30:53 -0700204 return false; // no need to change
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700205 }
jiabin245cdd92018-12-07 17:55:15 -0800206 const audio_channel_mask_t hapticChannelMask = trackChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
207 trackChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
208 const audio_channel_mask_t mixerHapticChannelMask = mixerChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
209 mixerChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
Andy Hunge93b6b72014-07-17 21:30:53 -0700210 // always recompute for both channel masks even if only one has changed.
211 const uint32_t trackChannelCount = audio_channel_count_from_out_mask(trackChannelMask);
212 const uint32_t mixerChannelCount = audio_channel_count_from_out_mask(mixerChannelMask);
jiabin245cdd92018-12-07 17:55:15 -0800213 const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(hapticChannelMask);
214 const uint32_t mixerHapticChannelCount =
215 audio_channel_count_from_out_mask(mixerHapticChannelMask);
Andy Hunge93b6b72014-07-17 21:30:53 -0700216
217 ALOG_ASSERT((trackChannelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX)
218 && trackChannelCount
219 && mixerChannelCount);
Andy Hung8ed196a2018-01-05 13:21:11 -0800220 track->channelMask = trackChannelMask;
221 track->channelCount = trackChannelCount;
222 track->mMixerChannelMask = mixerChannelMask;
223 track->mMixerChannelCount = mixerChannelCount;
jiabin245cdd92018-12-07 17:55:15 -0800224 track->mHapticChannelMask = hapticChannelMask;
225 track->mHapticChannelCount = hapticChannelCount;
226 track->mMixerHapticChannelMask = mixerHapticChannelMask;
227 track->mMixerHapticChannelCount = mixerHapticChannelCount;
228
229 if (track->mHapticChannelCount > 0) {
230 track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount;
231 track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount;
232 track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount;
233 track->mAdjustNonDestructiveOutChannelCount = track->channelCount;
234 track->mKeepContractedChannels = track->mHapticPlaybackEnabled;
235 } else {
236 track->mAdjustInChannelCount = 0;
237 track->mAdjustOutChannelCount = 0;
238 track->mAdjustNonDestructiveInChannelCount = 0;
239 track->mAdjustNonDestructiveOutChannelCount = 0;
240 track->mKeepContractedChannels = false;
241 }
Andy Hunge93b6b72014-07-17 21:30:53 -0700242
243 // channel masks have changed, does this track need a downmixer?
244 // update to try using our desired format (if we aren't already using it)
Andy Hung8ed196a2018-01-05 13:21:11 -0800245 const status_t status = track->prepareForDownmix();
Andy Hunge93b6b72014-07-17 21:30:53 -0700246 ALOGE_IF(status != OK,
Andy Hung0f451e92014-08-04 21:28:47 -0700247 "prepareForDownmix error %d, track channel mask %#x, mixer channel mask %#x",
Andy Hung8ed196a2018-01-05 13:21:11 -0800248 status, track->channelMask, track->mMixerChannelMask);
Andy Hunge93b6b72014-07-17 21:30:53 -0700249
Yung Ti Su1a0ecc32018-05-07 11:09:15 +0800250 // always do reformat since channel mask changed,
251 // do it after downmix since track format may change!
252 track->prepareForReformat();
Andy Hunge93b6b72014-07-17 21:30:53 -0700253
jiabindce8f8c2018-12-10 17:49:31 -0800254 track->prepareForAdjustChannelsNonDestructive(mFrameCount);
255 track->prepareForAdjustChannels();
256
Yung Ti Sub5d11952018-05-22 22:31:14 +0800257 if (track->mResampler.get() != nullptr) {
Andy Hung7f475492014-08-25 16:36:37 -0700258 // resampler channels may have changed.
Andy Hung8ed196a2018-01-05 13:21:11 -0800259 const uint32_t resetToSampleRate = track->sampleRate;
260 track->mResampler.reset(nullptr);
261 track->sampleRate = mSampleRate; // without resampler, track rate is device sample rate.
Andy Hunge93b6b72014-07-17 21:30:53 -0700262 // recreate the resampler with updated format, channels, saved sampleRate.
Andy Hung8ed196a2018-01-05 13:21:11 -0800263 track->setResampler(resetToSampleRate /*trackSampleRate*/, mSampleRate /*devSampleRate*/);
Andy Hunge93b6b72014-07-17 21:30:53 -0700264 }
265 return true;
266}
267
Andy Hung8ed196a2018-01-05 13:21:11 -0800268void AudioMixer::Track::unprepareForDownmix() {
Andy Hung0f451e92014-08-04 21:28:47 -0700269 ALOGV("AudioMixer::unprepareForDownmix(%p)", this);
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700270
Andy Hung8ed196a2018-01-05 13:21:11 -0800271 if (mPostDownmixReformatBufferProvider.get() != nullptr) {
Andy Hung85395892017-04-25 16:47:52 -0700272 // release any buffers held by the mPostDownmixReformatBufferProvider
Andy Hung8ed196a2018-01-05 13:21:11 -0800273 // before deallocating the mDownmixerBufferProvider.
Andy Hung85395892017-04-25 16:47:52 -0700274 mPostDownmixReformatBufferProvider->reset();
275 }
276
Andy Hung7f475492014-08-25 16:36:37 -0700277 mDownmixRequiresFormat = AUDIO_FORMAT_INVALID;
Andy Hung8ed196a2018-01-05 13:21:11 -0800278 if (mDownmixerBufferProvider.get() != nullptr) {
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700279 // this track had previously been configured with a downmixer, delete it
Andy Hung8ed196a2018-01-05 13:21:11 -0800280 mDownmixerBufferProvider.reset(nullptr);
Andy Hung0f451e92014-08-04 21:28:47 -0700281 reconfigureBufferProviders();
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700282 } else {
283 ALOGV(" nothing to do, no downmixer to delete");
284 }
285}
286
Andy Hung8ed196a2018-01-05 13:21:11 -0800287status_t AudioMixer::Track::prepareForDownmix()
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700288{
Andy Hung0f451e92014-08-04 21:28:47 -0700289 ALOGV("AudioMixer::prepareForDownmix(%p) with mask 0x%x",
290 this, channelMask);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700291
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700292 // discard the previous downmixer if there was one
Andy Hung0f451e92014-08-04 21:28:47 -0700293 unprepareForDownmix();
Andy Hung73e62e22015-04-20 12:06:38 -0700294 // MONO_HACK Only remix (upmix or downmix) if the track and mixer/device channel masks
Andy Hung0f451e92014-08-04 21:28:47 -0700295 // are not the same and not handled internally, as mono -> stereo currently is.
296 if (channelMask == mMixerChannelMask
297 || (channelMask == AUDIO_CHANNEL_OUT_MONO
298 && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO)) {
299 return NO_ERROR;
300 }
Andy Hung650ceb92015-01-29 13:31:12 -0800301 // DownmixerBufferProvider is only used for position masks.
302 if (audio_channel_mask_get_representation(channelMask)
303 == AUDIO_CHANNEL_REPRESENTATION_POSITION
304 && DownmixerBufferProvider::isMultichannelCapable()) {
Andy Hung8ed196a2018-01-05 13:21:11 -0800305 mDownmixerBufferProvider.reset(new DownmixerBufferProvider(channelMask,
Andy Hung0f451e92014-08-04 21:28:47 -0700306 mMixerChannelMask,
307 AUDIO_FORMAT_PCM_16_BIT /* TODO: use mMixerInFormat, now only PCM 16 */,
Andy Hung8ed196a2018-01-05 13:21:11 -0800308 sampleRate, sessionId, kCopyBufferFrameCount));
309 if (static_cast<DownmixerBufferProvider *>(mDownmixerBufferProvider.get())->isValid()) {
Andy Hung7f475492014-08-25 16:36:37 -0700310 mDownmixRequiresFormat = AUDIO_FORMAT_PCM_16_BIT; // PCM 16 bit required for downmix
Andy Hung0f451e92014-08-04 21:28:47 -0700311 reconfigureBufferProviders();
Andy Hung34803d52014-07-16 21:41:35 -0700312 return NO_ERROR;
313 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800314 // mDownmixerBufferProvider reset below.
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700315 }
Andy Hunge93b6b72014-07-17 21:30:53 -0700316
317 // Effect downmixer does not accept the channel conversion. Let's use our remixer.
Andy Hung8ed196a2018-01-05 13:21:11 -0800318 mDownmixerBufferProvider.reset(new RemixBufferProvider(channelMask,
319 mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount));
Andy Hunge93b6b72014-07-17 21:30:53 -0700320 // Remix always finds a conversion whereas Downmixer effect above may fail.
Andy Hung0f451e92014-08-04 21:28:47 -0700321 reconfigureBufferProviders();
Andy Hunge93b6b72014-07-17 21:30:53 -0700322 return NO_ERROR;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700323}
324
Andy Hung8ed196a2018-01-05 13:21:11 -0800325void AudioMixer::Track::unprepareForReformat() {
Andy Hung0f451e92014-08-04 21:28:47 -0700326 ALOGV("AudioMixer::unprepareForReformat(%p)", this);
Andy Hung7f475492014-08-25 16:36:37 -0700327 bool requiresReconfigure = false;
Andy Hung8ed196a2018-01-05 13:21:11 -0800328 if (mReformatBufferProvider.get() != nullptr) {
329 mReformatBufferProvider.reset(nullptr);
Andy Hung7f475492014-08-25 16:36:37 -0700330 requiresReconfigure = true;
331 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800332 if (mPostDownmixReformatBufferProvider.get() != nullptr) {
333 mPostDownmixReformatBufferProvider.reset(nullptr);
Andy Hung7f475492014-08-25 16:36:37 -0700334 requiresReconfigure = true;
335 }
336 if (requiresReconfigure) {
Andy Hung0f451e92014-08-04 21:28:47 -0700337 reconfigureBufferProviders();
Andy Hungef7c7fb2014-05-12 16:51:41 -0700338 }
339}
340
Andy Hung8ed196a2018-01-05 13:21:11 -0800341status_t AudioMixer::Track::prepareForReformat()
Andy Hungef7c7fb2014-05-12 16:51:41 -0700342{
Andy Hung0f451e92014-08-04 21:28:47 -0700343 ALOGV("AudioMixer::prepareForReformat(%p) with format %#x", this, mFormat);
Andy Hung7f475492014-08-25 16:36:37 -0700344 // discard previous reformatters
Andy Hung0f451e92014-08-04 21:28:47 -0700345 unprepareForReformat();
Andy Hung7f475492014-08-25 16:36:37 -0700346 // only configure reformatters as needed
347 const audio_format_t targetFormat = mDownmixRequiresFormat != AUDIO_FORMAT_INVALID
348 ? mDownmixRequiresFormat : mMixerInFormat;
349 bool requiresReconfigure = false;
350 if (mFormat != targetFormat) {
Andy Hung8ed196a2018-01-05 13:21:11 -0800351 mReformatBufferProvider.reset(new ReformatBufferProvider(
Andy Hung0f451e92014-08-04 21:28:47 -0700352 audio_channel_count_from_out_mask(channelMask),
Andy Hung7f475492014-08-25 16:36:37 -0700353 mFormat,
354 targetFormat,
Andy Hung8ed196a2018-01-05 13:21:11 -0800355 kCopyBufferFrameCount));
Andy Hung7f475492014-08-25 16:36:37 -0700356 requiresReconfigure = true;
Kevin Rocarde053bfa2017-11-09 22:07:34 -0800357 } else if (mFormat == AUDIO_FORMAT_PCM_FLOAT) {
358 // Input and output are floats, make sure application did not provide > 3db samples
359 // that would break volume application (b/68099072)
360 // TODO: add a trusted source flag to avoid the overhead
361 mReformatBufferProvider.reset(new ClampFloatBufferProvider(
362 audio_channel_count_from_out_mask(channelMask),
363 kCopyBufferFrameCount));
364 requiresReconfigure = true;
Andy Hung7f475492014-08-25 16:36:37 -0700365 }
366 if (targetFormat != mMixerInFormat) {
Andy Hung8ed196a2018-01-05 13:21:11 -0800367 mPostDownmixReformatBufferProvider.reset(new ReformatBufferProvider(
Andy Hung7f475492014-08-25 16:36:37 -0700368 audio_channel_count_from_out_mask(mMixerChannelMask),
369 targetFormat,
370 mMixerInFormat,
Andy Hung8ed196a2018-01-05 13:21:11 -0800371 kCopyBufferFrameCount));
Andy Hung7f475492014-08-25 16:36:37 -0700372 requiresReconfigure = true;
373 }
374 if (requiresReconfigure) {
Andy Hung0f451e92014-08-04 21:28:47 -0700375 reconfigureBufferProviders();
Andy Hung296b7412014-06-17 15:25:47 -0700376 }
377 return NO_ERROR;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700378}
379
jiabindce8f8c2018-12-10 17:49:31 -0800380void AudioMixer::Track::unprepareForAdjustChannels()
381{
382 ALOGV("AUDIOMIXER::unprepareForAdjustChannels");
383 if (mAdjustChannelsBufferProvider.get() != nullptr) {
384 mAdjustChannelsBufferProvider.reset(nullptr);
385 reconfigureBufferProviders();
386 }
387}
388
389status_t AudioMixer::Track::prepareForAdjustChannels()
390{
391 ALOGV("AudioMixer::prepareForAdjustChannels(%p) with inChannelCount: %u, outChannelCount: %u",
392 this, mAdjustInChannelCount, mAdjustOutChannelCount);
393 unprepareForAdjustChannels();
394 if (mAdjustInChannelCount != mAdjustOutChannelCount) {
395 mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider(
396 mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, kCopyBufferFrameCount));
397 reconfigureBufferProviders();
398 }
399 return NO_ERROR;
400}
401
402void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
403{
404 ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
405 if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
406 mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
407 reconfigureBufferProviders();
408 }
409}
410
411status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames)
412{
413 ALOGV("AudioMixer::prepareForAdjustChannelsNonDestructive(%p) with inChannelCount: %u, "
414 "outChannelCount: %u, keepContractedChannels: %d",
415 this, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount,
416 mKeepContractedChannels);
417 unprepareForAdjustChannelsNonDestructive();
418 if (mAdjustNonDestructiveInChannelCount != mAdjustNonDestructiveOutChannelCount) {
419 uint8_t* buffer = mKeepContractedChannels
420 ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
421 mMixerChannelCount, mMixerFormat)
422 : NULL;
423 mAdjustChannelsNonDestructiveBufferProvider.reset(
424 new AdjustChannelsNonDestructiveBufferProvider(
425 mFormat,
426 mAdjustNonDestructiveInChannelCount,
427 mAdjustNonDestructiveOutChannelCount,
428 mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
429 frames,
430 buffer));
431 reconfigureBufferProviders();
432 }
433 return NO_ERROR;
434}
435
436void AudioMixer::Track::clearContractedBuffer()
437{
438 if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
439 static_cast<AdjustChannelsNonDestructiveBufferProvider*>(
440 mAdjustChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
441 }
442}
443
Andy Hung8ed196a2018-01-05 13:21:11 -0800444void AudioMixer::Track::reconfigureBufferProviders()
Andy Hungef7c7fb2014-05-12 16:51:41 -0700445{
Andy Hung3a34df92018-08-21 12:32:30 -0700446 // configure from upstream to downstream buffer providers.
Andy Hung0f451e92014-08-04 21:28:47 -0700447 bufferProvider = mInputBufferProvider;
jiabindce8f8c2018-12-10 17:49:31 -0800448 if (mAdjustChannelsBufferProvider.get() != nullptr) {
449 mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
450 bufferProvider = mAdjustChannelsBufferProvider.get();
451 }
452 if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
453 mAdjustChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
454 bufferProvider = mAdjustChannelsNonDestructiveBufferProvider.get();
455 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800456 if (mReformatBufferProvider.get() != nullptr) {
Andy Hung0f451e92014-08-04 21:28:47 -0700457 mReformatBufferProvider->setBufferProvider(bufferProvider);
Andy Hung8ed196a2018-01-05 13:21:11 -0800458 bufferProvider = mReformatBufferProvider.get();
Andy Hungef7c7fb2014-05-12 16:51:41 -0700459 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800460 if (mDownmixerBufferProvider.get() != nullptr) {
461 mDownmixerBufferProvider->setBufferProvider(bufferProvider);
462 bufferProvider = mDownmixerBufferProvider.get();
Andy Hungef7c7fb2014-05-12 16:51:41 -0700463 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800464 if (mPostDownmixReformatBufferProvider.get() != nullptr) {
Andy Hung7f475492014-08-25 16:36:37 -0700465 mPostDownmixReformatBufferProvider->setBufferProvider(bufferProvider);
Andy Hung8ed196a2018-01-05 13:21:11 -0800466 bufferProvider = mPostDownmixReformatBufferProvider.get();
Andy Hung7f475492014-08-25 16:36:37 -0700467 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800468 if (mTimestretchBufferProvider.get() != nullptr) {
Andy Hungc5656cc2015-03-26 19:04:33 -0700469 mTimestretchBufferProvider->setBufferProvider(bufferProvider);
Andy Hung8ed196a2018-01-05 13:21:11 -0800470 bufferProvider = mTimestretchBufferProvider.get();
Andy Hungc5656cc2015-03-26 19:04:33 -0700471 }
Andy Hungef7c7fb2014-05-12 16:51:41 -0700472}
473
Andy Hung1bc088a2018-02-09 15:57:31 -0800474void AudioMixer::destroy(int name)
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800475{
Andy Hung1bc088a2018-02-09 15:57:31 -0800476 LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
Glenn Kasten237a6242011-12-15 15:32:27 -0800477 ALOGV("deleteTrackName(%d)", name);
Andy Hung8ed196a2018-01-05 13:21:11 -0800478
479 if (mTracks[name]->enabled) {
480 invalidate();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700481 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800482 mTracks.erase(name); // deallocate track
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800483}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700484
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800485void AudioMixer::enable(int name)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700486{
Andy Hung1bc088a2018-02-09 15:57:31 -0800487 LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
Andy Hung8ed196a2018-01-05 13:21:11 -0800488 const std::shared_ptr<Track> &track = mTracks[name];
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800489
Andy Hung8ed196a2018-01-05 13:21:11 -0800490 if (!track->enabled) {
491 track->enabled = true;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800492 ALOGV("enable(%d)", name);
Andy Hung8ed196a2018-01-05 13:21:11 -0800493 invalidate();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700494 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700495}
496
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800497void AudioMixer::disable(int name)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700498{
Andy Hung1bc088a2018-02-09 15:57:31 -0800499 LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
Andy Hung8ed196a2018-01-05 13:21:11 -0800500 const std::shared_ptr<Track> &track = mTracks[name];
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800501
Andy Hung8ed196a2018-01-05 13:21:11 -0800502 if (track->enabled) {
503 track->enabled = false;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800504 ALOGV("disable(%d)", name);
Andy Hung8ed196a2018-01-05 13:21:11 -0800505 invalidate();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700506 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700507}
508
Andy Hung5866a3b2014-05-29 21:33:13 -0700509/* Sets the volume ramp variables for the AudioMixer.
510 *
Andy Hung5e58b0a2014-06-23 19:07:29 -0700511 * The volume ramp variables are used to transition from the previous
512 * volume to the set volume. ramp controls the duration of the transition.
513 * Its value is typically one state framecount period, but may also be 0,
514 * meaning "immediate."
Andy Hung5866a3b2014-05-29 21:33:13 -0700515 *
Andy Hung5e58b0a2014-06-23 19:07:29 -0700516 * FIXME: 1) Volume ramp is enabled only if there is a nonzero integer increment
517 * even if there is a nonzero floating point increment (in that case, the volume
518 * change is immediate). This restriction should be changed when the legacy mixer
519 * is removed (see #2).
520 * FIXME: 2) Integer volume variables are used for Legacy mixing and should be removed
521 * when no longer needed.
522 *
523 * @param newVolume set volume target in floating point [0.0, 1.0].
524 * @param ramp number of frames to increment over. if ramp is 0, the volume
525 * should be set immediately. Currently ramp should not exceed 65535 (frames).
526 * @param pIntSetVolume pointer to the U4.12 integer target volume, set on return.
527 * @param pIntPrevVolume pointer to the U4.28 integer previous volume, set on return.
528 * @param pIntVolumeInc pointer to the U4.28 increment per output audio frame, set on return.
529 * @param pSetVolume pointer to the float target volume, set on return.
530 * @param pPrevVolume pointer to the float previous volume, set on return.
531 * @param pVolumeInc pointer to the float increment per output audio frame, set on return.
Andy Hung5866a3b2014-05-29 21:33:13 -0700532 * @return true if the volume has changed, false if volume is same.
533 */
Andy Hung5e58b0a2014-06-23 19:07:29 -0700534static inline bool setVolumeRampVariables(float newVolume, int32_t ramp,
535 int16_t *pIntSetVolume, int32_t *pIntPrevVolume, int32_t *pIntVolumeInc,
536 float *pSetVolume, float *pPrevVolume, float *pVolumeInc) {
Andy Hunge09c9942015-05-08 16:58:13 -0700537 // check floating point volume to see if it is identical to the previously
538 // set volume.
539 // We do not use a tolerance here (and reject changes too small)
540 // as it may be confusing to use a different value than the one set.
541 // If the resulting volume is too small to ramp, it is a direct set of the volume.
Andy Hung5e58b0a2014-06-23 19:07:29 -0700542 if (newVolume == *pSetVolume) {
Andy Hung5866a3b2014-05-29 21:33:13 -0700543 return false;
544 }
Andy Hunge09c9942015-05-08 16:58:13 -0700545 if (newVolume < 0) {
546 newVolume = 0; // should not have negative volumes
Andy Hung5866a3b2014-05-29 21:33:13 -0700547 } else {
Andy Hunge09c9942015-05-08 16:58:13 -0700548 switch (fpclassify(newVolume)) {
549 case FP_SUBNORMAL:
550 case FP_NAN:
551 newVolume = 0;
552 break;
553 case FP_ZERO:
554 break; // zero volume is fine
555 case FP_INFINITE:
556 // Infinite volume could be handled consistently since
557 // floating point math saturates at infinities,
558 // but we limit volume to unity gain float.
559 // ramp = 0; break;
560 //
561 newVolume = AudioMixer::UNITY_GAIN_FLOAT;
562 break;
563 case FP_NORMAL:
564 default:
565 // Floating point does not have problems with overflow wrap
566 // that integer has. However, we limit the volume to
567 // unity gain here.
568 // TODO: Revisit the volume limitation and perhaps parameterize.
569 if (newVolume > AudioMixer::UNITY_GAIN_FLOAT) {
570 newVolume = AudioMixer::UNITY_GAIN_FLOAT;
571 }
572 break;
573 }
Andy Hung5866a3b2014-05-29 21:33:13 -0700574 }
Andy Hung5e58b0a2014-06-23 19:07:29 -0700575
Andy Hunge09c9942015-05-08 16:58:13 -0700576 // set floating point volume ramp
577 if (ramp != 0) {
578 // when the ramp completes, *pPrevVolume is set to *pSetVolume, so there
579 // is no computational mismatch; hence equality is checked here.
580 ALOGD_IF(*pPrevVolume != *pSetVolume, "previous float ramp hasn't finished,"
581 " prev:%f set_to:%f", *pPrevVolume, *pSetVolume);
582 const float inc = (newVolume - *pPrevVolume) / ramp; // could be inf, nan, subnormal
Andy Hung8ed196a2018-01-05 13:21:11 -0800583 // could be inf, cannot be nan, subnormal
584 const float maxv = std::max(newVolume, *pPrevVolume);
Andy Hunge09c9942015-05-08 16:58:13 -0700585
586 if (isnormal(inc) // inc must be a normal number (no subnormals, infinite, nan)
587 && maxv + inc != maxv) { // inc must make forward progress
588 *pVolumeInc = inc;
589 // ramp is set now.
590 // Note: if newVolume is 0, then near the end of the ramp,
591 // it may be possible that the ramped volume may be subnormal or
592 // temporarily negative by a small amount or subnormal due to floating
593 // point inaccuracies.
594 } else {
595 ramp = 0; // ramp not allowed
596 }
Andy Hung5e58b0a2014-06-23 19:07:29 -0700597 }
Andy Hunge09c9942015-05-08 16:58:13 -0700598
599 // compute and check integer volume, no need to check negative values
600 // The integer volume is limited to "unity_gain" to avoid wrapping and other
601 // audio artifacts, so it never reaches the range limit of U4.28.
602 // We safely use signed 16 and 32 bit integers here.
603 const float scaledVolume = newVolume * AudioMixer::UNITY_GAIN_INT; // not neg, subnormal, nan
604 const int32_t intVolume = (scaledVolume >= (float)AudioMixer::UNITY_GAIN_INT) ?
605 AudioMixer::UNITY_GAIN_INT : (int32_t)scaledVolume;
606
607 // set integer volume ramp
608 if (ramp != 0) {
609 // integer volume is U4.12 (to use 16 bit multiplies), but ramping uses U4.28.
610 // when the ramp completes, *pIntPrevVolume is set to *pIntSetVolume << 16, so there
611 // is no computational mismatch; hence equality is checked here.
612 ALOGD_IF(*pIntPrevVolume != *pIntSetVolume << 16, "previous int ramp hasn't finished,"
613 " prev:%d set_to:%d", *pIntPrevVolume, *pIntSetVolume << 16);
614 const int32_t inc = ((intVolume << 16) - *pIntPrevVolume) / ramp;
615
616 if (inc != 0) { // inc must make forward progress
617 *pIntVolumeInc = inc;
618 } else {
619 ramp = 0; // ramp not allowed
620 }
621 }
622
623 // if no ramp, or ramp not allowed, then clear float and integer increments
624 if (ramp == 0) {
Andy Hung5e58b0a2014-06-23 19:07:29 -0700625 *pVolumeInc = 0;
626 *pPrevVolume = newVolume;
Andy Hung5e58b0a2014-06-23 19:07:29 -0700627 *pIntVolumeInc = 0;
628 *pIntPrevVolume = intVolume << 16;
629 }
Andy Hunge09c9942015-05-08 16:58:13 -0700630 *pSetVolume = newVolume;
Andy Hung5e58b0a2014-06-23 19:07:29 -0700631 *pIntSetVolume = intVolume;
Andy Hung5866a3b2014-05-29 21:33:13 -0700632 return true;
633}
634
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800635void AudioMixer::setParameter(int name, int target, int param, void *value)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700636{
Andy Hung1bc088a2018-02-09 15:57:31 -0800637 LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
Andy Hung8ed196a2018-01-05 13:21:11 -0800638 const std::shared_ptr<Track> &track = mTracks[name];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700639
Kévin PETIT377b2ec2014-02-03 12:35:36 +0000640 int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value));
641 int32_t *valueBuf = reinterpret_cast<int32_t*>(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700642
643 switch (target) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700644
Mathias Agopian65ab4712010-07-14 17:59:35 -0700645 case TRACK:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800646 switch (param) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700647 case CHANNEL_MASK: {
Andy Hunge93b6b72014-07-17 21:30:53 -0700648 const audio_channel_mask_t trackChannelMask =
649 static_cast<audio_channel_mask_t>(valueInt);
jiabin245cdd92018-12-07 17:55:15 -0800650 if (setChannelMasks(name, trackChannelMask,
651 (track->mMixerChannelMask | track->mMixerHapticChannelMask))) {
Andy Hunge93b6b72014-07-17 21:30:53 -0700652 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", trackChannelMask);
Andy Hung8ed196a2018-01-05 13:21:11 -0800653 invalidate();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700654 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700655 } break;
656 case MAIN_BUFFER:
Andy Hung8ed196a2018-01-05 13:21:11 -0800657 if (track->mainBuffer != valueBuf) {
658 track->mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100659 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
jiabindce8f8c2018-12-10 17:49:31 -0800660 if (track->mKeepContractedChannels) {
661 track->prepareForAdjustChannelsNonDestructive(mFrameCount);
662 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800663 invalidate();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700664 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700665 break;
666 case AUX_BUFFER:
Andy Hung8ed196a2018-01-05 13:21:11 -0800667 if (track->auxBuffer != valueBuf) {
668 track->auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100669 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Andy Hung8ed196a2018-01-05 13:21:11 -0800670 invalidate();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700671 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700672 break;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700673 case FORMAT: {
674 audio_format_t format = static_cast<audio_format_t>(valueInt);
Andy Hung8ed196a2018-01-05 13:21:11 -0800675 if (track->mFormat != format) {
Andy Hungef7c7fb2014-05-12 16:51:41 -0700676 ALOG_ASSERT(audio_is_linear_pcm(format), "Invalid format %#x", format);
Andy Hung8ed196a2018-01-05 13:21:11 -0800677 track->mFormat = format;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700678 ALOGV("setParameter(TRACK, FORMAT, %#x)", format);
Andy Hung8ed196a2018-01-05 13:21:11 -0800679 track->prepareForReformat();
680 invalidate();
Andy Hungef7c7fb2014-05-12 16:51:41 -0700681 }
682 } break;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700683 // FIXME do we want to support setting the downmix type from AudioFlinger?
684 // for a specific track? or per mixer?
685 /* case DOWNMIX_TYPE:
686 break */
Andy Hung78820702014-02-28 16:23:02 -0800687 case MIXER_FORMAT: {
Andy Hunga1ab7cc2014-02-24 19:26:52 -0800688 audio_format_t format = static_cast<audio_format_t>(valueInt);
Andy Hung8ed196a2018-01-05 13:21:11 -0800689 if (track->mMixerFormat != format) {
690 track->mMixerFormat = format;
Andy Hung78820702014-02-28 16:23:02 -0800691 ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
jiabindce8f8c2018-12-10 17:49:31 -0800692 if (track->mKeepContractedChannels) {
693 track->prepareForAdjustChannelsNonDestructive(mFrameCount);
694 }
Andy Hunga1ab7cc2014-02-24 19:26:52 -0800695 }
696 } break;
Andy Hunge93b6b72014-07-17 21:30:53 -0700697 case MIXER_CHANNEL_MASK: {
698 const audio_channel_mask_t mixerChannelMask =
699 static_cast<audio_channel_mask_t>(valueInt);
jiabin245cdd92018-12-07 17:55:15 -0800700 if (setChannelMasks(name, track->channelMask | track->mHapticChannelMask,
701 mixerChannelMask)) {
Andy Hunge93b6b72014-07-17 21:30:53 -0700702 ALOGV("setParameter(TRACK, MIXER_CHANNEL_MASK, %#x)", mixerChannelMask);
Andy Hung8ed196a2018-01-05 13:21:11 -0800703 invalidate();
Andy Hunge93b6b72014-07-17 21:30:53 -0700704 }
705 } break;
jiabin245cdd92018-12-07 17:55:15 -0800706 case HAPTIC_ENABLED: {
707 const bool hapticPlaybackEnabled = static_cast<bool>(valueInt);
708 if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) {
709 track->mHapticPlaybackEnabled = hapticPlaybackEnabled;
710 track->mKeepContractedChannels = hapticPlaybackEnabled;
711 track->prepareForAdjustChannelsNonDestructive(mFrameCount);
712 track->prepareForAdjustChannels();
713 }
714 } break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700715 default:
Glenn Kastenadad3d72014-02-21 14:51:43 -0800716 LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700717 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700718 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700719
Mathias Agopian65ab4712010-07-14 17:59:35 -0700720 case RESAMPLE:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800721 switch (param) {
722 case SAMPLE_RATE:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800723 ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
Andy Hung8ed196a2018-01-05 13:21:11 -0800724 if (track->setResampler(uint32_t(valueInt), mSampleRate)) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700725 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
726 uint32_t(valueInt));
Andy Hung8ed196a2018-01-05 13:21:11 -0800727 invalidate();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700728 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800729 break;
730 case RESET:
Andy Hung8ed196a2018-01-05 13:21:11 -0800731 track->resetResampler();
732 invalidate();
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800733 break;
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700734 case REMOVE:
Andy Hung8ed196a2018-01-05 13:21:11 -0800735 track->mResampler.reset(nullptr);
736 track->sampleRate = mSampleRate;
737 invalidate();
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700738 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700739 default:
Glenn Kastenadad3d72014-02-21 14:51:43 -0800740 LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
Eric Laurent243f5f92011-02-28 16:52:51 -0800741 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700742 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700743
Mathias Agopian65ab4712010-07-14 17:59:35 -0700744 case RAMP_VOLUME:
745 case VOLUME:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800746 switch (param) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800747 case AUXLEVEL:
Andy Hung6be49402014-05-30 10:42:03 -0700748 if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
Andy Hung8ed196a2018-01-05 13:21:11 -0800749 target == RAMP_VOLUME ? mFrameCount : 0,
750 &track->auxLevel, &track->prevAuxLevel, &track->auxInc,
751 &track->mAuxLevel, &track->mPrevAuxLevel, &track->mAuxInc)) {
Andy Hung5866a3b2014-05-29 21:33:13 -0700752 ALOGV("setParameter(%s, AUXLEVEL: %04x)",
Andy Hung8ed196a2018-01-05 13:21:11 -0800753 target == VOLUME ? "VOLUME" : "RAMP_VOLUME", track->auxLevel);
754 invalidate();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700755 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800756 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700757 default:
Andy Hunge93b6b72014-07-17 21:30:53 -0700758 if ((unsigned)param >= VOLUME0 && (unsigned)param < VOLUME0 + MAX_NUM_VOLUMES) {
759 if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
Andy Hung8ed196a2018-01-05 13:21:11 -0800760 target == RAMP_VOLUME ? mFrameCount : 0,
761 &track->volume[param - VOLUME0],
762 &track->prevVolume[param - VOLUME0],
763 &track->volumeInc[param - VOLUME0],
764 &track->mVolume[param - VOLUME0],
765 &track->mPrevVolume[param - VOLUME0],
766 &track->mVolumeInc[param - VOLUME0])) {
Andy Hunge93b6b72014-07-17 21:30:53 -0700767 ALOGV("setParameter(%s, VOLUME%d: %04x)",
768 target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
Andy Hung8ed196a2018-01-05 13:21:11 -0800769 track->volume[param - VOLUME0]);
770 invalidate();
Andy Hunge93b6b72014-07-17 21:30:53 -0700771 }
772 } else {
773 LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
774 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700775 }
776 break;
Andy Hungc5656cc2015-03-26 19:04:33 -0700777 case TIMESTRETCH:
778 switch (param) {
779 case PLAYBACK_RATE: {
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700780 const AudioPlaybackRate *playbackRate =
781 reinterpret_cast<AudioPlaybackRate*>(value);
Ricardo Garcia6c7f0622015-04-30 18:39:16 -0700782 ALOGW_IF(!isAudioPlaybackRateValid(*playbackRate),
Andy Hung8ed196a2018-01-05 13:21:11 -0800783 "bad parameters speed %f, pitch %f",
784 playbackRate->mSpeed, playbackRate->mPitch);
785 if (track->setPlaybackRate(*playbackRate)) {
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700786 ALOGV("setParameter(TIMESTRETCH, PLAYBACK_RATE, STRETCH_MODE, FALLBACK_MODE "
787 "%f %f %d %d",
788 playbackRate->mSpeed,
789 playbackRate->mPitch,
790 playbackRate->mStretchMode,
791 playbackRate->mFallbackMode);
Andy Hung8ed196a2018-01-05 13:21:11 -0800792 // invalidate(); (should not require reconfigure)
Andy Hungc5656cc2015-03-26 19:04:33 -0700793 }
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700794 } break;
Andy Hungc5656cc2015-03-26 19:04:33 -0700795 default:
796 LOG_ALWAYS_FATAL("setParameter timestretch: bad param %d", param);
797 }
798 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700799
800 default:
Glenn Kastenadad3d72014-02-21 14:51:43 -0800801 LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700802 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700803}
804
Andy Hung8ed196a2018-01-05 13:21:11 -0800805bool AudioMixer::Track::setResampler(uint32_t trackSampleRate, uint32_t devSampleRate)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700806{
Andy Hung8ed196a2018-01-05 13:21:11 -0800807 if (trackSampleRate != devSampleRate || mResampler.get() != nullptr) {
Andy Hunge93b6b72014-07-17 21:30:53 -0700808 if (sampleRate != trackSampleRate) {
809 sampleRate = trackSampleRate;
Andy Hung8ed196a2018-01-05 13:21:11 -0800810 if (mResampler.get() == nullptr) {
Andy Hunge93b6b72014-07-17 21:30:53 -0700811 ALOGV("Creating resampler from track %d Hz to device %d Hz",
812 trackSampleRate, devSampleRate);
Glenn Kastenac602052012-10-01 14:04:31 -0700813 AudioResampler::src_quality quality;
814 // force lowest quality level resampler if use case isn't music or video
815 // FIXME this is flawed for dynamic sample rates, as we choose the resampler
816 // quality level based on the initial ratio, but that could change later.
817 // Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
Andy Hungdb4c0312015-05-06 08:46:52 -0700818 if (isMusicRate(trackSampleRate)) {
Glenn Kastenac602052012-10-01 14:04:31 -0700819 quality = AudioResampler::DEFAULT_QUALITY;
Andy Hungdb4c0312015-05-06 08:46:52 -0700820 } else {
821 quality = AudioResampler::DYN_LOW_QUALITY;
Glenn Kastenac602052012-10-01 14:04:31 -0700822 }
Andy Hung296b7412014-06-17 15:25:47 -0700823
Andy Hunge93b6b72014-07-17 21:30:53 -0700824 // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
825 // but if none exists, it is the channel count (1 for mono).
Andy Hung8ed196a2018-01-05 13:21:11 -0800826 const int resamplerChannelCount = mDownmixerBufferProvider.get() != nullptr
Andy Hunge93b6b72014-07-17 21:30:53 -0700827 ? mMixerChannelCount : channelCount;
Andy Hung9a592762014-07-21 21:56:01 -0700828 ALOGVV("Creating resampler:"
829 " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n",
830 mMixerInFormat, resamplerChannelCount, devSampleRate, quality);
Andy Hung8ed196a2018-01-05 13:21:11 -0800831 mResampler.reset(AudioResampler::create(
Andy Hung3348e362014-07-07 10:21:44 -0700832 mMixerInFormat,
Andy Hunge93b6b72014-07-17 21:30:53 -0700833 resamplerChannelCount,
Andy Hung8ed196a2018-01-05 13:21:11 -0800834 devSampleRate, quality));
Mathias Agopian65ab4712010-07-14 17:59:35 -0700835 }
836 return true;
837 }
838 }
839 return false;
840}
841
Andy Hung8ed196a2018-01-05 13:21:11 -0800842bool AudioMixer::Track::setPlaybackRate(const AudioPlaybackRate &playbackRate)
Andy Hungc5656cc2015-03-26 19:04:33 -0700843{
Andy Hung8ed196a2018-01-05 13:21:11 -0800844 if ((mTimestretchBufferProvider.get() == nullptr &&
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700845 fabs(playbackRate.mSpeed - mPlaybackRate.mSpeed) < AUDIO_TIMESTRETCH_SPEED_MIN_DELTA &&
846 fabs(playbackRate.mPitch - mPlaybackRate.mPitch) < AUDIO_TIMESTRETCH_PITCH_MIN_DELTA) ||
847 isAudioPlaybackRateEqual(playbackRate, mPlaybackRate)) {
Andy Hungc5656cc2015-03-26 19:04:33 -0700848 return false;
849 }
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700850 mPlaybackRate = playbackRate;
Andy Hung8ed196a2018-01-05 13:21:11 -0800851 if (mTimestretchBufferProvider.get() == nullptr) {
Andy Hungc5656cc2015-03-26 19:04:33 -0700852 // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
853 // but if none exists, it is the channel count (1 for mono).
Andy Hung8ed196a2018-01-05 13:21:11 -0800854 const int timestretchChannelCount = mDownmixerBufferProvider.get() != nullptr
Andy Hungc5656cc2015-03-26 19:04:33 -0700855 ? mMixerChannelCount : channelCount;
Andy Hung8ed196a2018-01-05 13:21:11 -0800856 mTimestretchBufferProvider.reset(new TimestretchBufferProvider(timestretchChannelCount,
857 mMixerInFormat, sampleRate, playbackRate));
Andy Hungc5656cc2015-03-26 19:04:33 -0700858 reconfigureBufferProviders();
859 } else {
Andy Hung8ed196a2018-01-05 13:21:11 -0800860 static_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider.get())
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700861 ->setPlaybackRate(playbackRate);
Andy Hungc5656cc2015-03-26 19:04:33 -0700862 }
863 return true;
864}
865
Andy Hung5e58b0a2014-06-23 19:07:29 -0700866/* Checks to see if the volume ramp has completed and clears the increment
867 * variables appropriately.
868 *
869 * FIXME: There is code to handle int/float ramp variable switchover should it not
870 * complete within a mixer buffer processing call, but it is preferred to avoid switchover
871 * due to precision issues. The switchover code is included for legacy code purposes
872 * and can be removed once the integer volume is removed.
873 *
874 * It is not sufficient to clear only the volumeInc integer variable because
875 * if one channel requires ramping, all channels are ramped.
876 *
877 * There is a bit of duplicated code here, but it keeps backward compatibility.
878 */
Andy Hung8ed196a2018-01-05 13:21:11 -0800879inline void AudioMixer::Track::adjustVolumeRamp(bool aux, bool useFloat)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700880{
Andy Hung5e58b0a2014-06-23 19:07:29 -0700881 if (useFloat) {
Andy Hunge93b6b72014-07-17 21:30:53 -0700882 for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
Eric Laurent43412fc2015-05-08 16:14:36 -0700883 if ((mVolumeInc[i] > 0 && mPrevVolume[i] + mVolumeInc[i] >= mVolume[i]) ||
884 (mVolumeInc[i] < 0 && mPrevVolume[i] + mVolumeInc[i] <= mVolume[i])) {
Andy Hung5e58b0a2014-06-23 19:07:29 -0700885 volumeInc[i] = 0;
886 prevVolume[i] = volume[i] << 16;
887 mVolumeInc[i] = 0.;
888 mPrevVolume[i] = mVolume[i];
Andy Hung5e58b0a2014-06-23 19:07:29 -0700889 } else {
890 //ALOGV("ramp: %f %f %f", mVolume[i], mPrevVolume[i], mVolumeInc[i]);
891 prevVolume[i] = u4_28_from_float(mPrevVolume[i]);
892 }
893 }
894 } else {
Andy Hunge93b6b72014-07-17 21:30:53 -0700895 for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
Andy Hung5e58b0a2014-06-23 19:07:29 -0700896 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
897 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
898 volumeInc[i] = 0;
899 prevVolume[i] = volume[i] << 16;
900 mVolumeInc[i] = 0.;
901 mPrevVolume[i] = mVolume[i];
902 } else {
903 //ALOGV("ramp: %d %d %d", volume[i] << 16, prevVolume[i], volumeInc[i]);
904 mPrevVolume[i] = float_from_u4_28(prevVolume[i]);
905 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700906 }
907 }
Andy Hung116a4982017-11-30 10:15:08 -0800908
Mathias Agopian65ab4712010-07-14 17:59:35 -0700909 if (aux) {
Andy Hung116a4982017-11-30 10:15:08 -0800910#ifdef FLOAT_AUX
911 if (useFloat) {
912 if ((mAuxInc > 0.f && mPrevAuxLevel + mAuxInc >= mAuxLevel) ||
913 (mAuxInc < 0.f && mPrevAuxLevel + mAuxInc <= mAuxLevel)) {
914 auxInc = 0;
915 prevAuxLevel = auxLevel << 16;
916 mAuxInc = 0.f;
917 mPrevAuxLevel = mAuxLevel;
918 }
919 } else
920#endif
921 if ((auxInc > 0 && ((prevAuxLevel + auxInc) >> 16) >= auxLevel) ||
922 (auxInc < 0 && ((prevAuxLevel + auxInc) >> 16) <= auxLevel)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700923 auxInc = 0;
Andy Hung5e58b0a2014-06-23 19:07:29 -0700924 prevAuxLevel = auxLevel << 16;
Andy Hung116a4982017-11-30 10:15:08 -0800925 mAuxInc = 0.f;
Andy Hung5e58b0a2014-06-23 19:07:29 -0700926 mPrevAuxLevel = mAuxLevel;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700927 }
928 }
929}
930
Glenn Kastenc59c0042012-02-02 14:06:11 -0800931size_t AudioMixer::getUnreleasedFrames(int name) const
Eric Laurent071ccd52011-12-22 16:08:41 -0800932{
Andy Hung8ed196a2018-01-05 13:21:11 -0800933 const auto it = mTracks.find(name);
934 if (it != mTracks.end()) {
935 return it->second->getUnreleasedFrames();
Eric Laurent071ccd52011-12-22 16:08:41 -0800936 }
937 return 0;
938}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700939
Glenn Kasten01c4ebf2012-02-22 10:47:35 -0800940void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700941{
Andy Hung1bc088a2018-02-09 15:57:31 -0800942 LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
Andy Hung8ed196a2018-01-05 13:21:11 -0800943 const std::shared_ptr<Track> &track = mTracks[name];
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700944
Andy Hung8ed196a2018-01-05 13:21:11 -0800945 if (track->mInputBufferProvider == bufferProvider) {
Andy Hung1d26ddf2014-05-29 15:53:09 -0700946 return; // don't reset any buffer providers if identical.
947 }
Andy Hung3a34df92018-08-21 12:32:30 -0700948 // reset order from downstream to upstream buffer providers.
949 if (track->mTimestretchBufferProvider.get() != nullptr) {
950 track->mTimestretchBufferProvider->reset();
Andy Hung8ed196a2018-01-05 13:21:11 -0800951 } else if (track->mPostDownmixReformatBufferProvider.get() != nullptr) {
952 track->mPostDownmixReformatBufferProvider->reset();
Andy Hung3a34df92018-08-21 12:32:30 -0700953 } else if (track->mDownmixerBufferProvider != nullptr) {
954 track->mDownmixerBufferProvider->reset();
955 } else if (track->mReformatBufferProvider.get() != nullptr) {
956 track->mReformatBufferProvider->reset();
jiabindce8f8c2018-12-10 17:49:31 -0800957 } else if (track->mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
958 track->mAdjustChannelsNonDestructiveBufferProvider->reset();
959 } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
960 track->mAdjustChannelsBufferProvider->reset();
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700961 }
Andy Hungef7c7fb2014-05-12 16:51:41 -0700962
Andy Hung8ed196a2018-01-05 13:21:11 -0800963 track->mInputBufferProvider = bufferProvider;
964 track->reconfigureBufferProviders();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700965}
966
Andy Hung8ed196a2018-01-05 13:21:11 -0800967void AudioMixer::process__validate()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700968{
Andy Hung395db4b2014-08-25 17:15:29 -0700969 // TODO: fix all16BitsStereNoResample logic to
970 // either properly handle muted tracks (it should ignore them)
971 // or remove altogether as an obsolete optimization.
Glenn Kasten4c340c62012-01-27 12:33:54 -0800972 bool all16BitsStereoNoResample = true;
973 bool resampling = false;
974 bool volumeRamp = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700975
Andy Hung8ed196a2018-01-05 13:21:11 -0800976 mEnabled.clear();
977 mGroups.clear();
978 for (const auto &pair : mTracks) {
979 const int name = pair.first;
980 const std::shared_ptr<Track> &t = pair.second;
981 if (!t->enabled) continue;
982
983 mEnabled.emplace_back(name); // we add to mEnabled in order of name.
984 mGroups[t->mainBuffer].emplace_back(name); // mGroups also in order of name.
985
Mathias Agopian65ab4712010-07-14 17:59:35 -0700986 uint32_t n = 0;
Glenn Kastend6fadf02013-10-30 14:37:29 -0700987 // FIXME can overflow (mask is only 3 bits)
Andy Hung8ed196a2018-01-05 13:21:11 -0800988 n |= NEEDS_CHANNEL_1 + t->channelCount - 1;
989 if (t->doesResample()) {
Glenn Kastend6fadf02013-10-30 14:37:29 -0700990 n |= NEEDS_RESAMPLE;
991 }
Andy Hung8ed196a2018-01-05 13:21:11 -0800992 if (t->auxLevel != 0 && t->auxBuffer != NULL) {
Glenn Kastend6fadf02013-10-30 14:37:29 -0700993 n |= NEEDS_AUX;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700994 }
995
Andy Hung8ed196a2018-01-05 13:21:11 -0800996 if (t->volumeInc[0]|t->volumeInc[1]) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800997 volumeRamp = true;
Andy Hung8ed196a2018-01-05 13:21:11 -0800998 } else if (!t->doesResample() && t->volumeRL == 0) {
Glenn Kastend6fadf02013-10-30 14:37:29 -0700999 n |= NEEDS_MUTE;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001000 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001001 t->needs = n;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001002
Glenn Kastend6fadf02013-10-30 14:37:29 -07001003 if (n & NEEDS_MUTE) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001004 t->hook = &Track::track__nop;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001005 } else {
Glenn Kastend6fadf02013-10-30 14:37:29 -07001006 if (n & NEEDS_AUX) {
Glenn Kasten4c340c62012-01-27 12:33:54 -08001007 all16BitsStereoNoResample = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001008 }
Glenn Kastend6fadf02013-10-30 14:37:29 -07001009 if (n & NEEDS_RESAMPLE) {
Glenn Kasten4c340c62012-01-27 12:33:54 -08001010 all16BitsStereoNoResample = false;
1011 resampling = true;
Andy Hung8ed196a2018-01-05 13:21:11 -08001012 t->hook = Track::getTrackHook(TRACKTYPE_RESAMPLE, t->mMixerChannelCount,
1013 t->mMixerInFormat, t->mMixerFormat);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07001014 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
Chih-Hung Hsieh09f9c022018-07-27 10:22:35 -07001015 "Track %d needs downmix + resample", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001016 } else {
1017 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
Andy Hung8ed196a2018-01-05 13:21:11 -08001018 t->hook = Track::getTrackHook(
1019 (t->mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO // TODO: MONO_HACK
1020 && t->channelMask == AUDIO_CHANNEL_OUT_MONO)
Andy Hunge93b6b72014-07-17 21:30:53 -07001021 ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE,
Andy Hung8ed196a2018-01-05 13:21:11 -08001022 t->mMixerChannelCount,
1023 t->mMixerInFormat, t->mMixerFormat);
Glenn Kasten4c340c62012-01-27 12:33:54 -08001024 all16BitsStereoNoResample = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001025 }
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07001026 if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
Andy Hung8ed196a2018-01-05 13:21:11 -08001027 t->hook = Track::getTrackHook(TRACKTYPE_NORESAMPLE, t->mMixerChannelCount,
1028 t->mMixerInFormat, t->mMixerFormat);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -07001029 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
Chih-Hung Hsieh09f9c022018-07-27 10:22:35 -07001030 "Track %d needs downmix", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001031 }
1032 }
1033 }
1034 }
1035
1036 // select the processing hooks
Andy Hung8ed196a2018-01-05 13:21:11 -08001037 mHook = &AudioMixer::process__nop;
1038 if (mEnabled.size() > 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001039 if (resampling) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001040 if (mOutputTemp.get() == nullptr) {
1041 mOutputTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001042 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001043 if (mResampleTemp.get() == nullptr) {
1044 mResampleTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001045 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001046 mHook = &AudioMixer::process__genericResampling;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001047 } else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001048 // we keep temp arrays around.
1049 mHook = &AudioMixer::process__genericNoResampling;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001050 if (all16BitsStereoNoResample && !volumeRamp) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001051 if (mEnabled.size() == 1) {
1052 const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
1053 if ((t->needs & NEEDS_MUTE) == 0) {
Andy Hung395db4b2014-08-25 17:15:29 -07001054 // The check prevents a muted track from acquiring a process hook.
1055 //
1056 // This is dangerous if the track is MONO as that requires
1057 // special case handling due to implicit channel duplication.
1058 // Stereo or Multichannel should actually be fine here.
Andy Hung8ed196a2018-01-05 13:21:11 -08001059 mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
1060 t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);
Andy Hung395db4b2014-08-25 17:15:29 -07001061 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001062 }
1063 }
1064 }
1065 }
1066
Andy Hung8ed196a2018-01-05 13:21:11 -08001067 ALOGV("mixer configuration change: %zu "
Mathias Agopian65ab4712010-07-14 17:59:35 -07001068 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
Andy Hung8ed196a2018-01-05 13:21:11 -08001069 mEnabled.size(), all16BitsStereoNoResample, resampling, volumeRamp);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001070
Andy Hung8ed196a2018-01-05 13:21:11 -08001071 process();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001072
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001073 // Now that the volume ramp has been done, set optimal state and
1074 // track hooks for subsequent mixer process
Andy Hung8ed196a2018-01-05 13:21:11 -08001075 if (mEnabled.size() > 0) {
Glenn Kasten4c340c62012-01-27 12:33:54 -08001076 bool allMuted = true;
Andy Hung8ed196a2018-01-05 13:21:11 -08001077
1078 for (const int name : mEnabled) {
1079 const std::shared_ptr<Track> &t = mTracks[name];
1080 if (!t->doesResample() && t->volumeRL == 0) {
1081 t->needs |= NEEDS_MUTE;
1082 t->hook = &Track::track__nop;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001083 } else {
Glenn Kasten4c340c62012-01-27 12:33:54 -08001084 allMuted = false;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001085 }
1086 }
1087 if (allMuted) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001088 mHook = &AudioMixer::process__nop;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001089 } else if (all16BitsStereoNoResample) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001090 if (mEnabled.size() == 1) {
1091 //const int i = 31 - __builtin_clz(enabledTracks);
1092 const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
Andy Hung395db4b2014-08-25 17:15:29 -07001093 // Muted single tracks handled by allMuted above.
Andy Hung8ed196a2018-01-05 13:21:11 -08001094 mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
1095 t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001096 }
1097 }
1098 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001099}
1100
Andy Hung8ed196a2018-01-05 13:21:11 -08001101void AudioMixer::Track::track__genericResample(
1102 int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001103{
Andy Hung296b7412014-06-17 15:25:47 -07001104 ALOGVV("track__genericResample\n");
Andy Hung8ed196a2018-01-05 13:21:11 -08001105 mResampler->setSampleRate(sampleRate);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001106
1107 // ramp gain - resample to temp buffer and scale/mix in 2nd step
1108 if (aux != NULL) {
1109 // always resample with unity gain when sending to auxiliary buffer to be able
1110 // to apply send level after resampling
Andy Hung8ed196a2018-01-05 13:21:11 -08001111 mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
1112 memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(int32_t));
1113 mResampler->resample(temp, outFrameCount, bufferProvider);
1114 if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
1115 volumeRampStereo(out, outFrameCount, temp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001116 } else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001117 volumeStereo(out, outFrameCount, temp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001118 }
1119 } else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001120 if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
1121 mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001122 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
Andy Hung8ed196a2018-01-05 13:21:11 -08001123 mResampler->resample(temp, outFrameCount, bufferProvider);
1124 volumeRampStereo(out, outFrameCount, temp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001125 }
1126
1127 // constant gain
1128 else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001129 mResampler->setVolume(mVolume[0], mVolume[1]);
1130 mResampler->resample(out, outFrameCount, bufferProvider);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001131 }
1132 }
1133}
1134
Andy Hung8ed196a2018-01-05 13:21:11 -08001135void AudioMixer::Track::track__nop(int32_t* out __unused,
Andy Hungee931ff2014-01-28 13:44:14 -08001136 size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001137{
1138}
1139
Andy Hung8ed196a2018-01-05 13:21:11 -08001140void AudioMixer::Track::volumeRampStereo(
1141 int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001142{
Andy Hung8ed196a2018-01-05 13:21:11 -08001143 int32_t vl = prevVolume[0];
1144 int32_t vr = prevVolume[1];
1145 const int32_t vlInc = volumeInc[0];
1146 const int32_t vrInc = volumeInc[1];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001147
Steve Blockb8a80522011-12-20 16:23:08 +00001148 //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Andy Hung8ed196a2018-01-05 13:21:11 -08001149 // t, vlInc/65536.0f, vl/65536.0f, volume[0],
Mathias Agopian65ab4712010-07-14 17:59:35 -07001150 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1151
1152 // ramp volume
Glenn Kastenf6b16782011-12-15 09:51:17 -08001153 if (CC_UNLIKELY(aux != NULL)) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001154 int32_t va = prevAuxLevel;
1155 const int32_t vaInc = auxInc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001156 int32_t l;
1157 int32_t r;
1158
1159 do {
1160 l = (*temp++ >> 12);
1161 r = (*temp++ >> 12);
1162 *out++ += (vl >> 16) * l;
1163 *out++ += (vr >> 16) * r;
1164 *aux++ += (va >> 17) * (l + r);
1165 vl += vlInc;
1166 vr += vrInc;
1167 va += vaInc;
1168 } while (--frameCount);
Andy Hung8ed196a2018-01-05 13:21:11 -08001169 prevAuxLevel = va;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001170 } else {
1171 do {
1172 *out++ += (vl >> 16) * (*temp++ >> 12);
1173 *out++ += (vr >> 16) * (*temp++ >> 12);
1174 vl += vlInc;
1175 vr += vrInc;
1176 } while (--frameCount);
1177 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001178 prevVolume[0] = vl;
1179 prevVolume[1] = vr;
1180 adjustVolumeRamp(aux != NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001181}
1182
Andy Hung8ed196a2018-01-05 13:21:11 -08001183void AudioMixer::Track::volumeStereo(
1184 int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001185{
Andy Hung8ed196a2018-01-05 13:21:11 -08001186 const int16_t vl = volume[0];
1187 const int16_t vr = volume[1];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001188
Glenn Kastenf6b16782011-12-15 09:51:17 -08001189 if (CC_UNLIKELY(aux != NULL)) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001190 const int16_t va = auxLevel;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001191 do {
1192 int16_t l = (int16_t)(*temp++ >> 12);
1193 int16_t r = (int16_t)(*temp++ >> 12);
1194 out[0] = mulAdd(l, vl, out[0]);
1195 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
1196 out[1] = mulAdd(r, vr, out[1]);
1197 out += 2;
1198 aux[0] = mulAdd(a, va, aux[0]);
1199 aux++;
1200 } while (--frameCount);
1201 } else {
1202 do {
1203 int16_t l = (int16_t)(*temp++ >> 12);
1204 int16_t r = (int16_t)(*temp++ >> 12);
1205 out[0] = mulAdd(l, vl, out[0]);
1206 out[1] = mulAdd(r, vr, out[1]);
1207 out += 2;
1208 } while (--frameCount);
1209 }
1210}
1211
Andy Hung8ed196a2018-01-05 13:21:11 -08001212void AudioMixer::Track::track__16BitsStereo(
1213 int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001214{
Andy Hung296b7412014-06-17 15:25:47 -07001215 ALOGVV("track__16BitsStereo\n");
Andy Hung8ed196a2018-01-05 13:21:11 -08001216 const int16_t *in = static_cast<const int16_t *>(mIn);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001217
Glenn Kastenf6b16782011-12-15 09:51:17 -08001218 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001219 int32_t l;
1220 int32_t r;
1221 // ramp gain
Andy Hung8ed196a2018-01-05 13:21:11 -08001222 if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
1223 int32_t vl = prevVolume[0];
1224 int32_t vr = prevVolume[1];
1225 int32_t va = prevAuxLevel;
1226 const int32_t vlInc = volumeInc[0];
1227 const int32_t vrInc = volumeInc[1];
1228 const int32_t vaInc = auxInc;
Steve Blockb8a80522011-12-20 16:23:08 +00001229 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Andy Hung8ed196a2018-01-05 13:21:11 -08001230 // t, vlInc/65536.0f, vl/65536.0f, volume[0],
Mathias Agopian65ab4712010-07-14 17:59:35 -07001231 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1232
1233 do {
1234 l = (int32_t)*in++;
1235 r = (int32_t)*in++;
1236 *out++ += (vl >> 16) * l;
1237 *out++ += (vr >> 16) * r;
1238 *aux++ += (va >> 17) * (l + r);
1239 vl += vlInc;
1240 vr += vrInc;
1241 va += vaInc;
1242 } while (--frameCount);
1243
Andy Hung8ed196a2018-01-05 13:21:11 -08001244 prevVolume[0] = vl;
1245 prevVolume[1] = vr;
1246 prevAuxLevel = va;
1247 adjustVolumeRamp(true);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001248 }
1249
1250 // constant gain
1251 else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001252 const uint32_t vrl = volumeRL;
1253 const int16_t va = (int16_t)auxLevel;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001254 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001255 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001256 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
1257 in += 2;
1258 out[0] = mulAddRL(1, rl, vrl, out[0]);
1259 out[1] = mulAddRL(0, rl, vrl, out[1]);
1260 out += 2;
1261 aux[0] = mulAdd(a, va, aux[0]);
1262 aux++;
1263 } while (--frameCount);
1264 }
1265 } else {
1266 // ramp gain
Andy Hung8ed196a2018-01-05 13:21:11 -08001267 if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
1268 int32_t vl = prevVolume[0];
1269 int32_t vr = prevVolume[1];
1270 const int32_t vlInc = volumeInc[0];
1271 const int32_t vrInc = volumeInc[1];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001272
Steve Blockb8a80522011-12-20 16:23:08 +00001273 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Andy Hung8ed196a2018-01-05 13:21:11 -08001274 // t, vlInc/65536.0f, vl/65536.0f, volume[0],
Mathias Agopian65ab4712010-07-14 17:59:35 -07001275 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1276
1277 do {
1278 *out++ += (vl >> 16) * (int32_t) *in++;
1279 *out++ += (vr >> 16) * (int32_t) *in++;
1280 vl += vlInc;
1281 vr += vrInc;
1282 } while (--frameCount);
1283
Andy Hung8ed196a2018-01-05 13:21:11 -08001284 prevVolume[0] = vl;
1285 prevVolume[1] = vr;
1286 adjustVolumeRamp(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001287 }
1288
1289 // constant gain
1290 else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001291 const uint32_t vrl = volumeRL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001292 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001293 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001294 in += 2;
1295 out[0] = mulAddRL(1, rl, vrl, out[0]);
1296 out[1] = mulAddRL(0, rl, vrl, out[1]);
1297 out += 2;
1298 } while (--frameCount);
1299 }
1300 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001301 mIn = in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001302}
1303
Andy Hung8ed196a2018-01-05 13:21:11 -08001304void AudioMixer::Track::track__16BitsMono(
1305 int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001306{
Andy Hung296b7412014-06-17 15:25:47 -07001307 ALOGVV("track__16BitsMono\n");
Andy Hung8ed196a2018-01-05 13:21:11 -08001308 const int16_t *in = static_cast<int16_t const *>(mIn);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001309
Glenn Kastenf6b16782011-12-15 09:51:17 -08001310 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001311 // ramp gain
Andy Hung8ed196a2018-01-05 13:21:11 -08001312 if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
1313 int32_t vl = prevVolume[0];
1314 int32_t vr = prevVolume[1];
1315 int32_t va = prevAuxLevel;
1316 const int32_t vlInc = volumeInc[0];
1317 const int32_t vrInc = volumeInc[1];
1318 const int32_t vaInc = auxInc;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001319
Steve Blockb8a80522011-12-20 16:23:08 +00001320 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Andy Hung8ed196a2018-01-05 13:21:11 -08001321 // t, vlInc/65536.0f, vl/65536.0f, volume[0],
Mathias Agopian65ab4712010-07-14 17:59:35 -07001322 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1323
1324 do {
1325 int32_t l = *in++;
1326 *out++ += (vl >> 16) * l;
1327 *out++ += (vr >> 16) * l;
1328 *aux++ += (va >> 16) * l;
1329 vl += vlInc;
1330 vr += vrInc;
1331 va += vaInc;
1332 } while (--frameCount);
1333
Andy Hung8ed196a2018-01-05 13:21:11 -08001334 prevVolume[0] = vl;
1335 prevVolume[1] = vr;
1336 prevAuxLevel = va;
1337 adjustVolumeRamp(true);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001338 }
1339 // constant gain
1340 else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001341 const int16_t vl = volume[0];
1342 const int16_t vr = volume[1];
1343 const int16_t va = (int16_t)auxLevel;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001344 do {
1345 int16_t l = *in++;
1346 out[0] = mulAdd(l, vl, out[0]);
1347 out[1] = mulAdd(l, vr, out[1]);
1348 out += 2;
1349 aux[0] = mulAdd(l, va, aux[0]);
1350 aux++;
1351 } while (--frameCount);
1352 }
1353 } else {
1354 // ramp gain
Andy Hung8ed196a2018-01-05 13:21:11 -08001355 if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
1356 int32_t vl = prevVolume[0];
1357 int32_t vr = prevVolume[1];
1358 const int32_t vlInc = volumeInc[0];
1359 const int32_t vrInc = volumeInc[1];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001360
Steve Blockb8a80522011-12-20 16:23:08 +00001361 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Andy Hung8ed196a2018-01-05 13:21:11 -08001362 // t, vlInc/65536.0f, vl/65536.0f, volume[0],
Mathias Agopian65ab4712010-07-14 17:59:35 -07001363 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1364
1365 do {
1366 int32_t l = *in++;
1367 *out++ += (vl >> 16) * l;
1368 *out++ += (vr >> 16) * l;
1369 vl += vlInc;
1370 vr += vrInc;
1371 } while (--frameCount);
1372
Andy Hung8ed196a2018-01-05 13:21:11 -08001373 prevVolume[0] = vl;
1374 prevVolume[1] = vr;
1375 adjustVolumeRamp(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001376 }
1377 // constant gain
1378 else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001379 const int16_t vl = volume[0];
1380 const int16_t vr = volume[1];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001381 do {
1382 int16_t l = *in++;
1383 out[0] = mulAdd(l, vl, out[0]);
1384 out[1] = mulAdd(l, vr, out[1]);
1385 out += 2;
1386 } while (--frameCount);
1387 }
1388 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001389 mIn = in;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001390}
1391
Mathias Agopian65ab4712010-07-14 17:59:35 -07001392// no-op case
Andy Hung8ed196a2018-01-05 13:21:11 -08001393void AudioMixer::process__nop()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001394{
Andy Hung296b7412014-06-17 15:25:47 -07001395 ALOGVV("process__nop\n");
Andy Hung8ed196a2018-01-05 13:21:11 -08001396
1397 for (const auto &pair : mGroups) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001398 // process by group of tracks with same output buffer to
1399 // avoid multiple memset() on same buffer
Andy Hung8ed196a2018-01-05 13:21:11 -08001400 const auto &group = pair.second;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001401
Andy Hung8ed196a2018-01-05 13:21:11 -08001402 const std::shared_ptr<Track> &t = mTracks[group[0]];
1403 memset(t->mainBuffer, 0,
jiabin245cdd92018-12-07 17:55:15 -08001404 mFrameCount * audio_bytes_per_frame(
1405 t->mMixerChannelCount + t->mMixerHapticChannelCount, t->mMixerFormat));
Mathias Agopian65ab4712010-07-14 17:59:35 -07001406
Andy Hung8ed196a2018-01-05 13:21:11 -08001407 // now consume data
1408 for (const int name : group) {
1409 const std::shared_ptr<Track> &t = mTracks[name];
1410 size_t outFrames = mFrameCount;
1411 while (outFrames) {
1412 t->buffer.frameCount = outFrames;
1413 t->bufferProvider->getNextBuffer(&t->buffer);
1414 if (t->buffer.raw == NULL) break;
1415 outFrames -= t->buffer.frameCount;
1416 t->bufferProvider->releaseBuffer(&t->buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001417 }
1418 }
1419 }
1420}
1421
1422// generic code without resampling
Andy Hung8ed196a2018-01-05 13:21:11 -08001423void AudioMixer::process__genericNoResampling()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001424{
Andy Hung296b7412014-06-17 15:25:47 -07001425 ALOGVV("process__genericNoResampling\n");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001426 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
1427
Andy Hung8ed196a2018-01-05 13:21:11 -08001428 for (const auto &pair : mGroups) {
1429 // process by group of tracks with same output main buffer to
1430 // avoid multiple memset() on same buffer
1431 const auto &group = pair.second;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001432
Andy Hung8ed196a2018-01-05 13:21:11 -08001433 // acquire buffer
1434 for (const int name : group) {
1435 const std::shared_ptr<Track> &t = mTracks[name];
1436 t->buffer.frameCount = mFrameCount;
1437 t->bufferProvider->getNextBuffer(&t->buffer);
1438 t->frameCount = t->buffer.frameCount;
1439 t->mIn = t->buffer.raw;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001440 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001441
1442 int32_t *out = (int *)pair.first;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001443 size_t numFrames = 0;
1444 do {
Andy Hung8ed196a2018-01-05 13:21:11 -08001445 const size_t frameCount = std::min((size_t)BLOCKSIZE, mFrameCount - numFrames);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001446 memset(outTemp, 0, sizeof(outTemp));
Andy Hung8ed196a2018-01-05 13:21:11 -08001447 for (const int name : group) {
1448 const std::shared_ptr<Track> &t = mTracks[name];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001449 int32_t *aux = NULL;
Andy Hung8ed196a2018-01-05 13:21:11 -08001450 if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
1451 aux = t->auxBuffer + numFrames;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001452 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001453 for (int outFrames = frameCount; outFrames > 0; ) {
1454 // t->in == nullptr can happen if the track was flushed just after having
Gaurav Kumar7e79cd22014-01-06 10:57:18 +05301455 // been enabled for mixing.
Andy Hung8ed196a2018-01-05 13:21:11 -08001456 if (t->mIn == nullptr) {
Gaurav Kumar7e79cd22014-01-06 10:57:18 +05301457 break;
1458 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001459 size_t inFrames = (t->frameCount > outFrames)?outFrames:t->frameCount;
Glenn Kasten34fca342013-08-13 09:48:14 -07001460 if (inFrames > 0) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001461 (t.get()->*t->hook)(
1462 outTemp + (frameCount - outFrames) * t->mMixerChannelCount,
1463 inFrames, mResampleTemp.get() /* naked ptr */, aux);
1464 t->frameCount -= inFrames;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001465 outFrames -= inFrames;
Glenn Kastenf6b16782011-12-15 09:51:17 -08001466 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001467 aux += inFrames;
1468 }
1469 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001470 if (t->frameCount == 0 && outFrames) {
1471 t->bufferProvider->releaseBuffer(&t->buffer);
1472 t->buffer.frameCount = (mFrameCount - numFrames) -
Yahan Zhouc1c11b42018-01-16 12:44:04 -08001473 (frameCount - outFrames);
Andy Hung8ed196a2018-01-05 13:21:11 -08001474 t->bufferProvider->getNextBuffer(&t->buffer);
1475 t->mIn = t->buffer.raw;
1476 if (t->mIn == nullptr) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001477 break;
1478 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001479 t->frameCount = t->buffer.frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001480 }
1481 }
1482 }
Andy Hung296b7412014-06-17 15:25:47 -07001483
Andy Hung8ed196a2018-01-05 13:21:11 -08001484 const std::shared_ptr<Track> &t1 = mTracks[group[0]];
1485 convertMixerFormat(out, t1->mMixerFormat, outTemp, t1->mMixerInFormat,
1486 frameCount * t1->mMixerChannelCount);
Andy Hung296b7412014-06-17 15:25:47 -07001487 // TODO: fix ugly casting due to choice of out pointer type
1488 out = reinterpret_cast<int32_t*>((uint8_t*)out
Andy Hung8ed196a2018-01-05 13:21:11 -08001489 + frameCount * t1->mMixerChannelCount
1490 * audio_bytes_per_sample(t1->mMixerFormat));
Yahan Zhouc1c11b42018-01-16 12:44:04 -08001491 numFrames += frameCount;
Andy Hung8ed196a2018-01-05 13:21:11 -08001492 } while (numFrames < mFrameCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001493
Andy Hung8ed196a2018-01-05 13:21:11 -08001494 // release each track's buffer
1495 for (const int name : group) {
1496 const std::shared_ptr<Track> &t = mTracks[name];
1497 t->bufferProvider->releaseBuffer(&t->buffer);
1498 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001499 }
1500}
1501
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001502// generic code with resampling
Andy Hung8ed196a2018-01-05 13:21:11 -08001503void AudioMixer::process__genericResampling()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001504{
Andy Hung296b7412014-06-17 15:25:47 -07001505 ALOGVV("process__genericResampling\n");
Andy Hung8ed196a2018-01-05 13:21:11 -08001506 int32_t * const outTemp = mOutputTemp.get(); // naked ptr
1507 size_t numFrames = mFrameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001508
Andy Hung8ed196a2018-01-05 13:21:11 -08001509 for (const auto &pair : mGroups) {
1510 const auto &group = pair.second;
1511 const std::shared_ptr<Track> &t1 = mTracks[group[0]];
1512
1513 // clear temp buffer
1514 memset(outTemp, 0, sizeof(*outTemp) * t1->mMixerChannelCount * mFrameCount);
1515 for (const int name : group) {
1516 const std::shared_ptr<Track> &t = mTracks[name];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001517 int32_t *aux = NULL;
Andy Hung8ed196a2018-01-05 13:21:11 -08001518 if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
1519 aux = t->auxBuffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001520 }
1521
1522 // this is a little goofy, on the resampling case we don't
1523 // acquire/release the buffers because it's done by
1524 // the resampler.
Andy Hung8ed196a2018-01-05 13:21:11 -08001525 if (t->needs & NEEDS_RESAMPLE) {
1526 (t.get()->*t->hook)(outTemp, numFrames, mResampleTemp.get() /* naked ptr */, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001527 } else {
1528
1529 size_t outFrames = 0;
1530
1531 while (outFrames < numFrames) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001532 t->buffer.frameCount = numFrames - outFrames;
1533 t->bufferProvider->getNextBuffer(&t->buffer);
1534 t->mIn = t->buffer.raw;
1535 // t->mIn == nullptr can happen if the track was flushed just after having
Mathias Agopian65ab4712010-07-14 17:59:35 -07001536 // been enabled for mixing.
Andy Hung8ed196a2018-01-05 13:21:11 -08001537 if (t->mIn == nullptr) break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001538
Andy Hung8ed196a2018-01-05 13:21:11 -08001539 (t.get()->*t->hook)(
1540 outTemp + outFrames * t->mMixerChannelCount, t->buffer.frameCount,
Andy Hunga6018892018-02-21 14:32:16 -08001541 mResampleTemp.get() /* naked ptr */,
1542 aux != nullptr ? aux + outFrames : nullptr);
Andy Hung8ed196a2018-01-05 13:21:11 -08001543 outFrames += t->buffer.frameCount;
Andy Hunga6018892018-02-21 14:32:16 -08001544
Andy Hung8ed196a2018-01-05 13:21:11 -08001545 t->bufferProvider->releaseBuffer(&t->buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001546 }
1547 }
1548 }
Andy Hung8ed196a2018-01-05 13:21:11 -08001549 convertMixerFormat(t1->mainBuffer, t1->mMixerFormat,
1550 outTemp, t1->mMixerInFormat, numFrames * t1->mMixerChannelCount);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001551 }
1552}
1553
1554// one track, 16 bits stereo without resampling is the most common case
Andy Hung8ed196a2018-01-05 13:21:11 -08001555void AudioMixer::process__oneTrack16BitsStereoNoResampling()
Mathias Agopian65ab4712010-07-14 17:59:35 -07001556{
Andy Hung8ed196a2018-01-05 13:21:11 -08001557 ALOGVV("process__oneTrack16BitsStereoNoResampling\n");
1558 LOG_ALWAYS_FATAL_IF(mEnabled.size() != 0,
1559 "%zu != 1 tracks enabled", mEnabled.size());
1560 const int name = mEnabled[0];
1561 const std::shared_ptr<Track> &t = mTracks[name];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001562
Andy Hung8ed196a2018-01-05 13:21:11 -08001563 AudioBufferProvider::Buffer& b(t->buffer);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001564
Andy Hung8ed196a2018-01-05 13:21:11 -08001565 int32_t* out = t->mainBuffer;
Andy Hungf8a106a2014-05-29 18:52:38 -07001566 float *fout = reinterpret_cast<float*>(out);
Andy Hung8ed196a2018-01-05 13:21:11 -08001567 size_t numFrames = mFrameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001568
Andy Hung8ed196a2018-01-05 13:21:11 -08001569 const int16_t vl = t->volume[0];
1570 const int16_t vr = t->volume[1];
1571 const uint32_t vrl = t->volumeRL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001572 while (numFrames) {
1573 b.frameCount = numFrames;
Andy Hung8ed196a2018-01-05 13:21:11 -08001574 t->bufferProvider->getNextBuffer(&b);
Glenn Kasten54c3b662012-01-06 07:46:30 -08001575 const int16_t *in = b.i16;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001576
1577 // in == NULL can happen if the track was flushed just after having
1578 // been enabled for mixing.
Andy Hungf8a106a2014-05-29 18:52:38 -07001579 if (in == NULL || (((uintptr_t)in) & 3)) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001580 if ( AUDIO_FORMAT_PCM_FLOAT == t->mMixerFormat ) {
Jinguang Dong7c5ec032016-11-14 19:57:14 +08001581 memset((char*)fout, 0, numFrames
Andy Hung8ed196a2018-01-05 13:21:11 -08001582 * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
Jinguang Dong7c5ec032016-11-14 19:57:14 +08001583 } else {
1584 memset((char*)out, 0, numFrames
Andy Hung8ed196a2018-01-05 13:21:11 -08001585 * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
Jinguang Dong7c5ec032016-11-14 19:57:14 +08001586 }
Andy Hung395db4b2014-08-25 17:15:29 -07001587 ALOGE_IF((((uintptr_t)in) & 3),
Andy Hung8ed196a2018-01-05 13:21:11 -08001588 "process__oneTrack16BitsStereoNoResampling: misaligned buffer"
Andy Hung395db4b2014-08-25 17:15:29 -07001589 " %p track %d, channels %d, needs %08x, volume %08x vfl %f vfr %f",
Andy Hung8ed196a2018-01-05 13:21:11 -08001590 in, name, t->channelCount, t->needs, vrl, t->mVolume[0], t->mVolume[1]);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001591 return;
1592 }
1593 size_t outFrames = b.frameCount;
1594
Andy Hung8ed196a2018-01-05 13:21:11 -08001595 switch (t->mMixerFormat) {
Andy Hungf8a106a2014-05-29 18:52:38 -07001596 case AUDIO_FORMAT_PCM_FLOAT:
Mathias Agopian65ab4712010-07-14 17:59:35 -07001597 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001598 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001599 in += 2;
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001600 int32_t l = mulRL(1, rl, vrl);
1601 int32_t r = mulRL(0, rl, vrl);
Andy Hung84a0c6e2014-04-02 11:24:53 -07001602 *fout++ = float_from_q4_27(l);
1603 *fout++ = float_from_q4_27(r);
Andy Hung3375bde2014-02-28 15:51:47 -08001604 // Note: In case of later int16_t sink output,
1605 // conversion and clamping is done by memcpy_to_i16_from_float().
Mathias Agopian65ab4712010-07-14 17:59:35 -07001606 } while (--outFrames);
Andy Hungf8a106a2014-05-29 18:52:38 -07001607 break;
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001608 case AUDIO_FORMAT_PCM_16_BIT:
Andy Hung97ae8242014-05-30 10:35:47 -07001609 if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001610 // volume is boosted, so we might need to clamp even though
1611 // we process only one track.
1612 do {
1613 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1614 in += 2;
1615 int32_t l = mulRL(1, rl, vrl) >> 12;
1616 int32_t r = mulRL(0, rl, vrl) >> 12;
1617 // clamping...
1618 l = clamp16(l);
1619 r = clamp16(r);
1620 *out++ = (r<<16) | (l & 0xFFFF);
1621 } while (--outFrames);
1622 } else {
1623 do {
1624 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1625 in += 2;
1626 int32_t l = mulRL(1, rl, vrl) >> 12;
1627 int32_t r = mulRL(0, rl, vrl) >> 12;
1628 *out++ = (r<<16) | (l & 0xFFFF);
1629 } while (--outFrames);
1630 }
1631 break;
1632 default:
Andy Hung8ed196a2018-01-05 13:21:11 -08001633 LOG_ALWAYS_FATAL("bad mixer format: %d", t->mMixerFormat);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001634 }
1635 numFrames -= b.frameCount;
Andy Hung8ed196a2018-01-05 13:21:11 -08001636 t->bufferProvider->releaseBuffer(&b);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001637 }
1638}
1639
Glenn Kasten52008f82012-03-18 09:34:41 -07001640/*static*/ pthread_once_t AudioMixer::sOnceControl = PTHREAD_ONCE_INIT;
1641
1642/*static*/ void AudioMixer::sInitRoutine()
1643{
Andy Hung34803d52014-07-16 21:41:35 -07001644 DownmixerBufferProvider::init(); // for the downmixer
John Grossman4ff14ba2012-02-08 16:37:41 -08001645}
1646
Andy Hunge93b6b72014-07-17 21:30:53 -07001647/* TODO: consider whether this level of optimization is necessary.
1648 * Perhaps just stick with a single for loop.
1649 */
1650
1651// Needs to derive a compile time constant (constexpr). Could be targeted to go
1652// to a MONOVOL mixtype based on MAX_NUM_VOLUMES, but that's an unnecessary complication.
Chih-Hung Hsiehbf291732016-05-17 15:16:07 -07001653#define MIXTYPE_MONOVOL(mixtype) ((mixtype) == MIXTYPE_MULTI ? MIXTYPE_MULTI_MONOVOL : \
1654 (mixtype) == MIXTYPE_MULTI_SAVEONLY ? MIXTYPE_MULTI_SAVEONLY_MONOVOL : (mixtype))
Andy Hunge93b6b72014-07-17 21:30:53 -07001655
1656/* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
1657 * TO: int32_t (Q4.27) or float
1658 * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
Andy Hung116a4982017-11-30 10:15:08 -08001659 * TA: int32_t (Q4.27) or float
Andy Hunge93b6b72014-07-17 21:30:53 -07001660 */
1661template <int MIXTYPE,
1662 typename TO, typename TI, typename TV, typename TA, typename TAV>
1663static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount,
1664 const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc)
1665{
1666 switch (channels) {
1667 case 1:
1668 volumeRampMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, volinc, vola, volainc);
1669 break;
1670 case 2:
1671 volumeRampMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, volinc, vola, volainc);
1672 break;
1673 case 3:
1674 volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out,
1675 frameCount, in, aux, vol, volinc, vola, volainc);
1676 break;
1677 case 4:
1678 volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out,
1679 frameCount, in, aux, vol, volinc, vola, volainc);
1680 break;
1681 case 5:
1682 volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out,
1683 frameCount, in, aux, vol, volinc, vola, volainc);
1684 break;
1685 case 6:
1686 volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out,
1687 frameCount, in, aux, vol, volinc, vola, volainc);
1688 break;
1689 case 7:
1690 volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out,
1691 frameCount, in, aux, vol, volinc, vola, volainc);
1692 break;
1693 case 8:
1694 volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out,
1695 frameCount, in, aux, vol, volinc, vola, volainc);
1696 break;
1697 }
1698}
1699
1700/* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
1701 * TO: int32_t (Q4.27) or float
1702 * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
Andy Hung116a4982017-11-30 10:15:08 -08001703 * TA: int32_t (Q4.27) or float
Andy Hunge93b6b72014-07-17 21:30:53 -07001704 */
1705template <int MIXTYPE,
1706 typename TO, typename TI, typename TV, typename TA, typename TAV>
1707static void volumeMulti(uint32_t channels, TO* out, size_t frameCount,
1708 const TI* in, TA* aux, const TV *vol, TAV vola)
1709{
1710 switch (channels) {
1711 case 1:
1712 volumeMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, vola);
1713 break;
1714 case 2:
1715 volumeMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, vola);
1716 break;
1717 case 3:
1718 volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, frameCount, in, aux, vol, vola);
1719 break;
1720 case 4:
1721 volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, frameCount, in, aux, vol, vola);
1722 break;
1723 case 5:
1724 volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, frameCount, in, aux, vol, vola);
1725 break;
1726 case 6:
1727 volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, frameCount, in, aux, vol, vola);
1728 break;
1729 case 7:
1730 volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, frameCount, in, aux, vol, vola);
1731 break;
1732 case 8:
1733 volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, frameCount, in, aux, vol, vola);
1734 break;
1735 }
1736}
1737
1738/* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
1739 * USEFLOATVOL (set to true if float volume is used)
1740 * ADJUSTVOL (set to true if volume ramp parameters needs adjustment afterwards)
1741 * TO: int32_t (Q4.27) or float
1742 * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
Andy Hung116a4982017-11-30 10:15:08 -08001743 * TA: int32_t (Q4.27) or float
Andy Hunge93b6b72014-07-17 21:30:53 -07001744 */
1745template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
Andy Hung5e58b0a2014-06-23 19:07:29 -07001746 typename TO, typename TI, typename TA>
Andy Hung8ed196a2018-01-05 13:21:11 -08001747void AudioMixer::Track::volumeMix(TO *out, size_t outFrames,
1748 const TI *in, TA *aux, bool ramp)
Andy Hung5e58b0a2014-06-23 19:07:29 -07001749{
1750 if (USEFLOATVOL) {
1751 if (ramp) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001752 volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
1753 mPrevVolume, mVolumeInc,
Andy Hung116a4982017-11-30 10:15:08 -08001754#ifdef FLOAT_AUX
Andy Hung8ed196a2018-01-05 13:21:11 -08001755 &mPrevAuxLevel, mAuxInc
Andy Hung116a4982017-11-30 10:15:08 -08001756#else
Andy Hung8ed196a2018-01-05 13:21:11 -08001757 &prevAuxLevel, auxInc
Andy Hung116a4982017-11-30 10:15:08 -08001758#endif
1759 );
Andy Hung5e58b0a2014-06-23 19:07:29 -07001760 if (ADJUSTVOL) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001761 adjustVolumeRamp(aux != NULL, true);
Andy Hung5e58b0a2014-06-23 19:07:29 -07001762 }
1763 } else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001764 volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
1765 mVolume,
Andy Hung116a4982017-11-30 10:15:08 -08001766#ifdef FLOAT_AUX
Andy Hung8ed196a2018-01-05 13:21:11 -08001767 mAuxLevel
Andy Hung116a4982017-11-30 10:15:08 -08001768#else
Andy Hung8ed196a2018-01-05 13:21:11 -08001769 auxLevel
Andy Hung116a4982017-11-30 10:15:08 -08001770#endif
1771 );
Andy Hung5e58b0a2014-06-23 19:07:29 -07001772 }
1773 } else {
1774 if (ramp) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001775 volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
1776 prevVolume, volumeInc, &prevAuxLevel, auxInc);
Andy Hung5e58b0a2014-06-23 19:07:29 -07001777 if (ADJUSTVOL) {
Andy Hung8ed196a2018-01-05 13:21:11 -08001778 adjustVolumeRamp(aux != NULL);
Andy Hung5e58b0a2014-06-23 19:07:29 -07001779 }
1780 } else {
Andy Hung8ed196a2018-01-05 13:21:11 -08001781 volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
1782 volume, auxLevel);
Andy Hung5e58b0a2014-06-23 19:07:29 -07001783 }
1784 }
1785}
1786
Andy Hung296b7412014-06-17 15:25:47 -07001787/* This process hook is called when there is a single track without
1788 * aux buffer, volume ramp, or resampling.
1789 * TODO: Update the hook selection: this can properly handle aux and ramp.
Andy Hunge93b6b72014-07-17 21:30:53 -07001790 *
1791 * MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
1792 * TO: int32_t (Q4.27) or float
1793 * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
1794 * TA: int32_t (Q4.27)
Andy Hung296b7412014-06-17 15:25:47 -07001795 */
Andy Hunge93b6b72014-07-17 21:30:53 -07001796template <int MIXTYPE, typename TO, typename TI, typename TA>
Andy Hung8ed196a2018-01-05 13:21:11 -08001797void AudioMixer::process__noResampleOneTrack()
Andy Hung296b7412014-06-17 15:25:47 -07001798{
Andy Hung8ed196a2018-01-05 13:21:11 -08001799 ALOGVV("process__noResampleOneTrack\n");
1800 LOG_ALWAYS_FATAL_IF(mEnabled.size() != 1,
1801 "%zu != 1 tracks enabled", mEnabled.size());
1802 const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
Andy Hunge93b6b72014-07-17 21:30:53 -07001803 const uint32_t channels = t->mMixerChannelCount;
Andy Hung296b7412014-06-17 15:25:47 -07001804 TO* out = reinterpret_cast<TO*>(t->mainBuffer);
1805 TA* aux = reinterpret_cast<TA*>(t->auxBuffer);
1806 const bool ramp = t->needsRamp();
1807
Andy Hung8ed196a2018-01-05 13:21:11 -08001808 for (size_t numFrames = mFrameCount; numFrames > 0; ) {
Andy Hung296b7412014-06-17 15:25:47 -07001809 AudioBufferProvider::Buffer& b(t->buffer);
1810 // get input buffer
1811 b.frameCount = numFrames;
Glenn Kastend79072e2016-01-06 08:41:20 -08001812 t->bufferProvider->getNextBuffer(&b);
Andy Hung296b7412014-06-17 15:25:47 -07001813 const TI *in = reinterpret_cast<TI*>(b.raw);
1814
1815 // in == NULL can happen if the track was flushed just after having
1816 // been enabled for mixing.
1817 if (in == NULL || (((uintptr_t)in) & 3)) {
1818 memset(out, 0, numFrames
Andy Hunge93b6b72014-07-17 21:30:53 -07001819 * channels * audio_bytes_per_sample(t->mMixerFormat));
Andy Hung8ed196a2018-01-05 13:21:11 -08001820 ALOGE_IF((((uintptr_t)in) & 3), "process__noResampleOneTrack: bus error: "
Andy Hung296b7412014-06-17 15:25:47 -07001821 "buffer %p track %p, channels %d, needs %#x",
Andy Hung8ed196a2018-01-05 13:21:11 -08001822 in, &t, t->channelCount, t->needs);
Andy Hung296b7412014-06-17 15:25:47 -07001823 return;
1824 }
1825
1826 const size_t outFrames = b.frameCount;
Andy Hung8ed196a2018-01-05 13:21:11 -08001827 t->volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, false /* ADJUSTVOL */> (
1828 out, outFrames, in, aux, ramp);
Andy Hung5e58b0a2014-06-23 19:07:29 -07001829
Andy Hunge93b6b72014-07-17 21:30:53 -07001830 out += outFrames * channels;
Andy Hung296b7412014-06-17 15:25:47 -07001831 if (aux != NULL) {
Andy Hunga6018892018-02-21 14:32:16 -08001832 aux += outFrames;
Andy Hung296b7412014-06-17 15:25:47 -07001833 }
1834 numFrames -= b.frameCount;
1835
1836 // release buffer
1837 t->bufferProvider->releaseBuffer(&b);
1838 }
1839 if (ramp) {
Andy Hung5e58b0a2014-06-23 19:07:29 -07001840 t->adjustVolumeRamp(aux != NULL, is_same<TI, float>::value);
Andy Hung296b7412014-06-17 15:25:47 -07001841 }
1842}
1843
1844/* This track hook is called to do resampling then mixing,
1845 * pulling from the track's upstream AudioBufferProvider.
Andy Hunge93b6b72014-07-17 21:30:53 -07001846 *
1847 * MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
1848 * TO: int32_t (Q4.27) or float
1849 * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
Andy Hung116a4982017-11-30 10:15:08 -08001850 * TA: int32_t (Q4.27) or float
Andy Hung296b7412014-06-17 15:25:47 -07001851 */
Andy Hunge93b6b72014-07-17 21:30:53 -07001852template <int MIXTYPE, typename TO, typename TI, typename TA>
Andy Hung8ed196a2018-01-05 13:21:11 -08001853void AudioMixer::Track::track__Resample(TO* out, size_t outFrameCount, TO* temp, TA* aux)
Andy Hung296b7412014-06-17 15:25:47 -07001854{
1855 ALOGVV("track__Resample\n");
Andy Hung8ed196a2018-01-05 13:21:11 -08001856 mResampler->setSampleRate(sampleRate);
1857 const bool ramp = needsRamp();
Andy Hung296b7412014-06-17 15:25:47 -07001858 if (ramp || aux != NULL) {
1859 // if ramp: resample with unity gain to temp buffer and scale/mix in 2nd step.
1860 // if aux != NULL: resample with unity gain to temp buffer then apply send level.
1861
Andy Hung8ed196a2018-01-05 13:21:11 -08001862 mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
1863 memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(TO));
1864 mResampler->resample((int32_t*)temp, outFrameCount, bufferProvider);
Andy Hung5e58b0a2014-06-23 19:07:29 -07001865
Andy Hung116a4982017-11-30 10:15:08 -08001866 volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
Andy Hung8ed196a2018-01-05 13:21:11 -08001867 out, outFrameCount, temp, aux, ramp);
Andy Hung5e58b0a2014-06-23 19:07:29 -07001868
Andy Hung296b7412014-06-17 15:25:47 -07001869 } else { // constant volume gain
Andy Hung8ed196a2018-01-05 13:21:11 -08001870 mResampler->setVolume(mVolume[0], mVolume[1]);
1871 mResampler->resample((int32_t*)out, outFrameCount, bufferProvider);
Andy Hung296b7412014-06-17 15:25:47 -07001872 }
1873}
1874
1875/* This track hook is called to mix a track, when no resampling is required.
Andy Hung8ed196a2018-01-05 13:21:11 -08001876 * The input buffer should be present in in.
Andy Hunge93b6b72014-07-17 21:30:53 -07001877 *
1878 * MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
1879 * TO: int32_t (Q4.27) or float
1880 * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
Andy Hung116a4982017-11-30 10:15:08 -08001881 * TA: int32_t (Q4.27) or float
Andy Hung296b7412014-06-17 15:25:47 -07001882 */
Andy Hunge93b6b72014-07-17 21:30:53 -07001883template <int MIXTYPE, typename TO, typename TI, typename TA>
Andy Hung8ed196a2018-01-05 13:21:11 -08001884void AudioMixer::Track::track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux)
Andy Hung296b7412014-06-17 15:25:47 -07001885{
1886 ALOGVV("track__NoResample\n");
Andy Hung8ed196a2018-01-05 13:21:11 -08001887 const TI *in = static_cast<const TI *>(mIn);
Andy Hung296b7412014-06-17 15:25:47 -07001888
Andy Hung116a4982017-11-30 10:15:08 -08001889 volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
Andy Hung8ed196a2018-01-05 13:21:11 -08001890 out, frameCount, in, aux, needsRamp());
Andy Hung5e58b0a2014-06-23 19:07:29 -07001891
Andy Hung296b7412014-06-17 15:25:47 -07001892 // MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels.
1893 // MIXTYPE_MULTI reads NCHAN input channels and places to NCHAN output channels.
Andy Hung8ed196a2018-01-05 13:21:11 -08001894 in += (MIXTYPE == MIXTYPE_MONOEXPAND) ? frameCount : frameCount * mMixerChannelCount;
1895 mIn = in;
Andy Hung296b7412014-06-17 15:25:47 -07001896}
1897
1898/* The Mixer engine generates either int32_t (Q4_27) or float data.
1899 * We use this function to convert the engine buffers
1900 * to the desired mixer output format, either int16_t (Q.15) or float.
1901 */
Andy Hung8ed196a2018-01-05 13:21:11 -08001902/* static */
Andy Hung296b7412014-06-17 15:25:47 -07001903void AudioMixer::convertMixerFormat(void *out, audio_format_t mixerOutFormat,
1904 void *in, audio_format_t mixerInFormat, size_t sampleCount)
1905{
1906 switch (mixerInFormat) {
1907 case AUDIO_FORMAT_PCM_FLOAT:
1908 switch (mixerOutFormat) {
1909 case AUDIO_FORMAT_PCM_FLOAT:
1910 memcpy(out, in, sampleCount * sizeof(float)); // MEMCPY. TODO optimize out
1911 break;
1912 case AUDIO_FORMAT_PCM_16_BIT:
1913 memcpy_to_i16_from_float((int16_t*)out, (float*)in, sampleCount);
1914 break;
1915 default:
1916 LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
1917 break;
1918 }
1919 break;
1920 case AUDIO_FORMAT_PCM_16_BIT:
1921 switch (mixerOutFormat) {
1922 case AUDIO_FORMAT_PCM_FLOAT:
Andy Hung5effdf62017-11-27 13:51:40 -08001923 memcpy_to_float_from_q4_27((float*)out, (const int32_t*)in, sampleCount);
Andy Hung296b7412014-06-17 15:25:47 -07001924 break;
1925 case AUDIO_FORMAT_PCM_16_BIT:
Andy Hung5effdf62017-11-27 13:51:40 -08001926 memcpy_to_i16_from_q4_27((int16_t*)out, (const int32_t*)in, sampleCount);
Andy Hung296b7412014-06-17 15:25:47 -07001927 break;
1928 default:
1929 LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
1930 break;
1931 }
1932 break;
1933 default:
1934 LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
1935 break;
1936 }
1937}
1938
1939/* Returns the proper track hook to use for mixing the track into the output buffer.
1940 */
Andy Hung8ed196a2018-01-05 13:21:11 -08001941/* static */
1942AudioMixer::hook_t AudioMixer::Track::getTrackHook(int trackType, uint32_t channelCount,
Andy Hung296b7412014-06-17 15:25:47 -07001943 audio_format_t mixerInFormat, audio_format_t mixerOutFormat __unused)
1944{
Andy Hunge93b6b72014-07-17 21:30:53 -07001945 if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
Andy Hung296b7412014-06-17 15:25:47 -07001946 switch (trackType) {
1947 case TRACKTYPE_NOP:
Andy Hung8ed196a2018-01-05 13:21:11 -08001948 return &Track::track__nop;
Andy Hung296b7412014-06-17 15:25:47 -07001949 case TRACKTYPE_RESAMPLE:
Andy Hung8ed196a2018-01-05 13:21:11 -08001950 return &Track::track__genericResample;
Andy Hung296b7412014-06-17 15:25:47 -07001951 case TRACKTYPE_NORESAMPLEMONO:
Andy Hung8ed196a2018-01-05 13:21:11 -08001952 return &Track::track__16BitsMono;
Andy Hung296b7412014-06-17 15:25:47 -07001953 case TRACKTYPE_NORESAMPLE:
Andy Hung8ed196a2018-01-05 13:21:11 -08001954 return &Track::track__16BitsStereo;
Andy Hung296b7412014-06-17 15:25:47 -07001955 default:
1956 LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
1957 break;
1958 }
1959 }
Andy Hunge93b6b72014-07-17 21:30:53 -07001960 LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
Andy Hung296b7412014-06-17 15:25:47 -07001961 switch (trackType) {
1962 case TRACKTYPE_NOP:
Andy Hung8ed196a2018-01-05 13:21:11 -08001963 return &Track::track__nop;
Andy Hung296b7412014-06-17 15:25:47 -07001964 case TRACKTYPE_RESAMPLE:
1965 switch (mixerInFormat) {
1966 case AUDIO_FORMAT_PCM_FLOAT:
Andy Hung8ed196a2018-01-05 13:21:11 -08001967 return (AudioMixer::hook_t) &Track::track__Resample<
Andy Hung116a4982017-11-30 10:15:08 -08001968 MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07001969 case AUDIO_FORMAT_PCM_16_BIT:
Andy Hung8ed196a2018-01-05 13:21:11 -08001970 return (AudioMixer::hook_t) &Track::track__Resample<
Andy Hung116a4982017-11-30 10:15:08 -08001971 MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07001972 default:
1973 LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
1974 break;
1975 }
1976 break;
1977 case TRACKTYPE_NORESAMPLEMONO:
1978 switch (mixerInFormat) {
1979 case AUDIO_FORMAT_PCM_FLOAT:
Andy Hung8ed196a2018-01-05 13:21:11 -08001980 return (AudioMixer::hook_t) &Track::track__NoResample<
Andy Hung116a4982017-11-30 10:15:08 -08001981 MIXTYPE_MONOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07001982 case AUDIO_FORMAT_PCM_16_BIT:
Andy Hung8ed196a2018-01-05 13:21:11 -08001983 return (AudioMixer::hook_t) &Track::track__NoResample<
Andy Hung116a4982017-11-30 10:15:08 -08001984 MIXTYPE_MONOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07001985 default:
1986 LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
1987 break;
1988 }
1989 break;
1990 case TRACKTYPE_NORESAMPLE:
1991 switch (mixerInFormat) {
1992 case AUDIO_FORMAT_PCM_FLOAT:
Andy Hung8ed196a2018-01-05 13:21:11 -08001993 return (AudioMixer::hook_t) &Track::track__NoResample<
Andy Hung116a4982017-11-30 10:15:08 -08001994 MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07001995 case AUDIO_FORMAT_PCM_16_BIT:
Andy Hung8ed196a2018-01-05 13:21:11 -08001996 return (AudioMixer::hook_t) &Track::track__NoResample<
Andy Hung116a4982017-11-30 10:15:08 -08001997 MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07001998 default:
1999 LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
2000 break;
2001 }
2002 break;
2003 default:
2004 LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
2005 break;
2006 }
2007 return NULL;
2008}
2009
2010/* Returns the proper process hook for mixing tracks. Currently works only for
2011 * PROCESSTYPE_NORESAMPLEONETRACK, a mix involving one track, no resampling.
Andy Hung395db4b2014-08-25 17:15:29 -07002012 *
2013 * TODO: Due to the special mixing considerations of duplicating to
2014 * a stereo output track, the input track cannot be MONO. This should be
2015 * prevented by the caller.
Andy Hung296b7412014-06-17 15:25:47 -07002016 */
Andy Hung8ed196a2018-01-05 13:21:11 -08002017/* static */
2018AudioMixer::process_hook_t AudioMixer::getProcessHook(
2019 int processType, uint32_t channelCount,
Andy Hung296b7412014-06-17 15:25:47 -07002020 audio_format_t mixerInFormat, audio_format_t mixerOutFormat)
2021{
2022 if (processType != PROCESSTYPE_NORESAMPLEONETRACK) { // Only NORESAMPLEONETRACK
2023 LOG_ALWAYS_FATAL("bad processType: %d", processType);
2024 return NULL;
2025 }
Andy Hunge93b6b72014-07-17 21:30:53 -07002026 if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
Andy Hung8ed196a2018-01-05 13:21:11 -08002027 return &AudioMixer::process__oneTrack16BitsStereoNoResampling;
Andy Hung296b7412014-06-17 15:25:47 -07002028 }
Andy Hunge93b6b72014-07-17 21:30:53 -07002029 LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
Andy Hung296b7412014-06-17 15:25:47 -07002030 switch (mixerInFormat) {
2031 case AUDIO_FORMAT_PCM_FLOAT:
2032 switch (mixerOutFormat) {
2033 case AUDIO_FORMAT_PCM_FLOAT:
Andy Hung8ed196a2018-01-05 13:21:11 -08002034 return &AudioMixer::process__noResampleOneTrack<
Andy Hung116a4982017-11-30 10:15:08 -08002035 MIXTYPE_MULTI_SAVEONLY, float /*TO*/, float /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07002036 case AUDIO_FORMAT_PCM_16_BIT:
Andy Hung8ed196a2018-01-05 13:21:11 -08002037 return &AudioMixer::process__noResampleOneTrack<
Andy Hung116a4982017-11-30 10:15:08 -08002038 MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, float /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07002039 default:
2040 LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
2041 break;
2042 }
2043 break;
2044 case AUDIO_FORMAT_PCM_16_BIT:
2045 switch (mixerOutFormat) {
2046 case AUDIO_FORMAT_PCM_FLOAT:
Andy Hung8ed196a2018-01-05 13:21:11 -08002047 return &AudioMixer::process__noResampleOneTrack<
Andy Hung116a4982017-11-30 10:15:08 -08002048 MIXTYPE_MULTI_SAVEONLY, float /*TO*/, int16_t /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07002049 case AUDIO_FORMAT_PCM_16_BIT:
Andy Hung8ed196a2018-01-05 13:21:11 -08002050 return &AudioMixer::process__noResampleOneTrack<
Andy Hung116a4982017-11-30 10:15:08 -08002051 MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
Andy Hung296b7412014-06-17 15:25:47 -07002052 default:
2053 LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
2054 break;
2055 }
2056 break;
2057 default:
2058 LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
2059 break;
2060 }
2061 return NULL;
2062}
2063
Mathias Agopian65ab4712010-07-14 17:59:35 -07002064// ----------------------------------------------------------------------------
Glenn Kasten63238ef2015-03-02 15:50:29 -08002065} // namespace android