blob: a0f2b7d749d55097ab4ddb4d56d28a2c3252b7d6 [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
Glenn Kasten153b9fe2013-07-15 11:23:36 -070021#include "Configuration.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070022#include <stdint.h>
23#include <string.h>
24#include <stdlib.h>
25#include <sys/types.h>
26
27#include <utils/Errors.h>
28#include <utils/Log.h>
29
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070030#include <cutils/bitops.h>
Glenn Kastenf6b16782011-12-15 09:51:17 -080031#include <cutils/compiler.h>
Glenn Kasten5798d4e2012-03-08 12:18:35 -080032#include <utils/Debug.h>
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070033
34#include <system/audio.h>
35
Glenn Kasten3b21c502011-12-15 09:52:39 -080036#include <audio_utils/primitives.h>
Andy Hungef7c7fb2014-05-12 16:51:41 -070037#include <audio_utils/format.h>
John Grossman4ff14ba2012-02-08 16:37:41 -080038#include <common_time/local_clock.h>
39#include <common_time/cc_helper.h>
Glenn Kasten3b21c502011-12-15 09:52:39 -080040
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070041#include <media/EffectsFactoryApi.h>
42
Mathias Agopian65ab4712010-07-14 17:59:35 -070043#include "AudioMixer.h"
44
45namespace android {
Mathias Agopian65ab4712010-07-14 17:59:35 -070046
47// ----------------------------------------------------------------------------
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070048AudioMixer::DownmixerBufferProvider::DownmixerBufferProvider() : AudioBufferProvider(),
49 mTrackBufferProvider(NULL), mDownmixHandle(NULL)
50{
51}
52
53AudioMixer::DownmixerBufferProvider::~DownmixerBufferProvider()
54{
55 ALOGV("AudioMixer deleting DownmixerBufferProvider (%p)", this);
56 EffectRelease(mDownmixHandle);
57}
58
59status_t AudioMixer::DownmixerBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer,
60 int64_t pts) {
61 //ALOGV("DownmixerBufferProvider::getNextBuffer()");
Glenn Kasten8f325372013-10-30 14:36:47 -070062 if (mTrackBufferProvider != NULL) {
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070063 status_t res = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
64 if (res == OK) {
65 mDownmixConfig.inputCfg.buffer.frameCount = pBuffer->frameCount;
66 mDownmixConfig.inputCfg.buffer.raw = pBuffer->raw;
67 mDownmixConfig.outputCfg.buffer.frameCount = pBuffer->frameCount;
68 mDownmixConfig.outputCfg.buffer.raw = mDownmixConfig.inputCfg.buffer.raw;
69 // in-place so overwrite the buffer contents, has been set in prepareTrackForDownmix()
70 //mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
71
72 res = (*mDownmixHandle)->process(mDownmixHandle,
73 &mDownmixConfig.inputCfg.buffer, &mDownmixConfig.outputCfg.buffer);
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -070074 //ALOGV("getNextBuffer is downmixing");
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070075 }
76 return res;
77 } else {
78 ALOGE("DownmixerBufferProvider::getNextBuffer() error: NULL track buffer provider");
79 return NO_INIT;
80 }
81}
82
83void AudioMixer::DownmixerBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -070084 //ALOGV("DownmixerBufferProvider::releaseBuffer()");
Glenn Kasten8f325372013-10-30 14:36:47 -070085 if (mTrackBufferProvider != NULL) {
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070086 mTrackBufferProvider->releaseBuffer(pBuffer);
87 } else {
88 ALOGE("DownmixerBufferProvider::releaseBuffer() error: NULL track buffer provider");
89 }
90}
91
Andy Hungef7c7fb2014-05-12 16:51:41 -070092template <typename T>
93T min(const T& a, const T& b)
94{
95 return a < b ? a : b;
96}
97
98AudioMixer::ReformatBufferProvider::ReformatBufferProvider(int32_t channels,
99 audio_format_t inputFormat, audio_format_t outputFormat) :
100 mTrackBufferProvider(NULL),
101 mChannels(channels),
102 mInputFormat(inputFormat),
103 mOutputFormat(outputFormat),
104 mInputFrameSize(channels * audio_bytes_per_sample(inputFormat)),
105 mOutputFrameSize(channels * audio_bytes_per_sample(outputFormat)),
106 mOutputData(NULL),
107 mOutputCount(0),
108 mConsumed(0)
109{
110 ALOGV("ReformatBufferProvider(%p)(%d, %#x, %#x)", this, channels, inputFormat, outputFormat);
111 if (requiresInternalBuffers()) {
112 mOutputCount = 256;
113 (void)posix_memalign(&mOutputData, 32, mOutputCount * mOutputFrameSize);
114 }
115 mBuffer.frameCount = 0;
116}
117
118AudioMixer::ReformatBufferProvider::~ReformatBufferProvider()
119{
120 ALOGV("~ReformatBufferProvider(%p)", this);
121 if (mBuffer.frameCount != 0) {
122 mTrackBufferProvider->releaseBuffer(&mBuffer);
123 }
124 free(mOutputData);
125}
126
127status_t AudioMixer::ReformatBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer,
128 int64_t pts) {
129 //ALOGV("ReformatBufferProvider(%p)::getNextBuffer(%p (%zu), %lld)",
130 // this, pBuffer, pBuffer->frameCount, pts);
131 if (!requiresInternalBuffers()) {
132 status_t res = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
133 if (res == OK) {
134 memcpy_by_audio_format(pBuffer->raw, mOutputFormat, pBuffer->raw, mInputFormat,
135 pBuffer->frameCount * mChannels);
136 }
137 return res;
138 }
139 if (mBuffer.frameCount == 0) {
140 mBuffer.frameCount = pBuffer->frameCount;
141 status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer, pts);
142 // TODO: Track down a bug in the upstream provider
143 // LOG_ALWAYS_FATAL_IF(res == OK && mBuffer.frameCount == 0,
144 // "ReformatBufferProvider::getNextBuffer():"
145 // " Invalid zero framecount returned from getNextBuffer()");
146 if (res != OK || mBuffer.frameCount == 0) {
147 pBuffer->raw = NULL;
148 pBuffer->frameCount = 0;
149 return res;
150 }
151 }
152 ALOG_ASSERT(mConsumed < mBuffer.frameCount);
153 size_t count = min(mOutputCount, mBuffer.frameCount - mConsumed);
154 count = min(count, pBuffer->frameCount);
155 pBuffer->raw = mOutputData;
156 pBuffer->frameCount = count;
157 //ALOGV("reformatting %d frames from %#x to %#x, %d chan",
158 // pBuffer->frameCount, mInputFormat, mOutputFormat, mChannels);
159 memcpy_by_audio_format(pBuffer->raw, mOutputFormat,
160 (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize, mInputFormat,
161 pBuffer->frameCount * mChannels);
162 return OK;
163}
164
165void AudioMixer::ReformatBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
166 //ALOGV("ReformatBufferProvider(%p)::releaseBuffer(%p(%zu))",
167 // this, pBuffer, pBuffer->frameCount);
168 if (!requiresInternalBuffers()) {
169 mTrackBufferProvider->releaseBuffer(pBuffer);
170 return;
171 }
172 // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
173 mConsumed += pBuffer->frameCount; // TODO: update for efficiency to reuse existing content
174 if (mConsumed != 0 && mConsumed >= mBuffer.frameCount) {
175 mConsumed = 0;
176 mTrackBufferProvider->releaseBuffer(&mBuffer);
177 // ALOG_ASSERT(mBuffer.frameCount == 0);
178 }
179 pBuffer->raw = NULL;
180 pBuffer->frameCount = 0;
181}
182
183void AudioMixer::ReformatBufferProvider::reset() {
184 if (mBuffer.frameCount != 0) {
185 mTrackBufferProvider->releaseBuffer(&mBuffer);
186 }
187 mConsumed = 0;
188}
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700189
190// ----------------------------------------------------------------------------
Glenn Kasten49c34ac2013-10-30 14:37:01 -0700191bool AudioMixer::sIsMultichannelCapable = false;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700192
Glenn Kasten49c34ac2013-10-30 14:37:01 -0700193effect_descriptor_t AudioMixer::sDwnmFxDesc;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700194
Paul Lind3c0a0e82012-08-01 18:49:49 -0700195// Ensure mConfiguredNames bitmask is initialized properly on all architectures.
196// The value of 1 << x is undefined in C when x >= 32.
197
Glenn Kasten5c94b6c2012-03-20 17:01:29 -0700198AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate, uint32_t maxNumTracks)
Paul Lind3c0a0e82012-08-01 18:49:49 -0700199 : mTrackNames(0), mConfiguredNames((maxNumTracks >= 32 ? 0 : 1 << maxNumTracks) - 1),
Glenn Kasten7f5d3352013-02-15 23:55:04 +0000200 mSampleRate(sampleRate)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700201{
Glenn Kasten788040c2011-05-05 08:19:00 -0700202 // AudioMixer is not yet capable of multi-channel beyond stereo
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800203 COMPILE_TIME_ASSERT_FUNCTION_SCOPE(2 == MAX_NUM_CHANNELS);
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -0700204
Glenn Kasten5c94b6c2012-03-20 17:01:29 -0700205 ALOG_ASSERT(maxNumTracks <= MAX_NUM_TRACKS, "maxNumTracks %u > MAX_NUM_TRACKS %u",
206 maxNumTracks, MAX_NUM_TRACKS);
207
Glenn Kasten599fabc2012-03-08 12:33:37 -0800208 // AudioMixer is not yet capable of more than 32 active track inputs
209 ALOG_ASSERT(32 >= MAX_NUM_TRACKS, "bad MAX_NUM_TRACKS %d", MAX_NUM_TRACKS);
210
211 // AudioMixer is not yet capable of multi-channel output beyond stereo
212 ALOG_ASSERT(2 == MAX_NUM_CHANNELS, "bad MAX_NUM_CHANNELS %d", MAX_NUM_CHANNELS);
213
Glenn Kasten52008f82012-03-18 09:34:41 -0700214 pthread_once(&sOnceControl, &sInitRoutine);
215
Mathias Agopian65ab4712010-07-14 17:59:35 -0700216 mState.enabledTracks= 0;
217 mState.needsChanged = 0;
218 mState.frameCount = frameCount;
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800219 mState.hook = process__nop;
Glenn Kastene0feee32011-12-13 11:53:26 -0800220 mState.outputTemp = NULL;
221 mState.resampleTemp = NULL;
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800222 mState.mLog = &mDummyLog;
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800223 // mState.reserved
Glenn Kasten17a736c2012-02-14 08:52:15 -0800224
225 // FIXME Most of the following initialization is probably redundant since
226 // tracks[i] should only be referenced if (mTrackNames & (1 << i)) != 0
227 // and mTrackNames is initially 0. However, leave it here until that's verified.
Mathias Agopian65ab4712010-07-14 17:59:35 -0700228 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800229 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Eric Laurenta5e82142012-04-16 13:47:17 -0700230 t->resampler = NULL;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700231 t->downmixerBufferProvider = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700232 t++;
233 }
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700234
Mathias Agopian65ab4712010-07-14 17:59:35 -0700235}
236
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800237AudioMixer::~AudioMixer()
238{
239 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800240 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800241 delete t->resampler;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700242 delete t->downmixerBufferProvider;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800243 t++;
244 }
245 delete [] mState.outputTemp;
246 delete [] mState.resampleTemp;
247}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700248
Glenn Kastenab7d72f2013-02-27 09:05:28 -0800249void AudioMixer::setLog(NBLog::Writer *log)
250{
251 mState.mLog = log;
252}
253
Andy Hunge8a1ced2014-05-09 15:02:21 -0700254int AudioMixer::getTrackName(audio_channel_mask_t channelMask,
255 audio_format_t format, int sessionId)
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800256{
Andy Hunge8a1ced2014-05-09 15:02:21 -0700257 if (!isValidPcmTrackFormat(format)) {
258 ALOGE("AudioMixer::getTrackName invalid format (%#x)", format);
259 return -1;
260 }
Glenn Kasten5c94b6c2012-03-20 17:01:29 -0700261 uint32_t names = (~mTrackNames) & mConfiguredNames;
Glenn Kasten98dd5422011-12-15 14:38:29 -0800262 if (names != 0) {
263 int n = __builtin_ctz(names);
Steve Block3856b092011-10-20 11:56:00 +0100264 ALOGV("add track (%d)", n);
Glenn Kastendeeb1282012-03-25 11:59:31 -0700265 // assume default parameters for the track, except where noted below
266 track_t* t = &mState.tracks[n];
267 t->needs = 0;
268 t->volume[0] = UNITY_GAIN;
269 t->volume[1] = UNITY_GAIN;
270 // no initialization needed
271 // t->prevVolume[0]
272 // t->prevVolume[1]
273 t->volumeInc[0] = 0;
274 t->volumeInc[1] = 0;
275 t->auxLevel = 0;
276 t->auxInc = 0;
277 // no initialization needed
278 // t->prevAuxLevel
279 // t->frameCount
Andy Hung68112fc2014-05-14 14:13:23 -0700280 t->channelCount = audio_channel_count_from_out_mask(channelMask);
Glenn Kastendeeb1282012-03-25 11:59:31 -0700281 t->enabled = false;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700282 ALOGV_IF(channelMask != AUDIO_CHANNEL_OUT_STEREO,
283 "Non-stereo channel mask: %d\n", channelMask);
Andy Hung68112fc2014-05-14 14:13:23 -0700284 t->channelMask = channelMask;
Jean-Michel Trivid06e1322012-09-12 15:47:07 -0700285 t->sessionId = sessionId;
Glenn Kastendeeb1282012-03-25 11:59:31 -0700286 // setBufferProvider(name, AudioBufferProvider *) is required before enable(name)
287 t->bufferProvider = NULL;
288 t->buffer.raw = NULL;
289 // no initialization needed
290 // t->buffer.frameCount
291 t->hook = NULL;
292 t->in = NULL;
293 t->resampler = NULL;
294 t->sampleRate = mSampleRate;
295 // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
296 t->mainBuffer = NULL;
297 t->auxBuffer = NULL;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700298 t->mInputBufferProvider = NULL;
299 t->mReformatBufferProvider = NULL;
Glenn Kasten52008f82012-03-18 09:34:41 -0700300 t->downmixerBufferProvider = NULL;
Andy Hung78820702014-02-28 16:23:02 -0800301 t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
Andy Hunge8a1ced2014-05-09 15:02:21 -0700302 t->mFormat = format;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700303 t->mMixerInFormat = AUDIO_FORMAT_PCM_16_BIT;
304 if (t->mFormat != t->mMixerInFormat) {
305 prepareTrackForReformat(t, n);
306 }
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700307 status_t status = initTrackDownmix(&mState.tracks[n], n, channelMask);
Andy Hung68112fc2014-05-14 14:13:23 -0700308 if (status != OK) {
309 ALOGE("AudioMixer::getTrackName invalid channelMask (%#x)", channelMask);
310 return -1;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700311 }
Andy Hung68112fc2014-05-14 14:13:23 -0700312 mTrackNames |= 1 << n;
313 return TRACK0 + n;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700314 }
Andy Hung68112fc2014-05-14 14:13:23 -0700315 ALOGE("AudioMixer::getTrackName out of available tracks");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700316 return -1;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800317}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700318
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800319void AudioMixer::invalidateState(uint32_t mask)
320{
Glenn Kasten34fca342013-08-13 09:48:14 -0700321 if (mask != 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700322 mState.needsChanged |= mask;
323 mState.hook = process__validate;
324 }
325 }
326
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700327status_t AudioMixer::initTrackDownmix(track_t* pTrack, int trackNum, audio_channel_mask_t mask)
328{
Andy Hunge5412692014-05-16 11:25:07 -0700329 uint32_t channelCount = audio_channel_count_from_out_mask(mask);
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700330 ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount);
331 status_t status = OK;
332 if (channelCount > MAX_NUM_CHANNELS) {
333 pTrack->channelMask = mask;
334 pTrack->channelCount = channelCount;
335 ALOGV("initTrackDownmix(track=%d, mask=0x%x) calls prepareTrackForDownmix()",
336 trackNum, mask);
337 status = prepareTrackForDownmix(pTrack, trackNum);
338 } else {
339 unprepareTrackForDownmix(pTrack, trackNum);
340 }
341 return status;
342}
343
Andy Hungee931ff2014-01-28 13:44:14 -0800344void AudioMixer::unprepareTrackForDownmix(track_t* pTrack, int trackName __unused) {
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700345 ALOGV("AudioMixer::unprepareTrackForDownmix(%d)", trackName);
346
347 if (pTrack->downmixerBufferProvider != NULL) {
348 // this track had previously been configured with a downmixer, delete it
349 ALOGV(" deleting old downmixer");
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700350 delete pTrack->downmixerBufferProvider;
351 pTrack->downmixerBufferProvider = NULL;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700352 reconfigureBufferProviders(pTrack);
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700353 } else {
354 ALOGV(" nothing to do, no downmixer to delete");
355 }
356}
357
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700358status_t AudioMixer::prepareTrackForDownmix(track_t* pTrack, int trackName)
359{
360 ALOGV("AudioMixer::prepareTrackForDownmix(%d) with mask 0x%x", trackName, pTrack->channelMask);
361
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700362 // discard the previous downmixer if there was one
363 unprepareTrackForDownmix(pTrack, trackName);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700364
365 DownmixerBufferProvider* pDbp = new DownmixerBufferProvider();
366 int32_t status;
367
Glenn Kasten49c34ac2013-10-30 14:37:01 -0700368 if (!sIsMultichannelCapable) {
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700369 ALOGE("prepareTrackForDownmix(%d) fails: mixer doesn't support multichannel content",
370 trackName);
371 goto noDownmixForActiveTrack;
372 }
373
Glenn Kasten49c34ac2013-10-30 14:37:01 -0700374 if (EffectCreate(&sDwnmFxDesc.uuid,
Jean-Michel Trivid06e1322012-09-12 15:47:07 -0700375 pTrack->sessionId /*sessionId*/, -2 /*ioId not relevant here, using random value*/,
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700376 &pDbp->mDownmixHandle/*pHandle*/) != 0) {
377 ALOGE("prepareTrackForDownmix(%d) fails: error creating downmixer effect", trackName);
378 goto noDownmixForActiveTrack;
379 }
380
381 // channel input configuration will be overridden per-track
382 pDbp->mDownmixConfig.inputCfg.channels = pTrack->channelMask;
383 pDbp->mDownmixConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
384 pDbp->mDownmixConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
385 pDbp->mDownmixConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
386 pDbp->mDownmixConfig.inputCfg.samplingRate = pTrack->sampleRate;
387 pDbp->mDownmixConfig.outputCfg.samplingRate = pTrack->sampleRate;
388 pDbp->mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
389 pDbp->mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
390 // input and output buffer provider, and frame count will not be used as the downmix effect
391 // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
392 pDbp->mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
393 EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
394 pDbp->mDownmixConfig.outputCfg.mask = pDbp->mDownmixConfig.inputCfg.mask;
395
396 {// scope for local variables that are not used in goto label "noDownmixForActiveTrack"
397 int cmdStatus;
398 uint32_t replySize = sizeof(int);
399
400 // Configure and enable downmixer
401 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
402 EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
403 &pDbp->mDownmixConfig /*pCmdData*/,
404 &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
405 if ((status != 0) || (cmdStatus != 0)) {
406 ALOGE("error %d while configuring downmixer for track %d", status, trackName);
407 goto noDownmixForActiveTrack;
408 }
409 replySize = sizeof(int);
410 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
411 EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
412 &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
413 if ((status != 0) || (cmdStatus != 0)) {
414 ALOGE("error %d while enabling downmixer for track %d", status, trackName);
415 goto noDownmixForActiveTrack;
416 }
417
418 // Set downmix type
419 // parameter size rounded for padding on 32bit boundary
420 const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
421 const int downmixParamSize =
422 sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
423 effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
424 param->psize = sizeof(downmix_params_t);
425 const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
426 memcpy(param->data, &downmixParam, param->psize);
427 const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
428 param->vsize = sizeof(downmix_type_t);
429 memcpy(param->data + psizePadded, &downmixType, param->vsize);
430
431 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
432 EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize/* cmdSize */,
433 param /*pCmndData*/, &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
434
435 free(param);
436
437 if ((status != 0) || (cmdStatus != 0)) {
438 ALOGE("error %d while setting downmix type for track %d", status, trackName);
439 goto noDownmixForActiveTrack;
440 } else {
441 ALOGV("downmix type set to %d for track %d", (int) downmixType, trackName);
442 }
443 }// end of scope for local variables that are not used in goto label "noDownmixForActiveTrack"
444
445 // initialization successful:
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700446 pTrack->downmixerBufferProvider = pDbp;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700447 reconfigureBufferProviders(pTrack);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700448 return NO_ERROR;
449
450noDownmixForActiveTrack:
451 delete pDbp;
452 pTrack->downmixerBufferProvider = NULL;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700453 reconfigureBufferProviders(pTrack);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700454 return NO_INIT;
455}
456
Andy Hungef7c7fb2014-05-12 16:51:41 -0700457void AudioMixer::unprepareTrackForReformat(track_t* pTrack, int trackName __unused) {
458 ALOGV("AudioMixer::unprepareTrackForReformat(%d)", trackName);
459 if (pTrack->mReformatBufferProvider != NULL) {
460 delete pTrack->mReformatBufferProvider;
461 pTrack->mReformatBufferProvider = NULL;
462 reconfigureBufferProviders(pTrack);
463 }
464}
465
466status_t AudioMixer::prepareTrackForReformat(track_t* pTrack, int trackName)
467{
468 ALOGV("AudioMixer::prepareTrackForReformat(%d) with format %#x", trackName, pTrack->mFormat);
469 // discard the previous reformatter if there was one
470 unprepareTrackForReformat(pTrack, trackName);
471 pTrack->mReformatBufferProvider = new ReformatBufferProvider(
472 audio_channel_count_from_out_mask(pTrack->channelMask),
473 pTrack->mFormat, pTrack->mMixerInFormat);
474 reconfigureBufferProviders(pTrack);
475 return NO_ERROR;
476}
477
478void AudioMixer::reconfigureBufferProviders(track_t* pTrack)
479{
480 pTrack->bufferProvider = pTrack->mInputBufferProvider;
481 if (pTrack->mReformatBufferProvider) {
482 pTrack->mReformatBufferProvider->mTrackBufferProvider = pTrack->bufferProvider;
483 pTrack->bufferProvider = pTrack->mReformatBufferProvider;
484 }
485 if (pTrack->downmixerBufferProvider) {
486 pTrack->downmixerBufferProvider->mTrackBufferProvider = pTrack->bufferProvider;
487 pTrack->bufferProvider = pTrack->downmixerBufferProvider;
488 }
489}
490
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800491void AudioMixer::deleteTrackName(int name)
492{
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700493 ALOGV("AudioMixer::deleteTrackName(%d)", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700494 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800495 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten237a6242011-12-15 15:32:27 -0800496 ALOGV("deleteTrackName(%d)", name);
497 track_t& track(mState.tracks[ name ]);
Glenn Kasten4c340c62012-01-27 12:33:54 -0800498 if (track.enabled) {
499 track.enabled = false;
Glenn Kasten237a6242011-12-15 15:32:27 -0800500 invalidateState(1<<name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700501 }
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700502 // delete the resampler
503 delete track.resampler;
504 track.resampler = NULL;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700505 // delete the downmixer
506 unprepareTrackForDownmix(&mState.tracks[name], name);
Andy Hungef7c7fb2014-05-12 16:51:41 -0700507 // delete the reformatter
508 unprepareTrackForReformat(&mState.tracks[name], name);
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700509
Glenn Kasten237a6242011-12-15 15:32:27 -0800510 mTrackNames &= ~(1<<name);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800511}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700512
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800513void AudioMixer::enable(int name)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700514{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800515 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800516 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800517 track_t& track = mState.tracks[name];
518
Glenn Kasten4c340c62012-01-27 12:33:54 -0800519 if (!track.enabled) {
520 track.enabled = true;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800521 ALOGV("enable(%d)", name);
522 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700523 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700524}
525
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800526void AudioMixer::disable(int name)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700527{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800528 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800529 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800530 track_t& track = mState.tracks[name];
531
Glenn Kasten4c340c62012-01-27 12:33:54 -0800532 if (track.enabled) {
533 track.enabled = false;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800534 ALOGV("disable(%d)", name);
535 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700536 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700537}
538
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800539void AudioMixer::setParameter(int name, int target, int param, void *value)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700540{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800541 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800542 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800543 track_t& track = mState.tracks[name];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700544
Kévin PETIT377b2ec2014-02-03 12:35:36 +0000545 int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value));
546 int32_t *valueBuf = reinterpret_cast<int32_t*>(value);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700547
548 switch (target) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700549
Mathias Agopian65ab4712010-07-14 17:59:35 -0700550 case TRACK:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800551 switch (param) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700552 case CHANNEL_MASK: {
Kévin PETIT377b2ec2014-02-03 12:35:36 +0000553 audio_channel_mask_t mask =
554 static_cast<audio_channel_mask_t>(reinterpret_cast<uintptr_t>(value));
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800555 if (track.channelMask != mask) {
Andy Hunge5412692014-05-16 11:25:07 -0700556 uint32_t channelCount = audio_channel_count_from_out_mask(mask);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700557 ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800558 track.channelMask = mask;
559 track.channelCount = channelCount;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700560 // the mask has changed, does this track need a downmixer?
561 initTrackDownmix(&mState.tracks[name], name, mask);
Glenn Kasten788040c2011-05-05 08:19:00 -0700562 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800563 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700564 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700565 } break;
566 case MAIN_BUFFER:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800567 if (track.mainBuffer != valueBuf) {
568 track.mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100569 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800570 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700571 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700572 break;
573 case AUX_BUFFER:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800574 if (track.auxBuffer != valueBuf) {
575 track.auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100576 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800577 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700578 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700579 break;
Andy Hungef7c7fb2014-05-12 16:51:41 -0700580 case FORMAT: {
581 audio_format_t format = static_cast<audio_format_t>(valueInt);
582 if (track.mFormat != format) {
583 ALOG_ASSERT(audio_is_linear_pcm(format), "Invalid format %#x", format);
584 track.mFormat = format;
585 ALOGV("setParameter(TRACK, FORMAT, %#x)", format);
586 //if (track.mFormat != track.mMixerInFormat)
587 {
588 ALOGD("Reformatting!");
589 prepareTrackForReformat(&track, name);
590 }
591 invalidateState(1 << name);
592 }
593 } break;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700594 // FIXME do we want to support setting the downmix type from AudioFlinger?
595 // for a specific track? or per mixer?
596 /* case DOWNMIX_TYPE:
597 break */
Andy Hung78820702014-02-28 16:23:02 -0800598 case MIXER_FORMAT: {
Andy Hunga1ab7cc2014-02-24 19:26:52 -0800599 audio_format_t format = static_cast<audio_format_t>(valueInt);
Andy Hung78820702014-02-28 16:23:02 -0800600 if (track.mMixerFormat != format) {
601 track.mMixerFormat = format;
602 ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
Andy Hunga1ab7cc2014-02-24 19:26:52 -0800603 }
604 } break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700605 default:
Glenn Kastenadad3d72014-02-21 14:51:43 -0800606 LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700607 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700608 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700609
Mathias Agopian65ab4712010-07-14 17:59:35 -0700610 case RESAMPLE:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800611 switch (param) {
612 case SAMPLE_RATE:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800613 ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
Glenn Kasten788040c2011-05-05 08:19:00 -0700614 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
615 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
616 uint32_t(valueInt));
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800617 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700618 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800619 break;
620 case RESET:
Eric Laurent243f5f92011-02-28 16:52:51 -0800621 track.resetResampler();
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800622 invalidateState(1 << name);
623 break;
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700624 case REMOVE:
625 delete track.resampler;
626 track.resampler = NULL;
627 track.sampleRate = mSampleRate;
628 invalidateState(1 << name);
629 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700630 default:
Glenn Kastenadad3d72014-02-21 14:51:43 -0800631 LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
Eric Laurent243f5f92011-02-28 16:52:51 -0800632 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700633 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700634
Mathias Agopian65ab4712010-07-14 17:59:35 -0700635 case RAMP_VOLUME:
636 case VOLUME:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800637 switch (param) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700638 case VOLUME0:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800639 case VOLUME1:
640 if (track.volume[param-VOLUME0] != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100641 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800642 track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16;
643 track.volume[param-VOLUME0] = valueInt;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700644 if (target == VOLUME) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800645 track.prevVolume[param-VOLUME0] = valueInt << 16;
646 track.volumeInc[param-VOLUME0] = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700647 } else {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800648 int32_t d = (valueInt<<16) - track.prevVolume[param-VOLUME0];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700649 int32_t volInc = d / int32_t(mState.frameCount);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800650 track.volumeInc[param-VOLUME0] = volInc;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700651 if (volInc == 0) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800652 track.prevVolume[param-VOLUME0] = valueInt << 16;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700653 }
654 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800655 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700656 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800657 break;
658 case AUXLEVEL:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800659 //ALOG_ASSERT(0 <= valueInt && valueInt <= MAX_GAIN_INT, "bad aux level %d", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700660 if (track.auxLevel != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100661 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700662 track.prevAuxLevel = track.auxLevel << 16;
663 track.auxLevel = valueInt;
664 if (target == VOLUME) {
665 track.prevAuxLevel = valueInt << 16;
666 track.auxInc = 0;
667 } else {
668 int32_t d = (valueInt<<16) - track.prevAuxLevel;
669 int32_t volInc = d / int32_t(mState.frameCount);
670 track.auxInc = volInc;
671 if (volInc == 0) {
672 track.prevAuxLevel = valueInt << 16;
673 }
674 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800675 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700676 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800677 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700678 default:
Glenn Kastenadad3d72014-02-21 14:51:43 -0800679 LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700680 }
681 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700682
683 default:
Glenn Kastenadad3d72014-02-21 14:51:43 -0800684 LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700685 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700686}
687
688bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
689{
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700690 if (value != devSampleRate || resampler != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700691 if (sampleRate != value) {
692 sampleRate = value;
Glenn Kastene0feee32011-12-13 11:53:26 -0800693 if (resampler == NULL) {
Glenn Kastenac602052012-10-01 14:04:31 -0700694 ALOGV("creating resampler from track %d Hz to device %d Hz", value, devSampleRate);
695 AudioResampler::src_quality quality;
696 // force lowest quality level resampler if use case isn't music or video
697 // FIXME this is flawed for dynamic sample rates, as we choose the resampler
698 // quality level based on the initial ratio, but that could change later.
699 // Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
700 if (!((value == 44100 && devSampleRate == 48000) ||
701 (value == 48000 && devSampleRate == 44100))) {
Andy Hung9e0308c2014-01-30 14:32:31 -0800702 quality = AudioResampler::DYN_LOW_QUALITY;
Glenn Kastenac602052012-10-01 14:04:31 -0700703 } else {
704 quality = AudioResampler::DEFAULT_QUALITY;
705 }
Andy Hungef7c7fb2014-05-12 16:51:41 -0700706 const int bits = mMixerInFormat == AUDIO_FORMAT_PCM_16_BIT ? 16 : /* FLOAT */ 32;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700707 resampler = AudioResampler::create(
Andy Hungef7c7fb2014-05-12 16:51:41 -0700708 bits,
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -0700709 // the resampler sees the number of channels after the downmixer, if any
Glenn Kastenf551e992013-08-19 18:45:42 -0700710 (int) (downmixerBufferProvider != NULL ? MAX_NUM_CHANNELS : channelCount),
Glenn Kastenac602052012-10-01 14:04:31 -0700711 devSampleRate, quality);
Glenn Kasten52008f82012-03-18 09:34:41 -0700712 resampler->setLocalTimeFreq(sLocalTimeFreq);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700713 }
714 return true;
715 }
716 }
717 return false;
718}
719
Mathias Agopian65ab4712010-07-14 17:59:35 -0700720inline
721void AudioMixer::track_t::adjustVolumeRamp(bool aux)
722{
Glenn Kastenf9a27772012-01-06 07:47:26 -0800723 for (uint32_t i=0 ; i<MAX_NUM_CHANNELS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700724 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
725 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
726 volumeInc[i] = 0;
727 prevVolume[i] = volume[i]<<16;
728 }
729 }
730 if (aux) {
731 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
732 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
733 auxInc = 0;
734 prevAuxLevel = auxLevel<<16;
735 }
736 }
737}
738
Glenn Kastenc59c0042012-02-02 14:06:11 -0800739size_t AudioMixer::getUnreleasedFrames(int name) const
Eric Laurent071ccd52011-12-22 16:08:41 -0800740{
741 name -= TRACK0;
742 if (uint32_t(name) < MAX_NUM_TRACKS) {
Glenn Kastenc59c0042012-02-02 14:06:11 -0800743 return mState.tracks[name].getUnreleasedFrames();
Eric Laurent071ccd52011-12-22 16:08:41 -0800744 }
745 return 0;
746}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700747
Glenn Kasten01c4ebf2012-02-22 10:47:35 -0800748void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700749{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800750 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800751 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700752
Andy Hung1d26ddf2014-05-29 15:53:09 -0700753 if (mState.tracks[name].mInputBufferProvider == bufferProvider) {
754 return; // don't reset any buffer providers if identical.
755 }
Andy Hungef7c7fb2014-05-12 16:51:41 -0700756 if (mState.tracks[name].mReformatBufferProvider != NULL) {
757 mState.tracks[name].mReformatBufferProvider->reset();
758 } else if (mState.tracks[name].downmixerBufferProvider != NULL) {
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700759 }
Andy Hungef7c7fb2014-05-12 16:51:41 -0700760
761 mState.tracks[name].mInputBufferProvider = bufferProvider;
762 reconfigureBufferProviders(&mState.tracks[name]);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700763}
764
765
John Grossman4ff14ba2012-02-08 16:37:41 -0800766void AudioMixer::process(int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700767{
John Grossman4ff14ba2012-02-08 16:37:41 -0800768 mState.hook(&mState, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700769}
770
771
John Grossman4ff14ba2012-02-08 16:37:41 -0800772void AudioMixer::process__validate(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700773{
Steve Block5ff1dd52012-01-05 23:22:43 +0000774 ALOGW_IF(!state->needsChanged,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700775 "in process__validate() but nothing's invalid");
776
777 uint32_t changed = state->needsChanged;
778 state->needsChanged = 0; // clear the validation flag
779
780 // recompute which tracks are enabled / disabled
781 uint32_t enabled = 0;
782 uint32_t disabled = 0;
783 while (changed) {
784 const int i = 31 - __builtin_clz(changed);
785 const uint32_t mask = 1<<i;
786 changed &= ~mask;
787 track_t& t = state->tracks[i];
788 (t.enabled ? enabled : disabled) |= mask;
789 }
790 state->enabledTracks &= ~disabled;
791 state->enabledTracks |= enabled;
792
793 // compute everything we need...
794 int countActiveTracks = 0;
Glenn Kasten4c340c62012-01-27 12:33:54 -0800795 bool all16BitsStereoNoResample = true;
796 bool resampling = false;
797 bool volumeRamp = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700798 uint32_t en = state->enabledTracks;
799 while (en) {
800 const int i = 31 - __builtin_clz(en);
801 en &= ~(1<<i);
802
803 countActiveTracks++;
804 track_t& t = state->tracks[i];
805 uint32_t n = 0;
Glenn Kastend6fadf02013-10-30 14:37:29 -0700806 // FIXME can overflow (mask is only 3 bits)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700807 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
Glenn Kastend6fadf02013-10-30 14:37:29 -0700808 if (t.doesResample()) {
809 n |= NEEDS_RESAMPLE;
810 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700811 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
Glenn Kastend6fadf02013-10-30 14:37:29 -0700812 n |= NEEDS_AUX;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700813 }
814
815 if (t.volumeInc[0]|t.volumeInc[1]) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800816 volumeRamp = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700817 } else if (!t.doesResample() && t.volumeRL == 0) {
Glenn Kastend6fadf02013-10-30 14:37:29 -0700818 n |= NEEDS_MUTE;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700819 }
820 t.needs = n;
821
Glenn Kastend6fadf02013-10-30 14:37:29 -0700822 if (n & NEEDS_MUTE) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700823 t.hook = track__nop;
824 } else {
Glenn Kastend6fadf02013-10-30 14:37:29 -0700825 if (n & NEEDS_AUX) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800826 all16BitsStereoNoResample = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700827 }
Glenn Kastend6fadf02013-10-30 14:37:29 -0700828 if (n & NEEDS_RESAMPLE) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800829 all16BitsStereoNoResample = false;
830 resampling = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700831 t.hook = track__genericResample;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700832 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700833 "Track %d needs downmix + resample", i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700834 } else {
835 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
836 t.hook = track__16BitsMono;
Glenn Kasten4c340c62012-01-27 12:33:54 -0800837 all16BitsStereoNoResample = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700838 }
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700839 if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
Mathias Agopian65ab4712010-07-14 17:59:35 -0700840 t.hook = track__16BitsStereo;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700841 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700842 "Track %d needs downmix", i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700843 }
844 }
845 }
846 }
847
848 // select the processing hooks
849 state->hook = process__nop;
Glenn Kasten34fca342013-08-13 09:48:14 -0700850 if (countActiveTracks > 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700851 if (resampling) {
852 if (!state->outputTemp) {
853 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
854 }
855 if (!state->resampleTemp) {
856 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
857 }
858 state->hook = process__genericResampling;
859 } else {
860 if (state->outputTemp) {
861 delete [] state->outputTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800862 state->outputTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700863 }
864 if (state->resampleTemp) {
865 delete [] state->resampleTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800866 state->resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700867 }
868 state->hook = process__genericNoResampling;
869 if (all16BitsStereoNoResample && !volumeRamp) {
870 if (countActiveTracks == 1) {
871 state->hook = process__OneTrack16BitsStereoNoResampling;
872 }
873 }
874 }
875 }
876
Steve Block3856b092011-10-20 11:56:00 +0100877 ALOGV("mixer configuration change: %d activeTracks (%08x) "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700878 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
879 countActiveTracks, state->enabledTracks,
880 all16BitsStereoNoResample, resampling, volumeRamp);
881
John Grossman4ff14ba2012-02-08 16:37:41 -0800882 state->hook(state, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700883
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800884 // Now that the volume ramp has been done, set optimal state and
885 // track hooks for subsequent mixer process
Glenn Kasten34fca342013-08-13 09:48:14 -0700886 if (countActiveTracks > 0) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800887 bool allMuted = true;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800888 uint32_t en = state->enabledTracks;
889 while (en) {
890 const int i = 31 - __builtin_clz(en);
891 en &= ~(1<<i);
892 track_t& t = state->tracks[i];
Glenn Kasten6e2ebe92013-08-13 09:14:51 -0700893 if (!t.doesResample() && t.volumeRL == 0) {
Glenn Kastend6fadf02013-10-30 14:37:29 -0700894 t.needs |= NEEDS_MUTE;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800895 t.hook = track__nop;
896 } else {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800897 allMuted = false;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800898 }
899 }
900 if (allMuted) {
901 state->hook = process__nop;
902 } else if (all16BitsStereoNoResample) {
903 if (countActiveTracks == 1) {
904 state->hook = process__OneTrack16BitsStereoNoResampling;
905 }
906 }
907 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700908}
909
Mathias Agopian65ab4712010-07-14 17:59:35 -0700910
Glenn Kasten85ab62c2012-11-01 11:11:38 -0700911void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount,
912 int32_t* temp, int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700913{
914 t->resampler->setSampleRate(t->sampleRate);
915
916 // ramp gain - resample to temp buffer and scale/mix in 2nd step
917 if (aux != NULL) {
918 // always resample with unity gain when sending to auxiliary buffer to be able
919 // to apply send level after resampling
920 // TODO: modify each resampler to support aux channel?
921 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
922 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
923 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Glenn Kastenf6b16782011-12-15 09:51:17 -0800924 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700925 volumeRampStereo(t, out, outFrameCount, temp, aux);
926 } else {
927 volumeStereo(t, out, outFrameCount, temp, aux);
928 }
929 } else {
Glenn Kastenf6b16782011-12-15 09:51:17 -0800930 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700931 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
932 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
933 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
934 volumeRampStereo(t, out, outFrameCount, temp, aux);
935 }
936
937 // constant gain
938 else {
939 t->resampler->setVolume(t->volume[0], t->volume[1]);
940 t->resampler->resample(out, outFrameCount, t->bufferProvider);
941 }
942 }
943}
944
Andy Hungee931ff2014-01-28 13:44:14 -0800945void AudioMixer::track__nop(track_t* t __unused, int32_t* out __unused,
946 size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700947{
948}
949
Glenn Kasten85ab62c2012-11-01 11:11:38 -0700950void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp,
951 int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700952{
953 int32_t vl = t->prevVolume[0];
954 int32_t vr = t->prevVolume[1];
955 const int32_t vlInc = t->volumeInc[0];
956 const int32_t vrInc = t->volumeInc[1];
957
Steve Blockb8a80522011-12-20 16:23:08 +0000958 //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700959 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
960 // (vl + vlInc*frameCount)/65536.0f, frameCount);
961
962 // ramp volume
Glenn Kastenf6b16782011-12-15 09:51:17 -0800963 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700964 int32_t va = t->prevAuxLevel;
965 const int32_t vaInc = t->auxInc;
966 int32_t l;
967 int32_t r;
968
969 do {
970 l = (*temp++ >> 12);
971 r = (*temp++ >> 12);
972 *out++ += (vl >> 16) * l;
973 *out++ += (vr >> 16) * r;
974 *aux++ += (va >> 17) * (l + r);
975 vl += vlInc;
976 vr += vrInc;
977 va += vaInc;
978 } while (--frameCount);
979 t->prevAuxLevel = va;
980 } else {
981 do {
982 *out++ += (vl >> 16) * (*temp++ >> 12);
983 *out++ += (vr >> 16) * (*temp++ >> 12);
984 vl += vlInc;
985 vr += vrInc;
986 } while (--frameCount);
987 }
988 t->prevVolume[0] = vl;
989 t->prevVolume[1] = vr;
Glenn Kastena1117922012-01-26 10:53:32 -0800990 t->adjustVolumeRamp(aux != NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700991}
992
Glenn Kasten85ab62c2012-11-01 11:11:38 -0700993void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp,
994 int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700995{
996 const int16_t vl = t->volume[0];
997 const int16_t vr = t->volume[1];
998
Glenn Kastenf6b16782011-12-15 09:51:17 -0800999 if (CC_UNLIKELY(aux != NULL)) {
Glenn Kasten3b81aca2012-01-27 15:26:23 -08001000 const int16_t va = t->auxLevel;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001001 do {
1002 int16_t l = (int16_t)(*temp++ >> 12);
1003 int16_t r = (int16_t)(*temp++ >> 12);
1004 out[0] = mulAdd(l, vl, out[0]);
1005 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
1006 out[1] = mulAdd(r, vr, out[1]);
1007 out += 2;
1008 aux[0] = mulAdd(a, va, aux[0]);
1009 aux++;
1010 } while (--frameCount);
1011 } else {
1012 do {
1013 int16_t l = (int16_t)(*temp++ >> 12);
1014 int16_t r = (int16_t)(*temp++ >> 12);
1015 out[0] = mulAdd(l, vl, out[0]);
1016 out[1] = mulAdd(r, vr, out[1]);
1017 out += 2;
1018 } while (--frameCount);
1019 }
1020}
1021
Andy Hungee931ff2014-01-28 13:44:14 -08001022void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount,
1023 int32_t* temp __unused, int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001024{
Glenn Kasten54c3b662012-01-06 07:46:30 -08001025 const int16_t *in = static_cast<const int16_t *>(t->in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001026
Glenn Kastenf6b16782011-12-15 09:51:17 -08001027 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001028 int32_t l;
1029 int32_t r;
1030 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -08001031 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001032 int32_t vl = t->prevVolume[0];
1033 int32_t vr = t->prevVolume[1];
1034 int32_t va = t->prevAuxLevel;
1035 const int32_t vlInc = t->volumeInc[0];
1036 const int32_t vrInc = t->volumeInc[1];
1037 const int32_t vaInc = t->auxInc;
Steve Blockb8a80522011-12-20 16:23:08 +00001038 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07001039 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1040 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1041
1042 do {
1043 l = (int32_t)*in++;
1044 r = (int32_t)*in++;
1045 *out++ += (vl >> 16) * l;
1046 *out++ += (vr >> 16) * r;
1047 *aux++ += (va >> 17) * (l + r);
1048 vl += vlInc;
1049 vr += vrInc;
1050 va += vaInc;
1051 } while (--frameCount);
1052
1053 t->prevVolume[0] = vl;
1054 t->prevVolume[1] = vr;
1055 t->prevAuxLevel = va;
1056 t->adjustVolumeRamp(true);
1057 }
1058
1059 // constant gain
1060 else {
1061 const uint32_t vrl = t->volumeRL;
1062 const int16_t va = (int16_t)t->auxLevel;
1063 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001064 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001065 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
1066 in += 2;
1067 out[0] = mulAddRL(1, rl, vrl, out[0]);
1068 out[1] = mulAddRL(0, rl, vrl, out[1]);
1069 out += 2;
1070 aux[0] = mulAdd(a, va, aux[0]);
1071 aux++;
1072 } while (--frameCount);
1073 }
1074 } else {
1075 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -08001076 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001077 int32_t vl = t->prevVolume[0];
1078 int32_t vr = t->prevVolume[1];
1079 const int32_t vlInc = t->volumeInc[0];
1080 const int32_t vrInc = t->volumeInc[1];
1081
Steve Blockb8a80522011-12-20 16:23:08 +00001082 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07001083 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1084 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1085
1086 do {
1087 *out++ += (vl >> 16) * (int32_t) *in++;
1088 *out++ += (vr >> 16) * (int32_t) *in++;
1089 vl += vlInc;
1090 vr += vrInc;
1091 } while (--frameCount);
1092
1093 t->prevVolume[0] = vl;
1094 t->prevVolume[1] = vr;
1095 t->adjustVolumeRamp(false);
1096 }
1097
1098 // constant gain
1099 else {
1100 const uint32_t vrl = t->volumeRL;
1101 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001102 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001103 in += 2;
1104 out[0] = mulAddRL(1, rl, vrl, out[0]);
1105 out[1] = mulAddRL(0, rl, vrl, out[1]);
1106 out += 2;
1107 } while (--frameCount);
1108 }
1109 }
1110 t->in = in;
1111}
1112
Andy Hungee931ff2014-01-28 13:44:14 -08001113void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount,
1114 int32_t* temp __unused, int32_t* aux)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001115{
Glenn Kasten54c3b662012-01-06 07:46:30 -08001116 const int16_t *in = static_cast<int16_t const *>(t->in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001117
Glenn Kastenf6b16782011-12-15 09:51:17 -08001118 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001119 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -08001120 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001121 int32_t vl = t->prevVolume[0];
1122 int32_t vr = t->prevVolume[1];
1123 int32_t va = t->prevAuxLevel;
1124 const int32_t vlInc = t->volumeInc[0];
1125 const int32_t vrInc = t->volumeInc[1];
1126 const int32_t vaInc = t->auxInc;
1127
Steve Blockb8a80522011-12-20 16:23:08 +00001128 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07001129 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1130 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1131
1132 do {
1133 int32_t l = *in++;
1134 *out++ += (vl >> 16) * l;
1135 *out++ += (vr >> 16) * l;
1136 *aux++ += (va >> 16) * l;
1137 vl += vlInc;
1138 vr += vrInc;
1139 va += vaInc;
1140 } while (--frameCount);
1141
1142 t->prevVolume[0] = vl;
1143 t->prevVolume[1] = vr;
1144 t->prevAuxLevel = va;
1145 t->adjustVolumeRamp(true);
1146 }
1147 // constant gain
1148 else {
1149 const int16_t vl = t->volume[0];
1150 const int16_t vr = t->volume[1];
1151 const int16_t va = (int16_t)t->auxLevel;
1152 do {
1153 int16_t l = *in++;
1154 out[0] = mulAdd(l, vl, out[0]);
1155 out[1] = mulAdd(l, vr, out[1]);
1156 out += 2;
1157 aux[0] = mulAdd(l, va, aux[0]);
1158 aux++;
1159 } while (--frameCount);
1160 }
1161 } else {
1162 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -08001163 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001164 int32_t vl = t->prevVolume[0];
1165 int32_t vr = t->prevVolume[1];
1166 const int32_t vlInc = t->volumeInc[0];
1167 const int32_t vrInc = t->volumeInc[1];
1168
Steve Blockb8a80522011-12-20 16:23:08 +00001169 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -07001170 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1171 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1172
1173 do {
1174 int32_t l = *in++;
1175 *out++ += (vl >> 16) * l;
1176 *out++ += (vr >> 16) * l;
1177 vl += vlInc;
1178 vr += vrInc;
1179 } while (--frameCount);
1180
1181 t->prevVolume[0] = vl;
1182 t->prevVolume[1] = vr;
1183 t->adjustVolumeRamp(false);
1184 }
1185 // constant gain
1186 else {
1187 const int16_t vl = t->volume[0];
1188 const int16_t vr = t->volume[1];
1189 do {
1190 int16_t l = *in++;
1191 out[0] = mulAdd(l, vl, out[0]);
1192 out[1] = mulAdd(l, vr, out[1]);
1193 out += 2;
1194 } while (--frameCount);
1195 }
1196 }
1197 t->in = in;
1198}
1199
Mathias Agopian65ab4712010-07-14 17:59:35 -07001200// no-op case
John Grossman4ff14ba2012-02-08 16:37:41 -08001201void AudioMixer::process__nop(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001202{
1203 uint32_t e0 = state->enabledTracks;
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001204 size_t sampleCount = state->frameCount * MAX_NUM_CHANNELS;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001205 while (e0) {
1206 // process by group of tracks with same output buffer to
1207 // avoid multiple memset() on same buffer
1208 uint32_t e1 = e0, e2 = e0;
1209 int i = 31 - __builtin_clz(e1);
Glenn Kastenfc900c92013-02-18 12:47:49 -08001210 {
1211 track_t& t1 = state->tracks[i];
Mathias Agopian65ab4712010-07-14 17:59:35 -07001212 e2 &= ~(1<<i);
Glenn Kastenfc900c92013-02-18 12:47:49 -08001213 while (e2) {
1214 i = 31 - __builtin_clz(e2);
1215 e2 &= ~(1<<i);
1216 track_t& t2 = state->tracks[i];
1217 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
1218 e1 &= ~(1<<i);
1219 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001220 }
Glenn Kastenfc900c92013-02-18 12:47:49 -08001221 e0 &= ~(e1);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001222
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001223 memset(t1.mainBuffer, 0, sampleCount
Andy Hung78820702014-02-28 16:23:02 -08001224 * audio_bytes_per_sample(t1.mMixerFormat));
Glenn Kastenfc900c92013-02-18 12:47:49 -08001225 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001226
1227 while (e1) {
1228 i = 31 - __builtin_clz(e1);
1229 e1 &= ~(1<<i);
Glenn Kastenfc900c92013-02-18 12:47:49 -08001230 {
1231 track_t& t3 = state->tracks[i];
1232 size_t outFrames = state->frameCount;
1233 while (outFrames) {
1234 t3.buffer.frameCount = outFrames;
1235 int64_t outputPTS = calculateOutputPTS(
1236 t3, pts, state->frameCount - outFrames);
1237 t3.bufferProvider->getNextBuffer(&t3.buffer, outputPTS);
1238 if (t3.buffer.raw == NULL) break;
1239 outFrames -= t3.buffer.frameCount;
1240 t3.bufferProvider->releaseBuffer(&t3.buffer);
1241 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001242 }
1243 }
1244 }
1245}
1246
1247// generic code without resampling
John Grossman4ff14ba2012-02-08 16:37:41 -08001248void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001249{
1250 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
1251
1252 // acquire each track's buffer
1253 uint32_t enabledTracks = state->enabledTracks;
1254 uint32_t e0 = enabledTracks;
1255 while (e0) {
1256 const int i = 31 - __builtin_clz(e0);
1257 e0 &= ~(1<<i);
1258 track_t& t = state->tracks[i];
1259 t.buffer.frameCount = state->frameCount;
John Grossman4ff14ba2012-02-08 16:37:41 -08001260 t.bufferProvider->getNextBuffer(&t.buffer, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001261 t.frameCount = t.buffer.frameCount;
1262 t.in = t.buffer.raw;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001263 }
1264
1265 e0 = enabledTracks;
1266 while (e0) {
1267 // process by group of tracks with same output buffer to
1268 // optimize cache use
1269 uint32_t e1 = e0, e2 = e0;
1270 int j = 31 - __builtin_clz(e1);
1271 track_t& t1 = state->tracks[j];
1272 e2 &= ~(1<<j);
1273 while (e2) {
1274 j = 31 - __builtin_clz(e2);
1275 e2 &= ~(1<<j);
1276 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -08001277 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001278 e1 &= ~(1<<j);
1279 }
1280 }
1281 e0 &= ~(e1);
1282 // this assumes output 16 bits stereo, no resampling
1283 int32_t *out = t1.mainBuffer;
1284 size_t numFrames = 0;
1285 do {
1286 memset(outTemp, 0, sizeof(outTemp));
1287 e2 = e1;
1288 while (e2) {
1289 const int i = 31 - __builtin_clz(e2);
1290 e2 &= ~(1<<i);
1291 track_t& t = state->tracks[i];
1292 size_t outFrames = BLOCKSIZE;
1293 int32_t *aux = NULL;
Glenn Kastend6fadf02013-10-30 14:37:29 -07001294 if (CC_UNLIKELY(t.needs & NEEDS_AUX)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001295 aux = t.auxBuffer + numFrames;
1296 }
1297 while (outFrames) {
Gaurav Kumar7e79cd22014-01-06 10:57:18 +05301298 // t.in == NULL can happen if the track was flushed just after having
1299 // been enabled for mixing.
1300 if (t.in == NULL) {
1301 enabledTracks &= ~(1<<i);
1302 e1 &= ~(1<<i);
1303 break;
1304 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001305 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
Glenn Kasten34fca342013-08-13 09:48:14 -07001306 if (inFrames > 0) {
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001307 t.hook(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames,
1308 state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001309 t.frameCount -= inFrames;
1310 outFrames -= inFrames;
Glenn Kastenf6b16782011-12-15 09:51:17 -08001311 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001312 aux += inFrames;
1313 }
1314 }
1315 if (t.frameCount == 0 && outFrames) {
1316 t.bufferProvider->releaseBuffer(&t.buffer);
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001317 t.buffer.frameCount = (state->frameCount - numFrames) -
1318 (BLOCKSIZE - outFrames);
John Grossman4ff14ba2012-02-08 16:37:41 -08001319 int64_t outputPTS = calculateOutputPTS(
1320 t, pts, numFrames + (BLOCKSIZE - outFrames));
1321 t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001322 t.in = t.buffer.raw;
1323 if (t.in == NULL) {
1324 enabledTracks &= ~(1<<i);
1325 e1 &= ~(1<<i);
1326 break;
1327 }
1328 t.frameCount = t.buffer.frameCount;
1329 }
1330 }
1331 }
Andy Hung78820702014-02-28 16:23:02 -08001332 switch (t1.mMixerFormat) {
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001333 case AUDIO_FORMAT_PCM_FLOAT:
Andy Hung84a0c6e2014-04-02 11:24:53 -07001334 memcpy_to_float_from_q4_27(reinterpret_cast<float *>(out), outTemp, BLOCKSIZE * 2);
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001335 out += BLOCKSIZE * 2; // output is 2 floats/frame.
1336 break;
1337 case AUDIO_FORMAT_PCM_16_BIT:
1338 ditherAndClamp(out, outTemp, BLOCKSIZE);
1339 out += BLOCKSIZE; // output is 1 int32_t (2 int16_t samples)/frame
1340 break;
1341 default:
Andy Hung78820702014-02-28 16:23:02 -08001342 LOG_ALWAYS_FATAL("bad mixer format: %d", t1.mMixerFormat);
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001343 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001344 numFrames += BLOCKSIZE;
1345 } while (numFrames < state->frameCount);
1346 }
1347
1348 // release each track's buffer
1349 e0 = enabledTracks;
1350 while (e0) {
1351 const int i = 31 - __builtin_clz(e0);
1352 e0 &= ~(1<<i);
1353 track_t& t = state->tracks[i];
1354 t.bufferProvider->releaseBuffer(&t.buffer);
1355 }
1356}
1357
1358
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001359// generic code with resampling
John Grossman4ff14ba2012-02-08 16:37:41 -08001360void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001361{
Glenn Kasten54c3b662012-01-06 07:46:30 -08001362 // this const just means that local variable outTemp doesn't change
Mathias Agopian65ab4712010-07-14 17:59:35 -07001363 int32_t* const outTemp = state->outputTemp;
1364 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001365
1366 size_t numFrames = state->frameCount;
1367
1368 uint32_t e0 = state->enabledTracks;
1369 while (e0) {
1370 // process by group of tracks with same output buffer
1371 // to optimize cache use
1372 uint32_t e1 = e0, e2 = e0;
1373 int j = 31 - __builtin_clz(e1);
1374 track_t& t1 = state->tracks[j];
1375 e2 &= ~(1<<j);
1376 while (e2) {
1377 j = 31 - __builtin_clz(e2);
1378 e2 &= ~(1<<j);
1379 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -08001380 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001381 e1 &= ~(1<<j);
1382 }
1383 }
1384 e0 &= ~(e1);
1385 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi2151d7b2011-02-04 15:24:34 +01001386 memset(outTemp, 0, size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001387 while (e1) {
1388 const int i = 31 - __builtin_clz(e1);
1389 e1 &= ~(1<<i);
1390 track_t& t = state->tracks[i];
1391 int32_t *aux = NULL;
Glenn Kastend6fadf02013-10-30 14:37:29 -07001392 if (CC_UNLIKELY(t.needs & NEEDS_AUX)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001393 aux = t.auxBuffer;
1394 }
1395
1396 // this is a little goofy, on the resampling case we don't
1397 // acquire/release the buffers because it's done by
1398 // the resampler.
Glenn Kastend6fadf02013-10-30 14:37:29 -07001399 if (t.needs & NEEDS_RESAMPLE) {
John Grossman4ff14ba2012-02-08 16:37:41 -08001400 t.resampler->setPTS(pts);
Glenn Kastena1117922012-01-26 10:53:32 -08001401 t.hook(&t, outTemp, numFrames, state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001402 } else {
1403
1404 size_t outFrames = 0;
1405
1406 while (outFrames < numFrames) {
1407 t.buffer.frameCount = numFrames - outFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001408 int64_t outputPTS = calculateOutputPTS(t, pts, outFrames);
1409 t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001410 t.in = t.buffer.raw;
1411 // t.in == NULL can happen if the track was flushed just after having
1412 // been enabled for mixing.
1413 if (t.in == NULL) break;
1414
Glenn Kastenf6b16782011-12-15 09:51:17 -08001415 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001416 aux += outFrames;
1417 }
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001418 t.hook(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount,
1419 state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001420 outFrames += t.buffer.frameCount;
1421 t.bufferProvider->releaseBuffer(&t.buffer);
1422 }
1423 }
1424 }
Andy Hung78820702014-02-28 16:23:02 -08001425 switch (t1.mMixerFormat) {
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001426 case AUDIO_FORMAT_PCM_FLOAT:
Andy Hung84a0c6e2014-04-02 11:24:53 -07001427 memcpy_to_float_from_q4_27(reinterpret_cast<float*>(out), outTemp, numFrames*2);
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001428 break;
1429 case AUDIO_FORMAT_PCM_16_BIT:
1430 ditherAndClamp(out, outTemp, numFrames);
1431 break;
1432 default:
Andy Hung78820702014-02-28 16:23:02 -08001433 LOG_ALWAYS_FATAL("bad mixer format: %d", t1.mMixerFormat);
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001434 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001435 }
1436}
1437
1438// one track, 16 bits stereo without resampling is the most common case
John Grossman4ff14ba2012-02-08 16:37:41 -08001439void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state,
1440 int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001441{
Glenn Kasten99e53b82012-01-19 08:59:58 -08001442 // This method is only called when state->enabledTracks has exactly
1443 // one bit set. The asserts below would verify this, but are commented out
1444 // since the whole point of this method is to optimize performance.
Glenn Kasten5798d4e2012-03-08 12:18:35 -08001445 //ALOG_ASSERT(0 != state->enabledTracks, "no tracks enabled");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001446 const int i = 31 - __builtin_clz(state->enabledTracks);
Glenn Kasten5798d4e2012-03-08 12:18:35 -08001447 //ALOG_ASSERT((1 << i) == state->enabledTracks, "more than 1 track enabled");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001448 const track_t& t = state->tracks[i];
1449
1450 AudioBufferProvider::Buffer& b(t.buffer);
1451
1452 int32_t* out = t.mainBuffer;
Andy Hungf8a106a2014-05-29 18:52:38 -07001453 float *fout = reinterpret_cast<float*>(out);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001454 size_t numFrames = state->frameCount;
1455
1456 const int16_t vl = t.volume[0];
1457 const int16_t vr = t.volume[1];
1458 const uint32_t vrl = t.volumeRL;
1459 while (numFrames) {
1460 b.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001461 int64_t outputPTS = calculateOutputPTS(t, pts, out - t.mainBuffer);
1462 t.bufferProvider->getNextBuffer(&b, outputPTS);
Glenn Kasten54c3b662012-01-06 07:46:30 -08001463 const int16_t *in = b.i16;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001464
1465 // in == NULL can happen if the track was flushed just after having
1466 // been enabled for mixing.
Andy Hungf8a106a2014-05-29 18:52:38 -07001467 if (in == NULL || (((uintptr_t)in) & 3)) {
1468 memset(out, 0, numFrames
1469 * MAX_NUM_CHANNELS * audio_bytes_per_sample(t.mMixerFormat));
1470 ALOGE_IF((((uintptr_t)in) & 3), "process stereo track: input buffer alignment pb: "
Glenn Kasten85ab62c2012-11-01 11:11:38 -07001471 "buffer %p track %d, channels %d, needs %08x",
Mathias Agopian65ab4712010-07-14 17:59:35 -07001472 in, i, t.channelCount, t.needs);
1473 return;
1474 }
1475 size_t outFrames = b.frameCount;
1476
Andy Hung78820702014-02-28 16:23:02 -08001477 switch (t.mMixerFormat) {
Andy Hungf8a106a2014-05-29 18:52:38 -07001478 case AUDIO_FORMAT_PCM_FLOAT:
Mathias Agopian65ab4712010-07-14 17:59:35 -07001479 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001480 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001481 in += 2;
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001482 int32_t l = mulRL(1, rl, vrl);
1483 int32_t r = mulRL(0, rl, vrl);
Andy Hung84a0c6e2014-04-02 11:24:53 -07001484 *fout++ = float_from_q4_27(l);
1485 *fout++ = float_from_q4_27(r);
Andy Hung3375bde2014-02-28 15:51:47 -08001486 // Note: In case of later int16_t sink output,
1487 // conversion and clamping is done by memcpy_to_i16_from_float().
Mathias Agopian65ab4712010-07-14 17:59:35 -07001488 } while (--outFrames);
Andy Hungf8a106a2014-05-29 18:52:38 -07001489 break;
Andy Hunga1ab7cc2014-02-24 19:26:52 -08001490 case AUDIO_FORMAT_PCM_16_BIT:
1491 if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
1492 // volume is boosted, so we might need to clamp even though
1493 // we process only one track.
1494 do {
1495 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1496 in += 2;
1497 int32_t l = mulRL(1, rl, vrl) >> 12;
1498 int32_t r = mulRL(0, rl, vrl) >> 12;
1499 // clamping...
1500 l = clamp16(l);
1501 r = clamp16(r);
1502 *out++ = (r<<16) | (l & 0xFFFF);
1503 } while (--outFrames);
1504 } else {
1505 do {
1506 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1507 in += 2;
1508 int32_t l = mulRL(1, rl, vrl) >> 12;
1509 int32_t r = mulRL(0, rl, vrl) >> 12;
1510 *out++ = (r<<16) | (l & 0xFFFF);
1511 } while (--outFrames);
1512 }
1513 break;
1514 default:
Andy Hung78820702014-02-28 16:23:02 -08001515 LOG_ALWAYS_FATAL("bad mixer format: %d", t.mMixerFormat);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001516 }
1517 numFrames -= b.frameCount;
1518 t.bufferProvider->releaseBuffer(&b);
1519 }
1520}
1521
Glenn Kasten81a028f2011-12-15 09:53:12 -08001522#if 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07001523// 2 tracks is also a common case
1524// NEVER used in current implementation of process__validate()
1525// only use if the 2 tracks have the same output buffer
John Grossman4ff14ba2012-02-08 16:37:41 -08001526void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state,
1527 int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001528{
1529 int i;
1530 uint32_t en = state->enabledTracks;
1531
1532 i = 31 - __builtin_clz(en);
1533 const track_t& t0 = state->tracks[i];
1534 AudioBufferProvider::Buffer& b0(t0.buffer);
1535
1536 en &= ~(1<<i);
1537 i = 31 - __builtin_clz(en);
1538 const track_t& t1 = state->tracks[i];
1539 AudioBufferProvider::Buffer& b1(t1.buffer);
1540
Glenn Kasten54c3b662012-01-06 07:46:30 -08001541 const int16_t *in0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001542 const int16_t vl0 = t0.volume[0];
1543 const int16_t vr0 = t0.volume[1];
1544 size_t frameCount0 = 0;
1545
Glenn Kasten54c3b662012-01-06 07:46:30 -08001546 const int16_t *in1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001547 const int16_t vl1 = t1.volume[0];
1548 const int16_t vr1 = t1.volume[1];
1549 size_t frameCount1 = 0;
1550
1551 //FIXME: only works if two tracks use same buffer
1552 int32_t* out = t0.mainBuffer;
1553 size_t numFrames = state->frameCount;
Glenn Kasten54c3b662012-01-06 07:46:30 -08001554 const int16_t *buff = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001555
1556
1557 while (numFrames) {
1558
1559 if (frameCount0 == 0) {
1560 b0.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001561 int64_t outputPTS = calculateOutputPTS(t0, pts,
1562 out - t0.mainBuffer);
1563 t0.bufferProvider->getNextBuffer(&b0, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001564 if (b0.i16 == NULL) {
1565 if (buff == NULL) {
1566 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1567 }
1568 in0 = buff;
1569 b0.frameCount = numFrames;
1570 } else {
1571 in0 = b0.i16;
1572 }
1573 frameCount0 = b0.frameCount;
1574 }
1575 if (frameCount1 == 0) {
1576 b1.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001577 int64_t outputPTS = calculateOutputPTS(t1, pts,
1578 out - t0.mainBuffer);
1579 t1.bufferProvider->getNextBuffer(&b1, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001580 if (b1.i16 == NULL) {
1581 if (buff == NULL) {
1582 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1583 }
1584 in1 = buff;
1585 b1.frameCount = numFrames;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001586 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001587 in1 = b1.i16;
1588 }
1589 frameCount1 = b1.frameCount;
1590 }
1591
1592 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1593
1594 numFrames -= outFrames;
1595 frameCount0 -= outFrames;
1596 frameCount1 -= outFrames;
1597
1598 do {
1599 int32_t l0 = *in0++;
1600 int32_t r0 = *in0++;
1601 l0 = mul(l0, vl0);
1602 r0 = mul(r0, vr0);
1603 int32_t l = *in1++;
1604 int32_t r = *in1++;
1605 l = mulAdd(l, vl1, l0) >> 12;
1606 r = mulAdd(r, vr1, r0) >> 12;
1607 // clamping...
1608 l = clamp16(l);
1609 r = clamp16(r);
1610 *out++ = (r<<16) | (l & 0xFFFF);
1611 } while (--outFrames);
1612
1613 if (frameCount0 == 0) {
1614 t0.bufferProvider->releaseBuffer(&b0);
1615 }
1616 if (frameCount1 == 0) {
1617 t1.bufferProvider->releaseBuffer(&b1);
1618 }
1619 }
1620
Glenn Kastene9dd0172012-01-27 18:08:45 -08001621 delete [] buff;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001622}
Glenn Kasten81a028f2011-12-15 09:53:12 -08001623#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001624
John Grossman4ff14ba2012-02-08 16:37:41 -08001625int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS,
1626 int outputFrameIndex)
1627{
Glenn Kasten6e2ebe92013-08-13 09:14:51 -07001628 if (AudioBufferProvider::kInvalidPTS == basePTS) {
John Grossman4ff14ba2012-02-08 16:37:41 -08001629 return AudioBufferProvider::kInvalidPTS;
Glenn Kasten6e2ebe92013-08-13 09:14:51 -07001630 }
John Grossman4ff14ba2012-02-08 16:37:41 -08001631
Glenn Kasten52008f82012-03-18 09:34:41 -07001632 return basePTS + ((outputFrameIndex * sLocalTimeFreq) / t.sampleRate);
1633}
1634
1635/*static*/ uint64_t AudioMixer::sLocalTimeFreq;
1636/*static*/ pthread_once_t AudioMixer::sOnceControl = PTHREAD_ONCE_INIT;
1637
1638/*static*/ void AudioMixer::sInitRoutine()
1639{
1640 LocalClock lc;
1641 sLocalTimeFreq = lc.getLocalFreq();
Glenn Kasten49c34ac2013-10-30 14:37:01 -07001642
1643 // find multichannel downmix effect if we have to play multichannel content
1644 uint32_t numEffects = 0;
1645 int ret = EffectQueryNumberEffects(&numEffects);
1646 if (ret != 0) {
1647 ALOGE("AudioMixer() error %d querying number of effects", ret);
1648 return;
1649 }
1650 ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
1651
1652 for (uint32_t i = 0 ; i < numEffects ; i++) {
1653 if (EffectQueryEffect(i, &sDwnmFxDesc) == 0) {
1654 ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
1655 if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
1656 ALOGI("found effect \"%s\" from %s",
1657 sDwnmFxDesc.name, sDwnmFxDesc.implementor);
1658 sIsMultichannelCapable = true;
1659 break;
1660 }
1661 }
1662 }
1663 ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
John Grossman4ff14ba2012-02-08 16:37:41 -08001664}
1665
Mathias Agopian65ab4712010-07-14 17:59:35 -07001666// ----------------------------------------------------------------------------
1667}; // namespace android