blob: 3a8c54d5168bf74911868b1e6647a09cacf8800b [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"
19//#define LOG_NDEBUG 0
20
21#include <stdint.h>
22#include <string.h>
23#include <stdlib.h>
24#include <sys/types.h>
25
26#include <utils/Errors.h>
27#include <utils/Log.h>
28
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070029#include <cutils/bitops.h>
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>
John Grossman4ff14ba2012-02-08 16:37:41 -080036#include <common_time/local_clock.h>
37#include <common_time/cc_helper.h>
Glenn Kasten3b21c502011-12-15 09:52:39 -080038
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070039#include <media/EffectsFactoryApi.h>
40
Mathias Agopian65ab4712010-07-14 17:59:35 -070041#include "AudioMixer.h"
42
43namespace android {
Mathias Agopian65ab4712010-07-14 17:59:35 -070044
45// ----------------------------------------------------------------------------
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070046AudioMixer::DownmixerBufferProvider::DownmixerBufferProvider() : AudioBufferProvider(),
47 mTrackBufferProvider(NULL), mDownmixHandle(NULL)
48{
49}
50
51AudioMixer::DownmixerBufferProvider::~DownmixerBufferProvider()
52{
53 ALOGV("AudioMixer deleting DownmixerBufferProvider (%p)", this);
54 EffectRelease(mDownmixHandle);
55}
56
57status_t AudioMixer::DownmixerBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer,
58 int64_t pts) {
59 //ALOGV("DownmixerBufferProvider::getNextBuffer()");
60 if (this->mTrackBufferProvider != NULL) {
61 status_t res = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
62 if (res == OK) {
63 mDownmixConfig.inputCfg.buffer.frameCount = pBuffer->frameCount;
64 mDownmixConfig.inputCfg.buffer.raw = pBuffer->raw;
65 mDownmixConfig.outputCfg.buffer.frameCount = pBuffer->frameCount;
66 mDownmixConfig.outputCfg.buffer.raw = mDownmixConfig.inputCfg.buffer.raw;
67 // in-place so overwrite the buffer contents, has been set in prepareTrackForDownmix()
68 //mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
69
70 res = (*mDownmixHandle)->process(mDownmixHandle,
71 &mDownmixConfig.inputCfg.buffer, &mDownmixConfig.outputCfg.buffer);
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -070072 //ALOGV("getNextBuffer is downmixing");
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070073 }
74 return res;
75 } else {
76 ALOGE("DownmixerBufferProvider::getNextBuffer() error: NULL track buffer provider");
77 return NO_INIT;
78 }
79}
80
81void AudioMixer::DownmixerBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -070082 //ALOGV("DownmixerBufferProvider::releaseBuffer()");
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -070083 if (this->mTrackBufferProvider != NULL) {
84 mTrackBufferProvider->releaseBuffer(pBuffer);
85 } else {
86 ALOGE("DownmixerBufferProvider::releaseBuffer() error: NULL track buffer provider");
87 }
88}
89
90
91// ----------------------------------------------------------------------------
92bool AudioMixer::isMultichannelCapable = false;
93
94effect_descriptor_t AudioMixer::dwnmFxDesc;
Mathias Agopian65ab4712010-07-14 17:59:35 -070095
Glenn Kasten5c94b6c2012-03-20 17:01:29 -070096AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate, uint32_t maxNumTracks)
97 : mTrackNames(0), mConfiguredNames((1 << maxNumTracks) - 1), mSampleRate(sampleRate)
Mathias Agopian65ab4712010-07-14 17:59:35 -070098{
Glenn Kasten788040c2011-05-05 08:19:00 -070099 // AudioMixer is not yet capable of multi-channel beyond stereo
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800100 COMPILE_TIME_ASSERT_FUNCTION_SCOPE(2 == MAX_NUM_CHANNELS);
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -0700101
Glenn Kasten5c94b6c2012-03-20 17:01:29 -0700102 ALOG_ASSERT(maxNumTracks <= MAX_NUM_TRACKS, "maxNumTracks %u > MAX_NUM_TRACKS %u",
103 maxNumTracks, MAX_NUM_TRACKS);
104
John Grossman4ff14ba2012-02-08 16:37:41 -0800105 LocalClock lc;
106
Mathias Agopian65ab4712010-07-14 17:59:35 -0700107 mState.enabledTracks= 0;
108 mState.needsChanged = 0;
109 mState.frameCount = frameCount;
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800110 mState.hook = process__nop;
Glenn Kastene0feee32011-12-13 11:53:26 -0800111 mState.outputTemp = NULL;
112 mState.resampleTemp = NULL;
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800113 // mState.reserved
Glenn Kasten17a736c2012-02-14 08:52:15 -0800114
115 // FIXME Most of the following initialization is probably redundant since
116 // tracks[i] should only be referenced if (mTrackNames & (1 << i)) != 0
117 // and mTrackNames is initially 0. However, leave it here until that's verified.
Mathias Agopian65ab4712010-07-14 17:59:35 -0700118 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800119 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Glenn Kastendeeb1282012-03-25 11:59:31 -0700120 // FIXME redundant per track
John Grossman4ff14ba2012-02-08 16:37:41 -0800121 t->localTimeFreq = lc.getLocalFreq();
Eric Laurenta5e82142012-04-16 13:47:17 -0700122 t->resampler = NULL;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700123 t->downmixerBufferProvider = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700124 t++;
125 }
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700126
127 // find multichannel downmix effect if we have to play multichannel content
128 uint32_t numEffects = 0;
129 int ret = EffectQueryNumberEffects(&numEffects);
130 if (ret != 0) {
131 ALOGE("AudioMixer() error %d querying number of effects", ret);
132 return;
133 }
134 ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
135
136 for (uint32_t i = 0 ; i < numEffects ; i++) {
137 if (EffectQueryEffect(i, &dwnmFxDesc) == 0) {
138 ALOGV("effect %d is called %s", i, dwnmFxDesc.name);
139 if (memcmp(&dwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
140 ALOGI("found effect \"%s\" from %s",
141 dwnmFxDesc.name, dwnmFxDesc.implementor);
142 isMultichannelCapable = true;
143 break;
144 }
145 }
146 }
147 ALOGE_IF(!isMultichannelCapable, "unable to find downmix effect");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700148}
149
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800150AudioMixer::~AudioMixer()
151{
152 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800153 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800154 delete t->resampler;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700155 delete t->downmixerBufferProvider;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800156 t++;
157 }
158 delete [] mState.outputTemp;
159 delete [] mState.resampleTemp;
160}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700161
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700162int AudioMixer::getTrackName(audio_channel_mask_t channelMask)
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800163{
Glenn Kasten5c94b6c2012-03-20 17:01:29 -0700164 uint32_t names = (~mTrackNames) & mConfiguredNames;
Glenn Kasten98dd5422011-12-15 14:38:29 -0800165 if (names != 0) {
166 int n = __builtin_ctz(names);
Steve Block3856b092011-10-20 11:56:00 +0100167 ALOGV("add track (%d)", n);
Glenn Kasten98dd5422011-12-15 14:38:29 -0800168 mTrackNames |= 1 << n;
Glenn Kastendeeb1282012-03-25 11:59:31 -0700169 // assume default parameters for the track, except where noted below
170 track_t* t = &mState.tracks[n];
171 t->needs = 0;
172 t->volume[0] = UNITY_GAIN;
173 t->volume[1] = UNITY_GAIN;
174 // no initialization needed
175 // t->prevVolume[0]
176 // t->prevVolume[1]
177 t->volumeInc[0] = 0;
178 t->volumeInc[1] = 0;
179 t->auxLevel = 0;
180 t->auxInc = 0;
181 // no initialization needed
182 // t->prevAuxLevel
183 // t->frameCount
184 t->channelCount = 2;
185 t->enabled = false;
186 t->format = 16;
187 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
188 // setBufferProvider(name, AudioBufferProvider *) is required before enable(name)
189 t->bufferProvider = NULL;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700190 t->downmixerBufferProvider = NULL;
Glenn Kastendeeb1282012-03-25 11:59:31 -0700191 t->buffer.raw = NULL;
192 // no initialization needed
193 // t->buffer.frameCount
194 t->hook = NULL;
195 t->in = NULL;
196 t->resampler = NULL;
197 t->sampleRate = mSampleRate;
198 // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
199 t->mainBuffer = NULL;
200 t->auxBuffer = NULL;
201 // see t->localTimeFreq in constructor above
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700202
203 status_t status = initTrackDownmix(&mState.tracks[n], n, channelMask);
204 if (status == OK) {
205 return TRACK0 + n;
206 }
207 ALOGE("AudioMixer::getTrackName(0x%x) failed, error preparing track for downmix",
208 channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700209 }
210 return -1;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800211}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700212
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800213void AudioMixer::invalidateState(uint32_t mask)
214{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700215 if (mask) {
216 mState.needsChanged |= mask;
217 mState.hook = process__validate;
218 }
219 }
220
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700221status_t AudioMixer::initTrackDownmix(track_t* pTrack, int trackNum, audio_channel_mask_t mask)
222{
223 uint32_t channelCount = popcount(mask);
224 ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount);
225 status_t status = OK;
226 if (channelCount > MAX_NUM_CHANNELS) {
227 pTrack->channelMask = mask;
228 pTrack->channelCount = channelCount;
229 ALOGV("initTrackDownmix(track=%d, mask=0x%x) calls prepareTrackForDownmix()",
230 trackNum, mask);
231 status = prepareTrackForDownmix(pTrack, trackNum);
232 } else {
233 unprepareTrackForDownmix(pTrack, trackNum);
234 }
235 return status;
236}
237
238void AudioMixer::unprepareTrackForDownmix(track_t* pTrack, int trackName) {
239 ALOGV("AudioMixer::unprepareTrackForDownmix(%d)", trackName);
240
241 if (pTrack->downmixerBufferProvider != NULL) {
242 // this track had previously been configured with a downmixer, delete it
243 ALOGV(" deleting old downmixer");
244 pTrack->bufferProvider = pTrack->downmixerBufferProvider->mTrackBufferProvider;
245 delete pTrack->downmixerBufferProvider;
246 pTrack->downmixerBufferProvider = NULL;
247 } else {
248 ALOGV(" nothing to do, no downmixer to delete");
249 }
250}
251
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700252status_t AudioMixer::prepareTrackForDownmix(track_t* pTrack, int trackName)
253{
254 ALOGV("AudioMixer::prepareTrackForDownmix(%d) with mask 0x%x", trackName, pTrack->channelMask);
255
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700256 // discard the previous downmixer if there was one
257 unprepareTrackForDownmix(pTrack, trackName);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700258
259 DownmixerBufferProvider* pDbp = new DownmixerBufferProvider();
260 int32_t status;
261
262 if (!isMultichannelCapable) {
263 ALOGE("prepareTrackForDownmix(%d) fails: mixer doesn't support multichannel content",
264 trackName);
265 goto noDownmixForActiveTrack;
266 }
267
268 if (EffectCreate(&dwnmFxDesc.uuid,
269 -2 /*sessionId*/, -2 /*ioId*/,// both not relevant here, using random value
270 &pDbp->mDownmixHandle/*pHandle*/) != 0) {
271 ALOGE("prepareTrackForDownmix(%d) fails: error creating downmixer effect", trackName);
272 goto noDownmixForActiveTrack;
273 }
274
275 // channel input configuration will be overridden per-track
276 pDbp->mDownmixConfig.inputCfg.channels = pTrack->channelMask;
277 pDbp->mDownmixConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
278 pDbp->mDownmixConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
279 pDbp->mDownmixConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
280 pDbp->mDownmixConfig.inputCfg.samplingRate = pTrack->sampleRate;
281 pDbp->mDownmixConfig.outputCfg.samplingRate = pTrack->sampleRate;
282 pDbp->mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
283 pDbp->mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
284 // input and output buffer provider, and frame count will not be used as the downmix effect
285 // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
286 pDbp->mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
287 EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
288 pDbp->mDownmixConfig.outputCfg.mask = pDbp->mDownmixConfig.inputCfg.mask;
289
290 {// scope for local variables that are not used in goto label "noDownmixForActiveTrack"
291 int cmdStatus;
292 uint32_t replySize = sizeof(int);
293
294 // Configure and enable downmixer
295 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
296 EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
297 &pDbp->mDownmixConfig /*pCmdData*/,
298 &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
299 if ((status != 0) || (cmdStatus != 0)) {
300 ALOGE("error %d while configuring downmixer for track %d", status, trackName);
301 goto noDownmixForActiveTrack;
302 }
303 replySize = sizeof(int);
304 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
305 EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
306 &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
307 if ((status != 0) || (cmdStatus != 0)) {
308 ALOGE("error %d while enabling downmixer for track %d", status, trackName);
309 goto noDownmixForActiveTrack;
310 }
311
312 // Set downmix type
313 // parameter size rounded for padding on 32bit boundary
314 const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
315 const int downmixParamSize =
316 sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
317 effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
318 param->psize = sizeof(downmix_params_t);
319 const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
320 memcpy(param->data, &downmixParam, param->psize);
321 const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
322 param->vsize = sizeof(downmix_type_t);
323 memcpy(param->data + psizePadded, &downmixType, param->vsize);
324
325 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
326 EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize/* cmdSize */,
327 param /*pCmndData*/, &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
328
329 free(param);
330
331 if ((status != 0) || (cmdStatus != 0)) {
332 ALOGE("error %d while setting downmix type for track %d", status, trackName);
333 goto noDownmixForActiveTrack;
334 } else {
335 ALOGV("downmix type set to %d for track %d", (int) downmixType, trackName);
336 }
337 }// end of scope for local variables that are not used in goto label "noDownmixForActiveTrack"
338
339 // initialization successful:
340 // - keep track of the real buffer provider in case it was set before
341 pDbp->mTrackBufferProvider = pTrack->bufferProvider;
342 // - we'll use the downmix effect integrated inside this
343 // track's buffer provider, and we'll use it as the track's buffer provider
344 pTrack->downmixerBufferProvider = pDbp;
345 pTrack->bufferProvider = pDbp;
346
347 return NO_ERROR;
348
349noDownmixForActiveTrack:
350 delete pDbp;
351 pTrack->downmixerBufferProvider = NULL;
352 return NO_INIT;
353}
354
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800355void AudioMixer::deleteTrackName(int name)
356{
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700357 ALOGV("AudioMixer::deleteTrackName(%d)", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700358 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800359 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten237a6242011-12-15 15:32:27 -0800360 ALOGV("deleteTrackName(%d)", name);
361 track_t& track(mState.tracks[ name ]);
Glenn Kasten4c340c62012-01-27 12:33:54 -0800362 if (track.enabled) {
363 track.enabled = false;
Glenn Kasten237a6242011-12-15 15:32:27 -0800364 invalidateState(1<<name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700365 }
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700366 // delete the resampler
367 delete track.resampler;
368 track.resampler = NULL;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700369 // delete the downmixer
370 unprepareTrackForDownmix(&mState.tracks[name], name);
371
Glenn Kasten237a6242011-12-15 15:32:27 -0800372 mTrackNames &= ~(1<<name);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800373}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700374
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800375void AudioMixer::enable(int name)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700376{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800377 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800378 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800379 track_t& track = mState.tracks[name];
380
Glenn Kasten4c340c62012-01-27 12:33:54 -0800381 if (!track.enabled) {
382 track.enabled = true;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800383 ALOGV("enable(%d)", name);
384 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700385 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700386}
387
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800388void AudioMixer::disable(int name)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700389{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800390 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800391 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800392 track_t& track = mState.tracks[name];
393
Glenn Kasten4c340c62012-01-27 12:33:54 -0800394 if (track.enabled) {
395 track.enabled = false;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800396 ALOGV("disable(%d)", name);
397 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700398 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700399}
400
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800401void AudioMixer::setParameter(int name, int target, int param, void *value)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700402{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800403 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800404 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800405 track_t& track = mState.tracks[name];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700406
Mathias Agopian65ab4712010-07-14 17:59:35 -0700407 int valueInt = (int)value;
408 int32_t *valueBuf = (int32_t *)value;
409
410 switch (target) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700411
Mathias Agopian65ab4712010-07-14 17:59:35 -0700412 case TRACK:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800413 switch (param) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700414 case CHANNEL_MASK: {
Glenn Kasten254af182012-07-03 14:59:05 -0700415 audio_channel_mask_t mask = (audio_channel_mask_t) value;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800416 if (track.channelMask != mask) {
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800417 uint32_t channelCount = popcount(mask);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700418 ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800419 track.channelMask = mask;
420 track.channelCount = channelCount;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700421 // the mask has changed, does this track need a downmixer?
422 initTrackDownmix(&mState.tracks[name], name, mask);
Glenn Kasten788040c2011-05-05 08:19:00 -0700423 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800424 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700425 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700426 } break;
427 case MAIN_BUFFER:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800428 if (track.mainBuffer != valueBuf) {
429 track.mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100430 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800431 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700432 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700433 break;
434 case AUX_BUFFER:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800435 if (track.auxBuffer != valueBuf) {
436 track.auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100437 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800438 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700439 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700440 break;
Glenn Kastendeeb1282012-03-25 11:59:31 -0700441 case FORMAT:
442 ALOG_ASSERT(valueInt == AUDIO_FORMAT_PCM_16_BIT);
443 break;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700444 // FIXME do we want to support setting the downmix type from AudioFlinger?
445 // for a specific track? or per mixer?
446 /* case DOWNMIX_TYPE:
447 break */
Glenn Kasten788040c2011-05-05 08:19:00 -0700448 default:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800449 LOG_FATAL("bad param");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700450 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700451 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700452
Mathias Agopian65ab4712010-07-14 17:59:35 -0700453 case RESAMPLE:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800454 switch (param) {
455 case SAMPLE_RATE:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800456 ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
Glenn Kasten788040c2011-05-05 08:19:00 -0700457 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
458 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
459 uint32_t(valueInt));
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800460 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700461 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800462 break;
463 case RESET:
Eric Laurent243f5f92011-02-28 16:52:51 -0800464 track.resetResampler();
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800465 invalidateState(1 << name);
466 break;
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700467 case REMOVE:
468 delete track.resampler;
469 track.resampler = NULL;
470 track.sampleRate = mSampleRate;
471 invalidateState(1 << name);
472 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700473 default:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800474 LOG_FATAL("bad param");
Eric Laurent243f5f92011-02-28 16:52:51 -0800475 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700476 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700477
Mathias Agopian65ab4712010-07-14 17:59:35 -0700478 case RAMP_VOLUME:
479 case VOLUME:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800480 switch (param) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700481 case VOLUME0:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800482 case VOLUME1:
483 if (track.volume[param-VOLUME0] != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100484 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800485 track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16;
486 track.volume[param-VOLUME0] = valueInt;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700487 if (target == VOLUME) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800488 track.prevVolume[param-VOLUME0] = valueInt << 16;
489 track.volumeInc[param-VOLUME0] = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700490 } else {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800491 int32_t d = (valueInt<<16) - track.prevVolume[param-VOLUME0];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700492 int32_t volInc = d / int32_t(mState.frameCount);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800493 track.volumeInc[param-VOLUME0] = volInc;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700494 if (volInc == 0) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800495 track.prevVolume[param-VOLUME0] = valueInt << 16;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700496 }
497 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800498 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700499 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800500 break;
501 case AUXLEVEL:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800502 //ALOG_ASSERT(0 <= valueInt && valueInt <= MAX_GAIN_INT, "bad aux level %d", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700503 if (track.auxLevel != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100504 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700505 track.prevAuxLevel = track.auxLevel << 16;
506 track.auxLevel = valueInt;
507 if (target == VOLUME) {
508 track.prevAuxLevel = valueInt << 16;
509 track.auxInc = 0;
510 } else {
511 int32_t d = (valueInt<<16) - track.prevAuxLevel;
512 int32_t volInc = d / int32_t(mState.frameCount);
513 track.auxInc = volInc;
514 if (volInc == 0) {
515 track.prevAuxLevel = valueInt << 16;
516 }
517 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800518 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700519 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800520 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700521 default:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800522 LOG_FATAL("bad param");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700523 }
524 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700525
526 default:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800527 LOG_FATAL("bad target");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700528 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700529}
530
531bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
532{
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700533 if (value != devSampleRate || resampler != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700534 if (sampleRate != value) {
535 sampleRate = value;
Glenn Kastene0feee32011-12-13 11:53:26 -0800536 if (resampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700537 resampler = AudioResampler::create(
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -0700538 format,
539 // the resampler sees the number of channels after the downmixer, if any
540 downmixerBufferProvider != NULL ? MAX_NUM_CHANNELS : channelCount,
541 devSampleRate);
John Grossman4ff14ba2012-02-08 16:37:41 -0800542 resampler->setLocalTimeFreq(localTimeFreq);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700543 }
544 return true;
545 }
546 }
547 return false;
548}
549
Mathias Agopian65ab4712010-07-14 17:59:35 -0700550inline
551void AudioMixer::track_t::adjustVolumeRamp(bool aux)
552{
Glenn Kastenf9a27772012-01-06 07:47:26 -0800553 for (uint32_t i=0 ; i<MAX_NUM_CHANNELS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700554 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
555 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
556 volumeInc[i] = 0;
557 prevVolume[i] = volume[i]<<16;
558 }
559 }
560 if (aux) {
561 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
562 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
563 auxInc = 0;
564 prevAuxLevel = auxLevel<<16;
565 }
566 }
567}
568
Glenn Kastenc59c0042012-02-02 14:06:11 -0800569size_t AudioMixer::getUnreleasedFrames(int name) const
Eric Laurent071ccd52011-12-22 16:08:41 -0800570{
571 name -= TRACK0;
572 if (uint32_t(name) < MAX_NUM_TRACKS) {
Glenn Kastenc59c0042012-02-02 14:06:11 -0800573 return mState.tracks[name].getUnreleasedFrames();
Eric Laurent071ccd52011-12-22 16:08:41 -0800574 }
575 return 0;
576}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700577
Glenn Kasten01c4ebf2012-02-22 10:47:35 -0800578void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700579{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800580 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800581 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700582
583 if (mState.tracks[name].downmixerBufferProvider != NULL) {
584 // update required?
585 if (mState.tracks[name].downmixerBufferProvider->mTrackBufferProvider != bufferProvider) {
586 ALOGV("AudioMixer::setBufferProvider(%p) for downmix", bufferProvider);
587 // setting the buffer provider for a track that gets downmixed consists in:
588 // 1/ setting the buffer provider to the "downmix / buffer provider" wrapper
589 // so it's the one that gets called when the buffer provider is needed,
590 mState.tracks[name].bufferProvider = mState.tracks[name].downmixerBufferProvider;
591 // 2/ saving the buffer provider for the track so the wrapper can use it
592 // when it downmixes.
593 mState.tracks[name].downmixerBufferProvider->mTrackBufferProvider = bufferProvider;
594 }
595 } else {
596 mState.tracks[name].bufferProvider = bufferProvider;
597 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700598}
599
600
601
John Grossman4ff14ba2012-02-08 16:37:41 -0800602void AudioMixer::process(int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700603{
John Grossman4ff14ba2012-02-08 16:37:41 -0800604 mState.hook(&mState, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700605}
606
607
John Grossman4ff14ba2012-02-08 16:37:41 -0800608void AudioMixer::process__validate(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700609{
Steve Block5ff1dd52012-01-05 23:22:43 +0000610 ALOGW_IF(!state->needsChanged,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700611 "in process__validate() but nothing's invalid");
612
613 uint32_t changed = state->needsChanged;
614 state->needsChanged = 0; // clear the validation flag
615
616 // recompute which tracks are enabled / disabled
617 uint32_t enabled = 0;
618 uint32_t disabled = 0;
619 while (changed) {
620 const int i = 31 - __builtin_clz(changed);
621 const uint32_t mask = 1<<i;
622 changed &= ~mask;
623 track_t& t = state->tracks[i];
624 (t.enabled ? enabled : disabled) |= mask;
625 }
626 state->enabledTracks &= ~disabled;
627 state->enabledTracks |= enabled;
628
629 // compute everything we need...
630 int countActiveTracks = 0;
Glenn Kasten4c340c62012-01-27 12:33:54 -0800631 bool all16BitsStereoNoResample = true;
632 bool resampling = false;
633 bool volumeRamp = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700634 uint32_t en = state->enabledTracks;
635 while (en) {
636 const int i = 31 - __builtin_clz(en);
637 en &= ~(1<<i);
638
639 countActiveTracks++;
640 track_t& t = state->tracks[i];
641 uint32_t n = 0;
642 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
643 n |= NEEDS_FORMAT_16;
644 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
645 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
646 n |= NEEDS_AUX_ENABLED;
647 }
648
649 if (t.volumeInc[0]|t.volumeInc[1]) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800650 volumeRamp = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700651 } else if (!t.doesResample() && t.volumeRL == 0) {
652 n |= NEEDS_MUTE_ENABLED;
653 }
654 t.needs = n;
655
656 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
657 t.hook = track__nop;
658 } else {
659 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800660 all16BitsStereoNoResample = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700661 }
662 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800663 all16BitsStereoNoResample = false;
664 resampling = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700665 t.hook = track__genericResample;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700666 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700667 "Track %d needs downmix + resample", i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700668 } else {
669 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
670 t.hook = track__16BitsMono;
Glenn Kasten4c340c62012-01-27 12:33:54 -0800671 all16BitsStereoNoResample = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700672 }
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700673 if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
Mathias Agopian65ab4712010-07-14 17:59:35 -0700674 t.hook = track__16BitsStereo;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700675 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700676 "Track %d needs downmix", i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700677 }
678 }
679 }
680 }
681
682 // select the processing hooks
683 state->hook = process__nop;
684 if (countActiveTracks) {
685 if (resampling) {
686 if (!state->outputTemp) {
687 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
688 }
689 if (!state->resampleTemp) {
690 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
691 }
692 state->hook = process__genericResampling;
693 } else {
694 if (state->outputTemp) {
695 delete [] state->outputTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800696 state->outputTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700697 }
698 if (state->resampleTemp) {
699 delete [] state->resampleTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800700 state->resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700701 }
702 state->hook = process__genericNoResampling;
703 if (all16BitsStereoNoResample && !volumeRamp) {
704 if (countActiveTracks == 1) {
705 state->hook = process__OneTrack16BitsStereoNoResampling;
706 }
707 }
708 }
709 }
710
Steve Block3856b092011-10-20 11:56:00 +0100711 ALOGV("mixer configuration change: %d activeTracks (%08x) "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700712 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
713 countActiveTracks, state->enabledTracks,
714 all16BitsStereoNoResample, resampling, volumeRamp);
715
John Grossman4ff14ba2012-02-08 16:37:41 -0800716 state->hook(state, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700717
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800718 // Now that the volume ramp has been done, set optimal state and
719 // track hooks for subsequent mixer process
720 if (countActiveTracks) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800721 bool allMuted = true;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800722 uint32_t en = state->enabledTracks;
723 while (en) {
724 const int i = 31 - __builtin_clz(en);
725 en &= ~(1<<i);
726 track_t& t = state->tracks[i];
727 if (!t.doesResample() && t.volumeRL == 0)
728 {
729 t.needs |= NEEDS_MUTE_ENABLED;
730 t.hook = track__nop;
731 } else {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800732 allMuted = false;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800733 }
734 }
735 if (allMuted) {
736 state->hook = process__nop;
737 } else if (all16BitsStereoNoResample) {
738 if (countActiveTracks == 1) {
739 state->hook = process__OneTrack16BitsStereoNoResampling;
740 }
741 }
742 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700743}
744
Mathias Agopian65ab4712010-07-14 17:59:35 -0700745
746void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
747{
748 t->resampler->setSampleRate(t->sampleRate);
749
750 // ramp gain - resample to temp buffer and scale/mix in 2nd step
751 if (aux != NULL) {
752 // always resample with unity gain when sending to auxiliary buffer to be able
753 // to apply send level after resampling
754 // TODO: modify each resampler to support aux channel?
755 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
756 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
757 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Glenn Kastenf6b16782011-12-15 09:51:17 -0800758 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700759 volumeRampStereo(t, out, outFrameCount, temp, aux);
760 } else {
761 volumeStereo(t, out, outFrameCount, temp, aux);
762 }
763 } else {
Glenn Kastenf6b16782011-12-15 09:51:17 -0800764 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700765 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
766 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
767 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
768 volumeRampStereo(t, out, outFrameCount, temp, aux);
769 }
770
771 // constant gain
772 else {
773 t->resampler->setVolume(t->volume[0], t->volume[1]);
774 t->resampler->resample(out, outFrameCount, t->bufferProvider);
775 }
776 }
777}
778
779void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
780{
781}
782
783void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
784{
785 int32_t vl = t->prevVolume[0];
786 int32_t vr = t->prevVolume[1];
787 const int32_t vlInc = t->volumeInc[0];
788 const int32_t vrInc = t->volumeInc[1];
789
Steve Blockb8a80522011-12-20 16:23:08 +0000790 //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700791 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
792 // (vl + vlInc*frameCount)/65536.0f, frameCount);
793
794 // ramp volume
Glenn Kastenf6b16782011-12-15 09:51:17 -0800795 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700796 int32_t va = t->prevAuxLevel;
797 const int32_t vaInc = t->auxInc;
798 int32_t l;
799 int32_t r;
800
801 do {
802 l = (*temp++ >> 12);
803 r = (*temp++ >> 12);
804 *out++ += (vl >> 16) * l;
805 *out++ += (vr >> 16) * r;
806 *aux++ += (va >> 17) * (l + r);
807 vl += vlInc;
808 vr += vrInc;
809 va += vaInc;
810 } while (--frameCount);
811 t->prevAuxLevel = va;
812 } else {
813 do {
814 *out++ += (vl >> 16) * (*temp++ >> 12);
815 *out++ += (vr >> 16) * (*temp++ >> 12);
816 vl += vlInc;
817 vr += vrInc;
818 } while (--frameCount);
819 }
820 t->prevVolume[0] = vl;
821 t->prevVolume[1] = vr;
Glenn Kastena1117922012-01-26 10:53:32 -0800822 t->adjustVolumeRamp(aux != NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700823}
824
825void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
826{
827 const int16_t vl = t->volume[0];
828 const int16_t vr = t->volume[1];
829
Glenn Kastenf6b16782011-12-15 09:51:17 -0800830 if (CC_UNLIKELY(aux != NULL)) {
Glenn Kasten3b81aca2012-01-27 15:26:23 -0800831 const int16_t va = t->auxLevel;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700832 do {
833 int16_t l = (int16_t)(*temp++ >> 12);
834 int16_t r = (int16_t)(*temp++ >> 12);
835 out[0] = mulAdd(l, vl, out[0]);
836 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
837 out[1] = mulAdd(r, vr, out[1]);
838 out += 2;
839 aux[0] = mulAdd(a, va, aux[0]);
840 aux++;
841 } while (--frameCount);
842 } else {
843 do {
844 int16_t l = (int16_t)(*temp++ >> 12);
845 int16_t r = (int16_t)(*temp++ >> 12);
846 out[0] = mulAdd(l, vl, out[0]);
847 out[1] = mulAdd(r, vr, out[1]);
848 out += 2;
849 } while (--frameCount);
850 }
851}
852
853void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
854{
Glenn Kasten54c3b662012-01-06 07:46:30 -0800855 const int16_t *in = static_cast<const int16_t *>(t->in);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700856
Glenn Kastenf6b16782011-12-15 09:51:17 -0800857 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700858 int32_t l;
859 int32_t r;
860 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800861 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700862 int32_t vl = t->prevVolume[0];
863 int32_t vr = t->prevVolume[1];
864 int32_t va = t->prevAuxLevel;
865 const int32_t vlInc = t->volumeInc[0];
866 const int32_t vrInc = t->volumeInc[1];
867 const int32_t vaInc = t->auxInc;
Steve Blockb8a80522011-12-20 16:23:08 +0000868 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700869 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
870 // (vl + vlInc*frameCount)/65536.0f, frameCount);
871
872 do {
873 l = (int32_t)*in++;
874 r = (int32_t)*in++;
875 *out++ += (vl >> 16) * l;
876 *out++ += (vr >> 16) * r;
877 *aux++ += (va >> 17) * (l + r);
878 vl += vlInc;
879 vr += vrInc;
880 va += vaInc;
881 } while (--frameCount);
882
883 t->prevVolume[0] = vl;
884 t->prevVolume[1] = vr;
885 t->prevAuxLevel = va;
886 t->adjustVolumeRamp(true);
887 }
888
889 // constant gain
890 else {
891 const uint32_t vrl = t->volumeRL;
892 const int16_t va = (int16_t)t->auxLevel;
893 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -0800894 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700895 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
896 in += 2;
897 out[0] = mulAddRL(1, rl, vrl, out[0]);
898 out[1] = mulAddRL(0, rl, vrl, out[1]);
899 out += 2;
900 aux[0] = mulAdd(a, va, aux[0]);
901 aux++;
902 } while (--frameCount);
903 }
904 } else {
905 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800906 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700907 int32_t vl = t->prevVolume[0];
908 int32_t vr = t->prevVolume[1];
909 const int32_t vlInc = t->volumeInc[0];
910 const int32_t vrInc = t->volumeInc[1];
911
Steve Blockb8a80522011-12-20 16:23:08 +0000912 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700913 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
914 // (vl + vlInc*frameCount)/65536.0f, frameCount);
915
916 do {
917 *out++ += (vl >> 16) * (int32_t) *in++;
918 *out++ += (vr >> 16) * (int32_t) *in++;
919 vl += vlInc;
920 vr += vrInc;
921 } while (--frameCount);
922
923 t->prevVolume[0] = vl;
924 t->prevVolume[1] = vr;
925 t->adjustVolumeRamp(false);
926 }
927
928 // constant gain
929 else {
930 const uint32_t vrl = t->volumeRL;
931 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -0800932 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700933 in += 2;
934 out[0] = mulAddRL(1, rl, vrl, out[0]);
935 out[1] = mulAddRL(0, rl, vrl, out[1]);
936 out += 2;
937 } while (--frameCount);
938 }
939 }
940 t->in = in;
941}
942
943void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
944{
Glenn Kasten54c3b662012-01-06 07:46:30 -0800945 const int16_t *in = static_cast<int16_t const *>(t->in);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700946
Glenn Kastenf6b16782011-12-15 09:51:17 -0800947 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700948 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800949 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700950 int32_t vl = t->prevVolume[0];
951 int32_t vr = t->prevVolume[1];
952 int32_t va = t->prevAuxLevel;
953 const int32_t vlInc = t->volumeInc[0];
954 const int32_t vrInc = t->volumeInc[1];
955 const int32_t vaInc = t->auxInc;
956
Steve Blockb8a80522011-12-20 16:23:08 +0000957 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700958 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
959 // (vl + vlInc*frameCount)/65536.0f, frameCount);
960
961 do {
962 int32_t l = *in++;
963 *out++ += (vl >> 16) * l;
964 *out++ += (vr >> 16) * l;
965 *aux++ += (va >> 16) * l;
966 vl += vlInc;
967 vr += vrInc;
968 va += vaInc;
969 } while (--frameCount);
970
971 t->prevVolume[0] = vl;
972 t->prevVolume[1] = vr;
973 t->prevAuxLevel = va;
974 t->adjustVolumeRamp(true);
975 }
976 // constant gain
977 else {
978 const int16_t vl = t->volume[0];
979 const int16_t vr = t->volume[1];
980 const int16_t va = (int16_t)t->auxLevel;
981 do {
982 int16_t l = *in++;
983 out[0] = mulAdd(l, vl, out[0]);
984 out[1] = mulAdd(l, vr, out[1]);
985 out += 2;
986 aux[0] = mulAdd(l, va, aux[0]);
987 aux++;
988 } while (--frameCount);
989 }
990 } else {
991 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800992 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700993 int32_t vl = t->prevVolume[0];
994 int32_t vr = t->prevVolume[1];
995 const int32_t vlInc = t->volumeInc[0];
996 const int32_t vrInc = t->volumeInc[1];
997
Steve Blockb8a80522011-12-20 16:23:08 +0000998 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700999 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1000 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1001
1002 do {
1003 int32_t l = *in++;
1004 *out++ += (vl >> 16) * l;
1005 *out++ += (vr >> 16) * l;
1006 vl += vlInc;
1007 vr += vrInc;
1008 } while (--frameCount);
1009
1010 t->prevVolume[0] = vl;
1011 t->prevVolume[1] = vr;
1012 t->adjustVolumeRamp(false);
1013 }
1014 // constant gain
1015 else {
1016 const int16_t vl = t->volume[0];
1017 const int16_t vr = t->volume[1];
1018 do {
1019 int16_t l = *in++;
1020 out[0] = mulAdd(l, vl, out[0]);
1021 out[1] = mulAdd(l, vr, out[1]);
1022 out += 2;
1023 } while (--frameCount);
1024 }
1025 }
1026 t->in = in;
1027}
1028
Mathias Agopian65ab4712010-07-14 17:59:35 -07001029// no-op case
John Grossman4ff14ba2012-02-08 16:37:41 -08001030void AudioMixer::process__nop(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001031{
1032 uint32_t e0 = state->enabledTracks;
1033 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
1034 while (e0) {
1035 // process by group of tracks with same output buffer to
1036 // avoid multiple memset() on same buffer
1037 uint32_t e1 = e0, e2 = e0;
1038 int i = 31 - __builtin_clz(e1);
1039 track_t& t1 = state->tracks[i];
1040 e2 &= ~(1<<i);
1041 while (e2) {
1042 i = 31 - __builtin_clz(e2);
1043 e2 &= ~(1<<i);
1044 track_t& t2 = state->tracks[i];
Glenn Kastenf6b16782011-12-15 09:51:17 -08001045 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001046 e1 &= ~(1<<i);
1047 }
1048 }
1049 e0 &= ~(e1);
1050
1051 memset(t1.mainBuffer, 0, bufSize);
1052
1053 while (e1) {
1054 i = 31 - __builtin_clz(e1);
1055 e1 &= ~(1<<i);
1056 t1 = state->tracks[i];
1057 size_t outFrames = state->frameCount;
1058 while (outFrames) {
1059 t1.buffer.frameCount = outFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001060 int64_t outputPTS = calculateOutputPTS(
1061 t1, pts, state->frameCount - outFrames);
1062 t1.bufferProvider->getNextBuffer(&t1.buffer, outputPTS);
Glenn Kastena0d68332012-01-27 16:47:15 -08001063 if (t1.buffer.raw == NULL) break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001064 outFrames -= t1.buffer.frameCount;
1065 t1.bufferProvider->releaseBuffer(&t1.buffer);
1066 }
1067 }
1068 }
1069}
1070
1071// generic code without resampling
John Grossman4ff14ba2012-02-08 16:37:41 -08001072void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001073{
1074 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
1075
1076 // acquire each track's buffer
1077 uint32_t enabledTracks = state->enabledTracks;
1078 uint32_t e0 = enabledTracks;
1079 while (e0) {
1080 const int i = 31 - __builtin_clz(e0);
1081 e0 &= ~(1<<i);
1082 track_t& t = state->tracks[i];
1083 t.buffer.frameCount = state->frameCount;
John Grossman4ff14ba2012-02-08 16:37:41 -08001084 t.bufferProvider->getNextBuffer(&t.buffer, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001085 t.frameCount = t.buffer.frameCount;
1086 t.in = t.buffer.raw;
1087 // t.in == NULL can happen if the track was flushed just after having
1088 // been enabled for mixing.
1089 if (t.in == NULL)
1090 enabledTracks &= ~(1<<i);
1091 }
1092
1093 e0 = enabledTracks;
1094 while (e0) {
1095 // process by group of tracks with same output buffer to
1096 // optimize cache use
1097 uint32_t e1 = e0, e2 = e0;
1098 int j = 31 - __builtin_clz(e1);
1099 track_t& t1 = state->tracks[j];
1100 e2 &= ~(1<<j);
1101 while (e2) {
1102 j = 31 - __builtin_clz(e2);
1103 e2 &= ~(1<<j);
1104 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -08001105 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001106 e1 &= ~(1<<j);
1107 }
1108 }
1109 e0 &= ~(e1);
1110 // this assumes output 16 bits stereo, no resampling
1111 int32_t *out = t1.mainBuffer;
1112 size_t numFrames = 0;
1113 do {
1114 memset(outTemp, 0, sizeof(outTemp));
1115 e2 = e1;
1116 while (e2) {
1117 const int i = 31 - __builtin_clz(e2);
1118 e2 &= ~(1<<i);
1119 track_t& t = state->tracks[i];
1120 size_t outFrames = BLOCKSIZE;
1121 int32_t *aux = NULL;
Glenn Kastenf6b16782011-12-15 09:51:17 -08001122 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001123 aux = t.auxBuffer + numFrames;
1124 }
1125 while (outFrames) {
1126 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
1127 if (inFrames) {
Glenn Kastena1117922012-01-26 10:53:32 -08001128 t.hook(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001129 t.frameCount -= inFrames;
1130 outFrames -= inFrames;
Glenn Kastenf6b16782011-12-15 09:51:17 -08001131 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001132 aux += inFrames;
1133 }
1134 }
1135 if (t.frameCount == 0 && outFrames) {
1136 t.bufferProvider->releaseBuffer(&t.buffer);
1137 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
John Grossman4ff14ba2012-02-08 16:37:41 -08001138 int64_t outputPTS = calculateOutputPTS(
1139 t, pts, numFrames + (BLOCKSIZE - outFrames));
1140 t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001141 t.in = t.buffer.raw;
1142 if (t.in == NULL) {
1143 enabledTracks &= ~(1<<i);
1144 e1 &= ~(1<<i);
1145 break;
1146 }
1147 t.frameCount = t.buffer.frameCount;
1148 }
1149 }
1150 }
1151 ditherAndClamp(out, outTemp, BLOCKSIZE);
1152 out += BLOCKSIZE;
1153 numFrames += BLOCKSIZE;
1154 } while (numFrames < state->frameCount);
1155 }
1156
1157 // release each track's buffer
1158 e0 = enabledTracks;
1159 while (e0) {
1160 const int i = 31 - __builtin_clz(e0);
1161 e0 &= ~(1<<i);
1162 track_t& t = state->tracks[i];
1163 t.bufferProvider->releaseBuffer(&t.buffer);
1164 }
1165}
1166
1167
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001168// generic code with resampling
John Grossman4ff14ba2012-02-08 16:37:41 -08001169void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001170{
Glenn Kasten54c3b662012-01-06 07:46:30 -08001171 // this const just means that local variable outTemp doesn't change
Mathias Agopian65ab4712010-07-14 17:59:35 -07001172 int32_t* const outTemp = state->outputTemp;
1173 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001174
1175 size_t numFrames = state->frameCount;
1176
1177 uint32_t e0 = state->enabledTracks;
1178 while (e0) {
1179 // process by group of tracks with same output buffer
1180 // to optimize cache use
1181 uint32_t e1 = e0, e2 = e0;
1182 int j = 31 - __builtin_clz(e1);
1183 track_t& t1 = state->tracks[j];
1184 e2 &= ~(1<<j);
1185 while (e2) {
1186 j = 31 - __builtin_clz(e2);
1187 e2 &= ~(1<<j);
1188 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -08001189 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001190 e1 &= ~(1<<j);
1191 }
1192 }
1193 e0 &= ~(e1);
1194 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi2151d7b2011-02-04 15:24:34 +01001195 memset(outTemp, 0, size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001196 while (e1) {
1197 const int i = 31 - __builtin_clz(e1);
1198 e1 &= ~(1<<i);
1199 track_t& t = state->tracks[i];
1200 int32_t *aux = NULL;
Glenn Kastenf6b16782011-12-15 09:51:17 -08001201 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001202 aux = t.auxBuffer;
1203 }
1204
1205 // this is a little goofy, on the resampling case we don't
1206 // acquire/release the buffers because it's done by
1207 // the resampler.
1208 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
John Grossman4ff14ba2012-02-08 16:37:41 -08001209 t.resampler->setPTS(pts);
Glenn Kastena1117922012-01-26 10:53:32 -08001210 t.hook(&t, outTemp, numFrames, state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001211 } else {
1212
1213 size_t outFrames = 0;
1214
1215 while (outFrames < numFrames) {
1216 t.buffer.frameCount = numFrames - outFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001217 int64_t outputPTS = calculateOutputPTS(t, pts, outFrames);
1218 t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001219 t.in = t.buffer.raw;
1220 // t.in == NULL can happen if the track was flushed just after having
1221 // been enabled for mixing.
1222 if (t.in == NULL) break;
1223
Glenn Kastenf6b16782011-12-15 09:51:17 -08001224 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001225 aux += outFrames;
1226 }
Glenn Kastena1117922012-01-26 10:53:32 -08001227 t.hook(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001228 outFrames += t.buffer.frameCount;
1229 t.bufferProvider->releaseBuffer(&t.buffer);
1230 }
1231 }
1232 }
1233 ditherAndClamp(out, outTemp, numFrames);
1234 }
1235}
1236
1237// one track, 16 bits stereo without resampling is the most common case
John Grossman4ff14ba2012-02-08 16:37:41 -08001238void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state,
1239 int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001240{
Glenn Kasten99e53b82012-01-19 08:59:58 -08001241 // This method is only called when state->enabledTracks has exactly
1242 // one bit set. The asserts below would verify this, but are commented out
1243 // since the whole point of this method is to optimize performance.
Glenn Kasten5798d4e2012-03-08 12:18:35 -08001244 //ALOG_ASSERT(0 != state->enabledTracks, "no tracks enabled");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001245 const int i = 31 - __builtin_clz(state->enabledTracks);
Glenn Kasten5798d4e2012-03-08 12:18:35 -08001246 //ALOG_ASSERT((1 << i) == state->enabledTracks, "more than 1 track enabled");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001247 const track_t& t = state->tracks[i];
1248
1249 AudioBufferProvider::Buffer& b(t.buffer);
1250
1251 int32_t* out = t.mainBuffer;
1252 size_t numFrames = state->frameCount;
1253
1254 const int16_t vl = t.volume[0];
1255 const int16_t vr = t.volume[1];
1256 const uint32_t vrl = t.volumeRL;
1257 while (numFrames) {
1258 b.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001259 int64_t outputPTS = calculateOutputPTS(t, pts, out - t.mainBuffer);
1260 t.bufferProvider->getNextBuffer(&b, outputPTS);
Glenn Kasten54c3b662012-01-06 07:46:30 -08001261 const int16_t *in = b.i16;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001262
1263 // in == NULL can happen if the track was flushed just after having
1264 // been enabled for mixing.
1265 if (in == NULL || ((unsigned long)in & 3)) {
1266 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
Steve Block29357bc2012-01-06 19:20:56 +00001267 ALOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
Mathias Agopian65ab4712010-07-14 17:59:35 -07001268 in, i, t.channelCount, t.needs);
1269 return;
1270 }
1271 size_t outFrames = b.frameCount;
1272
Glenn Kastenf6b16782011-12-15 09:51:17 -08001273 if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001274 // volume is boosted, so we might need to clamp even though
1275 // we process only one track.
1276 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001277 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001278 in += 2;
1279 int32_t l = mulRL(1, rl, vrl) >> 12;
1280 int32_t r = mulRL(0, rl, vrl) >> 12;
1281 // clamping...
1282 l = clamp16(l);
1283 r = clamp16(r);
1284 *out++ = (r<<16) | (l & 0xFFFF);
1285 } while (--outFrames);
1286 } else {
1287 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001288 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001289 in += 2;
1290 int32_t l = mulRL(1, rl, vrl) >> 12;
1291 int32_t r = mulRL(0, rl, vrl) >> 12;
1292 *out++ = (r<<16) | (l & 0xFFFF);
1293 } while (--outFrames);
1294 }
1295 numFrames -= b.frameCount;
1296 t.bufferProvider->releaseBuffer(&b);
1297 }
1298}
1299
Glenn Kasten81a028f2011-12-15 09:53:12 -08001300#if 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07001301// 2 tracks is also a common case
1302// NEVER used in current implementation of process__validate()
1303// only use if the 2 tracks have the same output buffer
John Grossman4ff14ba2012-02-08 16:37:41 -08001304void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state,
1305 int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001306{
1307 int i;
1308 uint32_t en = state->enabledTracks;
1309
1310 i = 31 - __builtin_clz(en);
1311 const track_t& t0 = state->tracks[i];
1312 AudioBufferProvider::Buffer& b0(t0.buffer);
1313
1314 en &= ~(1<<i);
1315 i = 31 - __builtin_clz(en);
1316 const track_t& t1 = state->tracks[i];
1317 AudioBufferProvider::Buffer& b1(t1.buffer);
1318
Glenn Kasten54c3b662012-01-06 07:46:30 -08001319 const int16_t *in0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001320 const int16_t vl0 = t0.volume[0];
1321 const int16_t vr0 = t0.volume[1];
1322 size_t frameCount0 = 0;
1323
Glenn Kasten54c3b662012-01-06 07:46:30 -08001324 const int16_t *in1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001325 const int16_t vl1 = t1.volume[0];
1326 const int16_t vr1 = t1.volume[1];
1327 size_t frameCount1 = 0;
1328
1329 //FIXME: only works if two tracks use same buffer
1330 int32_t* out = t0.mainBuffer;
1331 size_t numFrames = state->frameCount;
Glenn Kasten54c3b662012-01-06 07:46:30 -08001332 const int16_t *buff = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001333
1334
1335 while (numFrames) {
1336
1337 if (frameCount0 == 0) {
1338 b0.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001339 int64_t outputPTS = calculateOutputPTS(t0, pts,
1340 out - t0.mainBuffer);
1341 t0.bufferProvider->getNextBuffer(&b0, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001342 if (b0.i16 == NULL) {
1343 if (buff == NULL) {
1344 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1345 }
1346 in0 = buff;
1347 b0.frameCount = numFrames;
1348 } else {
1349 in0 = b0.i16;
1350 }
1351 frameCount0 = b0.frameCount;
1352 }
1353 if (frameCount1 == 0) {
1354 b1.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001355 int64_t outputPTS = calculateOutputPTS(t1, pts,
1356 out - t0.mainBuffer);
1357 t1.bufferProvider->getNextBuffer(&b1, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001358 if (b1.i16 == NULL) {
1359 if (buff == NULL) {
1360 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1361 }
1362 in1 = buff;
1363 b1.frameCount = numFrames;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001364 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001365 in1 = b1.i16;
1366 }
1367 frameCount1 = b1.frameCount;
1368 }
1369
1370 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1371
1372 numFrames -= outFrames;
1373 frameCount0 -= outFrames;
1374 frameCount1 -= outFrames;
1375
1376 do {
1377 int32_t l0 = *in0++;
1378 int32_t r0 = *in0++;
1379 l0 = mul(l0, vl0);
1380 r0 = mul(r0, vr0);
1381 int32_t l = *in1++;
1382 int32_t r = *in1++;
1383 l = mulAdd(l, vl1, l0) >> 12;
1384 r = mulAdd(r, vr1, r0) >> 12;
1385 // clamping...
1386 l = clamp16(l);
1387 r = clamp16(r);
1388 *out++ = (r<<16) | (l & 0xFFFF);
1389 } while (--outFrames);
1390
1391 if (frameCount0 == 0) {
1392 t0.bufferProvider->releaseBuffer(&b0);
1393 }
1394 if (frameCount1 == 0) {
1395 t1.bufferProvider->releaseBuffer(&b1);
1396 }
1397 }
1398
Glenn Kastene9dd0172012-01-27 18:08:45 -08001399 delete [] buff;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001400}
Glenn Kasten81a028f2011-12-15 09:53:12 -08001401#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001402
John Grossman4ff14ba2012-02-08 16:37:41 -08001403int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS,
1404 int outputFrameIndex)
1405{
1406 if (AudioBufferProvider::kInvalidPTS == basePTS)
1407 return AudioBufferProvider::kInvalidPTS;
1408
1409 return basePTS + ((outputFrameIndex * t.localTimeFreq) / t.sampleRate);
1410}
1411
Mathias Agopian65ab4712010-07-14 17:59:35 -07001412// ----------------------------------------------------------------------------
1413}; // namespace android