blob: 5b0867d66705d563a57fc9f32dc52c55c4788360 [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
Glenn Kasten52008f82012-03-18 09:34:41 -0700107 pthread_once(&sOnceControl, &sInitRoutine);
108
Mathias Agopian65ab4712010-07-14 17:59:35 -0700109 mState.enabledTracks= 0;
110 mState.needsChanged = 0;
111 mState.frameCount = frameCount;
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800112 mState.hook = process__nop;
Glenn Kastene0feee32011-12-13 11:53:26 -0800113 mState.outputTemp = NULL;
114 mState.resampleTemp = NULL;
Glenn Kasten84afa3b2012-01-25 15:28:08 -0800115 // mState.reserved
Glenn Kasten17a736c2012-02-14 08:52:15 -0800116
117 // FIXME Most of the following initialization is probably redundant since
118 // tracks[i] should only be referenced if (mTrackNames & (1 << i)) != 0
119 // and mTrackNames is initially 0. However, leave it here until that's verified.
Mathias Agopian65ab4712010-07-14 17:59:35 -0700120 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800121 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
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;
190 t->buffer.raw = NULL;
191 // no initialization needed
192 // t->buffer.frameCount
193 t->hook = NULL;
194 t->in = NULL;
195 t->resampler = NULL;
196 t->sampleRate = mSampleRate;
197 // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
198 t->mainBuffer = NULL;
199 t->auxBuffer = NULL;
Glenn Kasten52008f82012-03-18 09:34:41 -0700200 t->downmixerBufferProvider = NULL;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700201
202 status_t status = initTrackDownmix(&mState.tracks[n], n, channelMask);
203 if (status == OK) {
204 return TRACK0 + n;
205 }
206 ALOGE("AudioMixer::getTrackName(0x%x) failed, error preparing track for downmix",
207 channelMask);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700208 }
209 return -1;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800210}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700211
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800212void AudioMixer::invalidateState(uint32_t mask)
213{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700214 if (mask) {
215 mState.needsChanged |= mask;
216 mState.hook = process__validate;
217 }
218 }
219
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700220status_t AudioMixer::initTrackDownmix(track_t* pTrack, int trackNum, audio_channel_mask_t mask)
221{
222 uint32_t channelCount = popcount(mask);
223 ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount);
224 status_t status = OK;
225 if (channelCount > MAX_NUM_CHANNELS) {
226 pTrack->channelMask = mask;
227 pTrack->channelCount = channelCount;
228 ALOGV("initTrackDownmix(track=%d, mask=0x%x) calls prepareTrackForDownmix()",
229 trackNum, mask);
230 status = prepareTrackForDownmix(pTrack, trackNum);
231 } else {
232 unprepareTrackForDownmix(pTrack, trackNum);
233 }
234 return status;
235}
236
237void AudioMixer::unprepareTrackForDownmix(track_t* pTrack, int trackName) {
238 ALOGV("AudioMixer::unprepareTrackForDownmix(%d)", trackName);
239
240 if (pTrack->downmixerBufferProvider != NULL) {
241 // this track had previously been configured with a downmixer, delete it
242 ALOGV(" deleting old downmixer");
243 pTrack->bufferProvider = pTrack->downmixerBufferProvider->mTrackBufferProvider;
244 delete pTrack->downmixerBufferProvider;
245 pTrack->downmixerBufferProvider = NULL;
246 } else {
247 ALOGV(" nothing to do, no downmixer to delete");
248 }
249}
250
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700251status_t AudioMixer::prepareTrackForDownmix(track_t* pTrack, int trackName)
252{
253 ALOGV("AudioMixer::prepareTrackForDownmix(%d) with mask 0x%x", trackName, pTrack->channelMask);
254
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700255 // discard the previous downmixer if there was one
256 unprepareTrackForDownmix(pTrack, trackName);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700257
258 DownmixerBufferProvider* pDbp = new DownmixerBufferProvider();
259 int32_t status;
260
261 if (!isMultichannelCapable) {
262 ALOGE("prepareTrackForDownmix(%d) fails: mixer doesn't support multichannel content",
263 trackName);
264 goto noDownmixForActiveTrack;
265 }
266
267 if (EffectCreate(&dwnmFxDesc.uuid,
268 -2 /*sessionId*/, -2 /*ioId*/,// both not relevant here, using random value
269 &pDbp->mDownmixHandle/*pHandle*/) != 0) {
270 ALOGE("prepareTrackForDownmix(%d) fails: error creating downmixer effect", trackName);
271 goto noDownmixForActiveTrack;
272 }
273
274 // channel input configuration will be overridden per-track
275 pDbp->mDownmixConfig.inputCfg.channels = pTrack->channelMask;
276 pDbp->mDownmixConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
277 pDbp->mDownmixConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
278 pDbp->mDownmixConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
279 pDbp->mDownmixConfig.inputCfg.samplingRate = pTrack->sampleRate;
280 pDbp->mDownmixConfig.outputCfg.samplingRate = pTrack->sampleRate;
281 pDbp->mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
282 pDbp->mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
283 // input and output buffer provider, and frame count will not be used as the downmix effect
284 // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
285 pDbp->mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
286 EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
287 pDbp->mDownmixConfig.outputCfg.mask = pDbp->mDownmixConfig.inputCfg.mask;
288
289 {// scope for local variables that are not used in goto label "noDownmixForActiveTrack"
290 int cmdStatus;
291 uint32_t replySize = sizeof(int);
292
293 // Configure and enable downmixer
294 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
295 EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
296 &pDbp->mDownmixConfig /*pCmdData*/,
297 &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
298 if ((status != 0) || (cmdStatus != 0)) {
299 ALOGE("error %d while configuring downmixer for track %d", status, trackName);
300 goto noDownmixForActiveTrack;
301 }
302 replySize = sizeof(int);
303 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
304 EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
305 &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
306 if ((status != 0) || (cmdStatus != 0)) {
307 ALOGE("error %d while enabling downmixer for track %d", status, trackName);
308 goto noDownmixForActiveTrack;
309 }
310
311 // Set downmix type
312 // parameter size rounded for padding on 32bit boundary
313 const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
314 const int downmixParamSize =
315 sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
316 effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
317 param->psize = sizeof(downmix_params_t);
318 const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
319 memcpy(param->data, &downmixParam, param->psize);
320 const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
321 param->vsize = sizeof(downmix_type_t);
322 memcpy(param->data + psizePadded, &downmixType, param->vsize);
323
324 status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
325 EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize/* cmdSize */,
326 param /*pCmndData*/, &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
327
328 free(param);
329
330 if ((status != 0) || (cmdStatus != 0)) {
331 ALOGE("error %d while setting downmix type for track %d", status, trackName);
332 goto noDownmixForActiveTrack;
333 } else {
334 ALOGV("downmix type set to %d for track %d", (int) downmixType, trackName);
335 }
336 }// end of scope for local variables that are not used in goto label "noDownmixForActiveTrack"
337
338 // initialization successful:
339 // - keep track of the real buffer provider in case it was set before
340 pDbp->mTrackBufferProvider = pTrack->bufferProvider;
341 // - we'll use the downmix effect integrated inside this
342 // track's buffer provider, and we'll use it as the track's buffer provider
343 pTrack->downmixerBufferProvider = pDbp;
344 pTrack->bufferProvider = pDbp;
345
346 return NO_ERROR;
347
348noDownmixForActiveTrack:
349 delete pDbp;
350 pTrack->downmixerBufferProvider = NULL;
351 return NO_INIT;
352}
353
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800354void AudioMixer::deleteTrackName(int name)
355{
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700356 ALOGV("AudioMixer::deleteTrackName(%d)", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700357 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800358 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten237a6242011-12-15 15:32:27 -0800359 ALOGV("deleteTrackName(%d)", name);
360 track_t& track(mState.tracks[ name ]);
Glenn Kasten4c340c62012-01-27 12:33:54 -0800361 if (track.enabled) {
362 track.enabled = false;
Glenn Kasten237a6242011-12-15 15:32:27 -0800363 invalidateState(1<<name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700364 }
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700365 // delete the resampler
366 delete track.resampler;
367 track.resampler = NULL;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700368 // delete the downmixer
369 unprepareTrackForDownmix(&mState.tracks[name], name);
370
Glenn Kasten237a6242011-12-15 15:32:27 -0800371 mTrackNames &= ~(1<<name);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800372}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700373
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800374void AudioMixer::enable(int name)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700375{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800376 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800377 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800378 track_t& track = mState.tracks[name];
379
Glenn Kasten4c340c62012-01-27 12:33:54 -0800380 if (!track.enabled) {
381 track.enabled = true;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800382 ALOGV("enable(%d)", name);
383 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700384 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700385}
386
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800387void AudioMixer::disable(int name)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700388{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800389 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800390 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800391 track_t& track = mState.tracks[name];
392
Glenn Kasten4c340c62012-01-27 12:33:54 -0800393 if (track.enabled) {
394 track.enabled = false;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800395 ALOGV("disable(%d)", name);
396 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700397 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700398}
399
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800400void AudioMixer::setParameter(int name, int target, int param, void *value)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700401{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800402 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800403 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800404 track_t& track = mState.tracks[name];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700405
Mathias Agopian65ab4712010-07-14 17:59:35 -0700406 int valueInt = (int)value;
407 int32_t *valueBuf = (int32_t *)value;
408
409 switch (target) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700410
Mathias Agopian65ab4712010-07-14 17:59:35 -0700411 case TRACK:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800412 switch (param) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700413 case CHANNEL_MASK: {
Glenn Kasten254af182012-07-03 14:59:05 -0700414 audio_channel_mask_t mask = (audio_channel_mask_t) value;
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800415 if (track.channelMask != mask) {
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800416 uint32_t channelCount = popcount(mask);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700417 ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800418 track.channelMask = mask;
419 track.channelCount = channelCount;
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700420 // the mask has changed, does this track need a downmixer?
421 initTrackDownmix(&mState.tracks[name], name, mask);
Glenn Kasten788040c2011-05-05 08:19:00 -0700422 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800423 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700424 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700425 } break;
426 case MAIN_BUFFER:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800427 if (track.mainBuffer != valueBuf) {
428 track.mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100429 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800430 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700431 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700432 break;
433 case AUX_BUFFER:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800434 if (track.auxBuffer != valueBuf) {
435 track.auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100436 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800437 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700438 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700439 break;
Glenn Kastendeeb1282012-03-25 11:59:31 -0700440 case FORMAT:
441 ALOG_ASSERT(valueInt == AUDIO_FORMAT_PCM_16_BIT);
442 break;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700443 // FIXME do we want to support setting the downmix type from AudioFlinger?
444 // for a specific track? or per mixer?
445 /* case DOWNMIX_TYPE:
446 break */
Glenn Kasten788040c2011-05-05 08:19:00 -0700447 default:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800448 LOG_FATAL("bad param");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700449 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700450 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700451
Mathias Agopian65ab4712010-07-14 17:59:35 -0700452 case RESAMPLE:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800453 switch (param) {
454 case SAMPLE_RATE:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800455 ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
Glenn Kasten788040c2011-05-05 08:19:00 -0700456 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
457 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
458 uint32_t(valueInt));
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800459 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700460 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800461 break;
462 case RESET:
Eric Laurent243f5f92011-02-28 16:52:51 -0800463 track.resetResampler();
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800464 invalidateState(1 << name);
465 break;
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700466 case REMOVE:
467 delete track.resampler;
468 track.resampler = NULL;
469 track.sampleRate = mSampleRate;
470 invalidateState(1 << name);
471 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700472 default:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800473 LOG_FATAL("bad param");
Eric Laurent243f5f92011-02-28 16:52:51 -0800474 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700475 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700476
Mathias Agopian65ab4712010-07-14 17:59:35 -0700477 case RAMP_VOLUME:
478 case VOLUME:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800479 switch (param) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700480 case VOLUME0:
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800481 case VOLUME1:
482 if (track.volume[param-VOLUME0] != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100483 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800484 track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16;
485 track.volume[param-VOLUME0] = valueInt;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700486 if (target == VOLUME) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800487 track.prevVolume[param-VOLUME0] = valueInt << 16;
488 track.volumeInc[param-VOLUME0] = 0;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700489 } else {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800490 int32_t d = (valueInt<<16) - track.prevVolume[param-VOLUME0];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700491 int32_t volInc = d / int32_t(mState.frameCount);
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800492 track.volumeInc[param-VOLUME0] = volInc;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700493 if (volInc == 0) {
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800494 track.prevVolume[param-VOLUME0] = valueInt << 16;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700495 }
496 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800497 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700498 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800499 break;
500 case AUXLEVEL:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800501 //ALOG_ASSERT(0 <= valueInt && valueInt <= MAX_GAIN_INT, "bad aux level %d", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700502 if (track.auxLevel != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100503 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700504 track.prevAuxLevel = track.auxLevel << 16;
505 track.auxLevel = valueInt;
506 if (target == VOLUME) {
507 track.prevAuxLevel = valueInt << 16;
508 track.auxInc = 0;
509 } else {
510 int32_t d = (valueInt<<16) - track.prevAuxLevel;
511 int32_t volInc = d / int32_t(mState.frameCount);
512 track.auxInc = volInc;
513 if (volInc == 0) {
514 track.prevAuxLevel = valueInt << 16;
515 }
516 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800517 invalidateState(1 << name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700518 }
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800519 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700520 default:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800521 LOG_FATAL("bad param");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700522 }
523 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700524
525 default:
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800526 LOG_FATAL("bad target");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700527 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700528}
529
530bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
531{
Glenn Kasten4e2293f2012-04-12 09:39:07 -0700532 if (value != devSampleRate || resampler != NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700533 if (sampleRate != value) {
534 sampleRate = value;
Glenn Kastene0feee32011-12-13 11:53:26 -0800535 if (resampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700536 resampler = AudioResampler::create(
Jean-Michel Triviacb86cc2012-04-16 12:43:57 -0700537 format,
538 // the resampler sees the number of channels after the downmixer, if any
539 downmixerBufferProvider != NULL ? MAX_NUM_CHANNELS : channelCount,
540 devSampleRate);
Glenn Kasten52008f82012-03-18 09:34:41 -0700541 resampler->setLocalTimeFreq(sLocalTimeFreq);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700542 }
543 return true;
544 }
545 }
546 return false;
547}
548
Mathias Agopian65ab4712010-07-14 17:59:35 -0700549inline
550void AudioMixer::track_t::adjustVolumeRamp(bool aux)
551{
Glenn Kastenf9a27772012-01-06 07:47:26 -0800552 for (uint32_t i=0 ; i<MAX_NUM_CHANNELS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700553 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
554 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
555 volumeInc[i] = 0;
556 prevVolume[i] = volume[i]<<16;
557 }
558 }
559 if (aux) {
560 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
561 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
562 auxInc = 0;
563 prevAuxLevel = auxLevel<<16;
564 }
565 }
566}
567
Glenn Kastenc59c0042012-02-02 14:06:11 -0800568size_t AudioMixer::getUnreleasedFrames(int name) const
Eric Laurent071ccd52011-12-22 16:08:41 -0800569{
570 name -= TRACK0;
571 if (uint32_t(name) < MAX_NUM_TRACKS) {
Glenn Kastenc59c0042012-02-02 14:06:11 -0800572 return mState.tracks[name].getUnreleasedFrames();
Eric Laurent071ccd52011-12-22 16:08:41 -0800573 }
574 return 0;
575}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700576
Glenn Kasten01c4ebf2012-02-22 10:47:35 -0800577void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700578{
Glenn Kasten9c56d4a2011-12-19 15:06:39 -0800579 name -= TRACK0;
Glenn Kasten5798d4e2012-03-08 12:18:35 -0800580 ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700581
582 if (mState.tracks[name].downmixerBufferProvider != NULL) {
583 // update required?
584 if (mState.tracks[name].downmixerBufferProvider->mTrackBufferProvider != bufferProvider) {
585 ALOGV("AudioMixer::setBufferProvider(%p) for downmix", bufferProvider);
586 // setting the buffer provider for a track that gets downmixed consists in:
587 // 1/ setting the buffer provider to the "downmix / buffer provider" wrapper
588 // so it's the one that gets called when the buffer provider is needed,
589 mState.tracks[name].bufferProvider = mState.tracks[name].downmixerBufferProvider;
590 // 2/ saving the buffer provider for the track so the wrapper can use it
591 // when it downmixes.
592 mState.tracks[name].downmixerBufferProvider->mTrackBufferProvider = bufferProvider;
593 }
594 } else {
595 mState.tracks[name].bufferProvider = bufferProvider;
596 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700597}
598
599
600
John Grossman4ff14ba2012-02-08 16:37:41 -0800601void AudioMixer::process(int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700602{
John Grossman4ff14ba2012-02-08 16:37:41 -0800603 mState.hook(&mState, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700604}
605
606
John Grossman4ff14ba2012-02-08 16:37:41 -0800607void AudioMixer::process__validate(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700608{
Steve Block5ff1dd52012-01-05 23:22:43 +0000609 ALOGW_IF(!state->needsChanged,
Mathias Agopian65ab4712010-07-14 17:59:35 -0700610 "in process__validate() but nothing's invalid");
611
612 uint32_t changed = state->needsChanged;
613 state->needsChanged = 0; // clear the validation flag
614
615 // recompute which tracks are enabled / disabled
616 uint32_t enabled = 0;
617 uint32_t disabled = 0;
618 while (changed) {
619 const int i = 31 - __builtin_clz(changed);
620 const uint32_t mask = 1<<i;
621 changed &= ~mask;
622 track_t& t = state->tracks[i];
623 (t.enabled ? enabled : disabled) |= mask;
624 }
625 state->enabledTracks &= ~disabled;
626 state->enabledTracks |= enabled;
627
628 // compute everything we need...
629 int countActiveTracks = 0;
Glenn Kasten4c340c62012-01-27 12:33:54 -0800630 bool all16BitsStereoNoResample = true;
631 bool resampling = false;
632 bool volumeRamp = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700633 uint32_t en = state->enabledTracks;
634 while (en) {
635 const int i = 31 - __builtin_clz(en);
636 en &= ~(1<<i);
637
638 countActiveTracks++;
639 track_t& t = state->tracks[i];
640 uint32_t n = 0;
641 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
642 n |= NEEDS_FORMAT_16;
643 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
644 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
645 n |= NEEDS_AUX_ENABLED;
646 }
647
648 if (t.volumeInc[0]|t.volumeInc[1]) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800649 volumeRamp = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700650 } else if (!t.doesResample() && t.volumeRL == 0) {
651 n |= NEEDS_MUTE_ENABLED;
652 }
653 t.needs = n;
654
655 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
656 t.hook = track__nop;
657 } else {
658 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800659 all16BitsStereoNoResample = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700660 }
661 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800662 all16BitsStereoNoResample = false;
663 resampling = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700664 t.hook = track__genericResample;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700665 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700666 "Track %d needs downmix + resample", i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700667 } else {
668 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
669 t.hook = track__16BitsMono;
Glenn Kasten4c340c62012-01-27 12:33:54 -0800670 all16BitsStereoNoResample = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700671 }
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700672 if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
Mathias Agopian65ab4712010-07-14 17:59:35 -0700673 t.hook = track__16BitsStereo;
Jean-Michel Trivi7d5b2622012-04-04 18:54:36 -0700674 ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
Jean-Michel Trivi9bd23222012-04-16 13:43:48 -0700675 "Track %d needs downmix", i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700676 }
677 }
678 }
679 }
680
681 // select the processing hooks
682 state->hook = process__nop;
683 if (countActiveTracks) {
684 if (resampling) {
685 if (!state->outputTemp) {
686 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
687 }
688 if (!state->resampleTemp) {
689 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
690 }
691 state->hook = process__genericResampling;
692 } else {
693 if (state->outputTemp) {
694 delete [] state->outputTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800695 state->outputTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700696 }
697 if (state->resampleTemp) {
698 delete [] state->resampleTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800699 state->resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700700 }
701 state->hook = process__genericNoResampling;
702 if (all16BitsStereoNoResample && !volumeRamp) {
703 if (countActiveTracks == 1) {
704 state->hook = process__OneTrack16BitsStereoNoResampling;
705 }
706 }
707 }
708 }
709
Steve Block3856b092011-10-20 11:56:00 +0100710 ALOGV("mixer configuration change: %d activeTracks (%08x) "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700711 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
712 countActiveTracks, state->enabledTracks,
713 all16BitsStereoNoResample, resampling, volumeRamp);
714
John Grossman4ff14ba2012-02-08 16:37:41 -0800715 state->hook(state, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700716
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800717 // Now that the volume ramp has been done, set optimal state and
718 // track hooks for subsequent mixer process
719 if (countActiveTracks) {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800720 bool allMuted = true;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800721 uint32_t en = state->enabledTracks;
722 while (en) {
723 const int i = 31 - __builtin_clz(en);
724 en &= ~(1<<i);
725 track_t& t = state->tracks[i];
726 if (!t.doesResample() && t.volumeRL == 0)
727 {
728 t.needs |= NEEDS_MUTE_ENABLED;
729 t.hook = track__nop;
730 } else {
Glenn Kasten4c340c62012-01-27 12:33:54 -0800731 allMuted = false;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800732 }
733 }
734 if (allMuted) {
735 state->hook = process__nop;
736 } else if (all16BitsStereoNoResample) {
737 if (countActiveTracks == 1) {
738 state->hook = process__OneTrack16BitsStereoNoResampling;
739 }
740 }
741 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700742}
743
Mathias Agopian65ab4712010-07-14 17:59:35 -0700744
745void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
746{
747 t->resampler->setSampleRate(t->sampleRate);
748
749 // ramp gain - resample to temp buffer and scale/mix in 2nd step
750 if (aux != NULL) {
751 // always resample with unity gain when sending to auxiliary buffer to be able
752 // to apply send level after resampling
753 // TODO: modify each resampler to support aux channel?
754 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
755 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
756 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Glenn Kastenf6b16782011-12-15 09:51:17 -0800757 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700758 volumeRampStereo(t, out, outFrameCount, temp, aux);
759 } else {
760 volumeStereo(t, out, outFrameCount, temp, aux);
761 }
762 } else {
Glenn Kastenf6b16782011-12-15 09:51:17 -0800763 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700764 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
765 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
766 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
767 volumeRampStereo(t, out, outFrameCount, temp, aux);
768 }
769
770 // constant gain
771 else {
772 t->resampler->setVolume(t->volume[0], t->volume[1]);
773 t->resampler->resample(out, outFrameCount, t->bufferProvider);
774 }
775 }
776}
777
778void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
779{
780}
781
782void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
783{
784 int32_t vl = t->prevVolume[0];
785 int32_t vr = t->prevVolume[1];
786 const int32_t vlInc = t->volumeInc[0];
787 const int32_t vrInc = t->volumeInc[1];
788
Steve Blockb8a80522011-12-20 16:23:08 +0000789 //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700790 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
791 // (vl + vlInc*frameCount)/65536.0f, frameCount);
792
793 // ramp volume
Glenn Kastenf6b16782011-12-15 09:51:17 -0800794 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700795 int32_t va = t->prevAuxLevel;
796 const int32_t vaInc = t->auxInc;
797 int32_t l;
798 int32_t r;
799
800 do {
801 l = (*temp++ >> 12);
802 r = (*temp++ >> 12);
803 *out++ += (vl >> 16) * l;
804 *out++ += (vr >> 16) * r;
805 *aux++ += (va >> 17) * (l + r);
806 vl += vlInc;
807 vr += vrInc;
808 va += vaInc;
809 } while (--frameCount);
810 t->prevAuxLevel = va;
811 } else {
812 do {
813 *out++ += (vl >> 16) * (*temp++ >> 12);
814 *out++ += (vr >> 16) * (*temp++ >> 12);
815 vl += vlInc;
816 vr += vrInc;
817 } while (--frameCount);
818 }
819 t->prevVolume[0] = vl;
820 t->prevVolume[1] = vr;
Glenn Kastena1117922012-01-26 10:53:32 -0800821 t->adjustVolumeRamp(aux != NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700822}
823
824void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
825{
826 const int16_t vl = t->volume[0];
827 const int16_t vr = t->volume[1];
828
Glenn Kastenf6b16782011-12-15 09:51:17 -0800829 if (CC_UNLIKELY(aux != NULL)) {
Glenn Kasten3b81aca2012-01-27 15:26:23 -0800830 const int16_t va = t->auxLevel;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700831 do {
832 int16_t l = (int16_t)(*temp++ >> 12);
833 int16_t r = (int16_t)(*temp++ >> 12);
834 out[0] = mulAdd(l, vl, out[0]);
835 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
836 out[1] = mulAdd(r, vr, out[1]);
837 out += 2;
838 aux[0] = mulAdd(a, va, aux[0]);
839 aux++;
840 } while (--frameCount);
841 } else {
842 do {
843 int16_t l = (int16_t)(*temp++ >> 12);
844 int16_t r = (int16_t)(*temp++ >> 12);
845 out[0] = mulAdd(l, vl, out[0]);
846 out[1] = mulAdd(r, vr, out[1]);
847 out += 2;
848 } while (--frameCount);
849 }
850}
851
852void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
853{
Glenn Kasten54c3b662012-01-06 07:46:30 -0800854 const int16_t *in = static_cast<const int16_t *>(t->in);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700855
Glenn Kastenf6b16782011-12-15 09:51:17 -0800856 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700857 int32_t l;
858 int32_t r;
859 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800860 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700861 int32_t vl = t->prevVolume[0];
862 int32_t vr = t->prevVolume[1];
863 int32_t va = t->prevAuxLevel;
864 const int32_t vlInc = t->volumeInc[0];
865 const int32_t vrInc = t->volumeInc[1];
866 const int32_t vaInc = t->auxInc;
Steve Blockb8a80522011-12-20 16:23:08 +0000867 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700868 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
869 // (vl + vlInc*frameCount)/65536.0f, frameCount);
870
871 do {
872 l = (int32_t)*in++;
873 r = (int32_t)*in++;
874 *out++ += (vl >> 16) * l;
875 *out++ += (vr >> 16) * r;
876 *aux++ += (va >> 17) * (l + r);
877 vl += vlInc;
878 vr += vrInc;
879 va += vaInc;
880 } while (--frameCount);
881
882 t->prevVolume[0] = vl;
883 t->prevVolume[1] = vr;
884 t->prevAuxLevel = va;
885 t->adjustVolumeRamp(true);
886 }
887
888 // constant gain
889 else {
890 const uint32_t vrl = t->volumeRL;
891 const int16_t va = (int16_t)t->auxLevel;
892 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -0800893 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700894 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
895 in += 2;
896 out[0] = mulAddRL(1, rl, vrl, out[0]);
897 out[1] = mulAddRL(0, rl, vrl, out[1]);
898 out += 2;
899 aux[0] = mulAdd(a, va, aux[0]);
900 aux++;
901 } while (--frameCount);
902 }
903 } else {
904 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800905 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700906 int32_t vl = t->prevVolume[0];
907 int32_t vr = t->prevVolume[1];
908 const int32_t vlInc = t->volumeInc[0];
909 const int32_t vrInc = t->volumeInc[1];
910
Steve Blockb8a80522011-12-20 16:23:08 +0000911 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700912 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
913 // (vl + vlInc*frameCount)/65536.0f, frameCount);
914
915 do {
916 *out++ += (vl >> 16) * (int32_t) *in++;
917 *out++ += (vr >> 16) * (int32_t) *in++;
918 vl += vlInc;
919 vr += vrInc;
920 } while (--frameCount);
921
922 t->prevVolume[0] = vl;
923 t->prevVolume[1] = vr;
924 t->adjustVolumeRamp(false);
925 }
926
927 // constant gain
928 else {
929 const uint32_t vrl = t->volumeRL;
930 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -0800931 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700932 in += 2;
933 out[0] = mulAddRL(1, rl, vrl, out[0]);
934 out[1] = mulAddRL(0, rl, vrl, out[1]);
935 out += 2;
936 } while (--frameCount);
937 }
938 }
939 t->in = in;
940}
941
942void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
943{
Glenn Kasten54c3b662012-01-06 07:46:30 -0800944 const int16_t *in = static_cast<int16_t const *>(t->in);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700945
Glenn Kastenf6b16782011-12-15 09:51:17 -0800946 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700947 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800948 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700949 int32_t vl = t->prevVolume[0];
950 int32_t vr = t->prevVolume[1];
951 int32_t va = t->prevAuxLevel;
952 const int32_t vlInc = t->volumeInc[0];
953 const int32_t vrInc = t->volumeInc[1];
954 const int32_t vaInc = t->auxInc;
955
Steve Blockb8a80522011-12-20 16:23:08 +0000956 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700957 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
958 // (vl + vlInc*frameCount)/65536.0f, frameCount);
959
960 do {
961 int32_t l = *in++;
962 *out++ += (vl >> 16) * l;
963 *out++ += (vr >> 16) * l;
964 *aux++ += (va >> 16) * l;
965 vl += vlInc;
966 vr += vrInc;
967 va += vaInc;
968 } while (--frameCount);
969
970 t->prevVolume[0] = vl;
971 t->prevVolume[1] = vr;
972 t->prevAuxLevel = va;
973 t->adjustVolumeRamp(true);
974 }
975 // constant gain
976 else {
977 const int16_t vl = t->volume[0];
978 const int16_t vr = t->volume[1];
979 const int16_t va = (int16_t)t->auxLevel;
980 do {
981 int16_t l = *in++;
982 out[0] = mulAdd(l, vl, out[0]);
983 out[1] = mulAdd(l, vr, out[1]);
984 out += 2;
985 aux[0] = mulAdd(l, va, aux[0]);
986 aux++;
987 } while (--frameCount);
988 }
989 } else {
990 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800991 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700992 int32_t vl = t->prevVolume[0];
993 int32_t vr = t->prevVolume[1];
994 const int32_t vlInc = t->volumeInc[0];
995 const int32_t vrInc = t->volumeInc[1];
996
Steve Blockb8a80522011-12-20 16:23:08 +0000997 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700998 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
999 // (vl + vlInc*frameCount)/65536.0f, frameCount);
1000
1001 do {
1002 int32_t l = *in++;
1003 *out++ += (vl >> 16) * l;
1004 *out++ += (vr >> 16) * l;
1005 vl += vlInc;
1006 vr += vrInc;
1007 } while (--frameCount);
1008
1009 t->prevVolume[0] = vl;
1010 t->prevVolume[1] = vr;
1011 t->adjustVolumeRamp(false);
1012 }
1013 // constant gain
1014 else {
1015 const int16_t vl = t->volume[0];
1016 const int16_t vr = t->volume[1];
1017 do {
1018 int16_t l = *in++;
1019 out[0] = mulAdd(l, vl, out[0]);
1020 out[1] = mulAdd(l, vr, out[1]);
1021 out += 2;
1022 } while (--frameCount);
1023 }
1024 }
1025 t->in = in;
1026}
1027
Mathias Agopian65ab4712010-07-14 17:59:35 -07001028// no-op case
John Grossman4ff14ba2012-02-08 16:37:41 -08001029void AudioMixer::process__nop(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001030{
1031 uint32_t e0 = state->enabledTracks;
1032 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
1033 while (e0) {
1034 // process by group of tracks with same output buffer to
1035 // avoid multiple memset() on same buffer
1036 uint32_t e1 = e0, e2 = e0;
1037 int i = 31 - __builtin_clz(e1);
1038 track_t& t1 = state->tracks[i];
1039 e2 &= ~(1<<i);
1040 while (e2) {
1041 i = 31 - __builtin_clz(e2);
1042 e2 &= ~(1<<i);
1043 track_t& t2 = state->tracks[i];
Glenn Kastenf6b16782011-12-15 09:51:17 -08001044 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001045 e1 &= ~(1<<i);
1046 }
1047 }
1048 e0 &= ~(e1);
1049
1050 memset(t1.mainBuffer, 0, bufSize);
1051
1052 while (e1) {
1053 i = 31 - __builtin_clz(e1);
1054 e1 &= ~(1<<i);
1055 t1 = state->tracks[i];
1056 size_t outFrames = state->frameCount;
1057 while (outFrames) {
1058 t1.buffer.frameCount = outFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001059 int64_t outputPTS = calculateOutputPTS(
1060 t1, pts, state->frameCount - outFrames);
1061 t1.bufferProvider->getNextBuffer(&t1.buffer, outputPTS);
Glenn Kastena0d68332012-01-27 16:47:15 -08001062 if (t1.buffer.raw == NULL) break;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001063 outFrames -= t1.buffer.frameCount;
1064 t1.bufferProvider->releaseBuffer(&t1.buffer);
1065 }
1066 }
1067 }
1068}
1069
1070// generic code without resampling
John Grossman4ff14ba2012-02-08 16:37:41 -08001071void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001072{
1073 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
1074
1075 // acquire each track's buffer
1076 uint32_t enabledTracks = state->enabledTracks;
1077 uint32_t e0 = enabledTracks;
1078 while (e0) {
1079 const int i = 31 - __builtin_clz(e0);
1080 e0 &= ~(1<<i);
1081 track_t& t = state->tracks[i];
1082 t.buffer.frameCount = state->frameCount;
John Grossman4ff14ba2012-02-08 16:37:41 -08001083 t.bufferProvider->getNextBuffer(&t.buffer, pts);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001084 t.frameCount = t.buffer.frameCount;
1085 t.in = t.buffer.raw;
1086 // t.in == NULL can happen if the track was flushed just after having
1087 // been enabled for mixing.
1088 if (t.in == NULL)
1089 enabledTracks &= ~(1<<i);
1090 }
1091
1092 e0 = enabledTracks;
1093 while (e0) {
1094 // process by group of tracks with same output buffer to
1095 // optimize cache use
1096 uint32_t e1 = e0, e2 = e0;
1097 int j = 31 - __builtin_clz(e1);
1098 track_t& t1 = state->tracks[j];
1099 e2 &= ~(1<<j);
1100 while (e2) {
1101 j = 31 - __builtin_clz(e2);
1102 e2 &= ~(1<<j);
1103 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -08001104 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001105 e1 &= ~(1<<j);
1106 }
1107 }
1108 e0 &= ~(e1);
1109 // this assumes output 16 bits stereo, no resampling
1110 int32_t *out = t1.mainBuffer;
1111 size_t numFrames = 0;
1112 do {
1113 memset(outTemp, 0, sizeof(outTemp));
1114 e2 = e1;
1115 while (e2) {
1116 const int i = 31 - __builtin_clz(e2);
1117 e2 &= ~(1<<i);
1118 track_t& t = state->tracks[i];
1119 size_t outFrames = BLOCKSIZE;
1120 int32_t *aux = NULL;
Glenn Kastenf6b16782011-12-15 09:51:17 -08001121 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001122 aux = t.auxBuffer + numFrames;
1123 }
1124 while (outFrames) {
1125 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
1126 if (inFrames) {
Glenn Kastena1117922012-01-26 10:53:32 -08001127 t.hook(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001128 t.frameCount -= inFrames;
1129 outFrames -= inFrames;
Glenn Kastenf6b16782011-12-15 09:51:17 -08001130 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001131 aux += inFrames;
1132 }
1133 }
1134 if (t.frameCount == 0 && outFrames) {
1135 t.bufferProvider->releaseBuffer(&t.buffer);
1136 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
John Grossman4ff14ba2012-02-08 16:37:41 -08001137 int64_t outputPTS = calculateOutputPTS(
1138 t, pts, numFrames + (BLOCKSIZE - outFrames));
1139 t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001140 t.in = t.buffer.raw;
1141 if (t.in == NULL) {
1142 enabledTracks &= ~(1<<i);
1143 e1 &= ~(1<<i);
1144 break;
1145 }
1146 t.frameCount = t.buffer.frameCount;
1147 }
1148 }
1149 }
1150 ditherAndClamp(out, outTemp, BLOCKSIZE);
1151 out += BLOCKSIZE;
1152 numFrames += BLOCKSIZE;
1153 } while (numFrames < state->frameCount);
1154 }
1155
1156 // release each track's buffer
1157 e0 = enabledTracks;
1158 while (e0) {
1159 const int i = 31 - __builtin_clz(e0);
1160 e0 &= ~(1<<i);
1161 track_t& t = state->tracks[i];
1162 t.bufferProvider->releaseBuffer(&t.buffer);
1163 }
1164}
1165
1166
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001167// generic code with resampling
John Grossman4ff14ba2012-02-08 16:37:41 -08001168void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001169{
Glenn Kasten54c3b662012-01-06 07:46:30 -08001170 // this const just means that local variable outTemp doesn't change
Mathias Agopian65ab4712010-07-14 17:59:35 -07001171 int32_t* const outTemp = state->outputTemp;
1172 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001173
1174 size_t numFrames = state->frameCount;
1175
1176 uint32_t e0 = state->enabledTracks;
1177 while (e0) {
1178 // process by group of tracks with same output buffer
1179 // to optimize cache use
1180 uint32_t e1 = e0, e2 = e0;
1181 int j = 31 - __builtin_clz(e1);
1182 track_t& t1 = state->tracks[j];
1183 e2 &= ~(1<<j);
1184 while (e2) {
1185 j = 31 - __builtin_clz(e2);
1186 e2 &= ~(1<<j);
1187 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -08001188 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001189 e1 &= ~(1<<j);
1190 }
1191 }
1192 e0 &= ~(e1);
1193 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi2151d7b2011-02-04 15:24:34 +01001194 memset(outTemp, 0, size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001195 while (e1) {
1196 const int i = 31 - __builtin_clz(e1);
1197 e1 &= ~(1<<i);
1198 track_t& t = state->tracks[i];
1199 int32_t *aux = NULL;
Glenn Kastenf6b16782011-12-15 09:51:17 -08001200 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001201 aux = t.auxBuffer;
1202 }
1203
1204 // this is a little goofy, on the resampling case we don't
1205 // acquire/release the buffers because it's done by
1206 // the resampler.
1207 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
John Grossman4ff14ba2012-02-08 16:37:41 -08001208 t.resampler->setPTS(pts);
Glenn Kastena1117922012-01-26 10:53:32 -08001209 t.hook(&t, outTemp, numFrames, state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001210 } else {
1211
1212 size_t outFrames = 0;
1213
1214 while (outFrames < numFrames) {
1215 t.buffer.frameCount = numFrames - outFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001216 int64_t outputPTS = calculateOutputPTS(t, pts, outFrames);
1217 t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001218 t.in = t.buffer.raw;
1219 // t.in == NULL can happen if the track was flushed just after having
1220 // been enabled for mixing.
1221 if (t.in == NULL) break;
1222
Glenn Kastenf6b16782011-12-15 09:51:17 -08001223 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001224 aux += outFrames;
1225 }
Glenn Kastena1117922012-01-26 10:53:32 -08001226 t.hook(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001227 outFrames += t.buffer.frameCount;
1228 t.bufferProvider->releaseBuffer(&t.buffer);
1229 }
1230 }
1231 }
1232 ditherAndClamp(out, outTemp, numFrames);
1233 }
1234}
1235
1236// one track, 16 bits stereo without resampling is the most common case
John Grossman4ff14ba2012-02-08 16:37:41 -08001237void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state,
1238 int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001239{
Glenn Kasten99e53b82012-01-19 08:59:58 -08001240 // This method is only called when state->enabledTracks has exactly
1241 // one bit set. The asserts below would verify this, but are commented out
1242 // since the whole point of this method is to optimize performance.
Glenn Kasten5798d4e2012-03-08 12:18:35 -08001243 //ALOG_ASSERT(0 != state->enabledTracks, "no tracks enabled");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001244 const int i = 31 - __builtin_clz(state->enabledTracks);
Glenn Kasten5798d4e2012-03-08 12:18:35 -08001245 //ALOG_ASSERT((1 << i) == state->enabledTracks, "more than 1 track enabled");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001246 const track_t& t = state->tracks[i];
1247
1248 AudioBufferProvider::Buffer& b(t.buffer);
1249
1250 int32_t* out = t.mainBuffer;
1251 size_t numFrames = state->frameCount;
1252
1253 const int16_t vl = t.volume[0];
1254 const int16_t vr = t.volume[1];
1255 const uint32_t vrl = t.volumeRL;
1256 while (numFrames) {
1257 b.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001258 int64_t outputPTS = calculateOutputPTS(t, pts, out - t.mainBuffer);
1259 t.bufferProvider->getNextBuffer(&b, outputPTS);
Glenn Kasten54c3b662012-01-06 07:46:30 -08001260 const int16_t *in = b.i16;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001261
1262 // in == NULL can happen if the track was flushed just after having
1263 // been enabled for mixing.
1264 if (in == NULL || ((unsigned long)in & 3)) {
1265 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
Steve Block29357bc2012-01-06 19:20:56 +00001266 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 -07001267 in, i, t.channelCount, t.needs);
1268 return;
1269 }
1270 size_t outFrames = b.frameCount;
1271
Glenn Kastenf6b16782011-12-15 09:51:17 -08001272 if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001273 // volume is boosted, so we might need to clamp even though
1274 // we process only one track.
1275 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001276 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001277 in += 2;
1278 int32_t l = mulRL(1, rl, vrl) >> 12;
1279 int32_t r = mulRL(0, rl, vrl) >> 12;
1280 // clamping...
1281 l = clamp16(l);
1282 r = clamp16(r);
1283 *out++ = (r<<16) | (l & 0xFFFF);
1284 } while (--outFrames);
1285 } else {
1286 do {
Glenn Kasten54c3b662012-01-06 07:46:30 -08001287 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001288 in += 2;
1289 int32_t l = mulRL(1, rl, vrl) >> 12;
1290 int32_t r = mulRL(0, rl, vrl) >> 12;
1291 *out++ = (r<<16) | (l & 0xFFFF);
1292 } while (--outFrames);
1293 }
1294 numFrames -= b.frameCount;
1295 t.bufferProvider->releaseBuffer(&b);
1296 }
1297}
1298
Glenn Kasten81a028f2011-12-15 09:53:12 -08001299#if 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07001300// 2 tracks is also a common case
1301// NEVER used in current implementation of process__validate()
1302// only use if the 2 tracks have the same output buffer
John Grossman4ff14ba2012-02-08 16:37:41 -08001303void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state,
1304 int64_t pts)
Mathias Agopian65ab4712010-07-14 17:59:35 -07001305{
1306 int i;
1307 uint32_t en = state->enabledTracks;
1308
1309 i = 31 - __builtin_clz(en);
1310 const track_t& t0 = state->tracks[i];
1311 AudioBufferProvider::Buffer& b0(t0.buffer);
1312
1313 en &= ~(1<<i);
1314 i = 31 - __builtin_clz(en);
1315 const track_t& t1 = state->tracks[i];
1316 AudioBufferProvider::Buffer& b1(t1.buffer);
1317
Glenn Kasten54c3b662012-01-06 07:46:30 -08001318 const int16_t *in0;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001319 const int16_t vl0 = t0.volume[0];
1320 const int16_t vr0 = t0.volume[1];
1321 size_t frameCount0 = 0;
1322
Glenn Kasten54c3b662012-01-06 07:46:30 -08001323 const int16_t *in1;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001324 const int16_t vl1 = t1.volume[0];
1325 const int16_t vr1 = t1.volume[1];
1326 size_t frameCount1 = 0;
1327
1328 //FIXME: only works if two tracks use same buffer
1329 int32_t* out = t0.mainBuffer;
1330 size_t numFrames = state->frameCount;
Glenn Kasten54c3b662012-01-06 07:46:30 -08001331 const int16_t *buff = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001332
1333
1334 while (numFrames) {
1335
1336 if (frameCount0 == 0) {
1337 b0.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001338 int64_t outputPTS = calculateOutputPTS(t0, pts,
1339 out - t0.mainBuffer);
1340 t0.bufferProvider->getNextBuffer(&b0, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001341 if (b0.i16 == NULL) {
1342 if (buff == NULL) {
1343 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1344 }
1345 in0 = buff;
1346 b0.frameCount = numFrames;
1347 } else {
1348 in0 = b0.i16;
1349 }
1350 frameCount0 = b0.frameCount;
1351 }
1352 if (frameCount1 == 0) {
1353 b1.frameCount = numFrames;
John Grossman4ff14ba2012-02-08 16:37:41 -08001354 int64_t outputPTS = calculateOutputPTS(t1, pts,
1355 out - t0.mainBuffer);
1356 t1.bufferProvider->getNextBuffer(&b1, outputPTS);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001357 if (b1.i16 == NULL) {
1358 if (buff == NULL) {
1359 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1360 }
1361 in1 = buff;
1362 b1.frameCount = numFrames;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001363 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001364 in1 = b1.i16;
1365 }
1366 frameCount1 = b1.frameCount;
1367 }
1368
1369 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1370
1371 numFrames -= outFrames;
1372 frameCount0 -= outFrames;
1373 frameCount1 -= outFrames;
1374
1375 do {
1376 int32_t l0 = *in0++;
1377 int32_t r0 = *in0++;
1378 l0 = mul(l0, vl0);
1379 r0 = mul(r0, vr0);
1380 int32_t l = *in1++;
1381 int32_t r = *in1++;
1382 l = mulAdd(l, vl1, l0) >> 12;
1383 r = mulAdd(r, vr1, r0) >> 12;
1384 // clamping...
1385 l = clamp16(l);
1386 r = clamp16(r);
1387 *out++ = (r<<16) | (l & 0xFFFF);
1388 } while (--outFrames);
1389
1390 if (frameCount0 == 0) {
1391 t0.bufferProvider->releaseBuffer(&b0);
1392 }
1393 if (frameCount1 == 0) {
1394 t1.bufferProvider->releaseBuffer(&b1);
1395 }
1396 }
1397
Glenn Kastene9dd0172012-01-27 18:08:45 -08001398 delete [] buff;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001399}
Glenn Kasten81a028f2011-12-15 09:53:12 -08001400#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001401
John Grossman4ff14ba2012-02-08 16:37:41 -08001402int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS,
1403 int outputFrameIndex)
1404{
1405 if (AudioBufferProvider::kInvalidPTS == basePTS)
1406 return AudioBufferProvider::kInvalidPTS;
1407
Glenn Kasten52008f82012-03-18 09:34:41 -07001408 return basePTS + ((outputFrameIndex * sLocalTimeFreq) / t.sampleRate);
1409}
1410
1411/*static*/ uint64_t AudioMixer::sLocalTimeFreq;
1412/*static*/ pthread_once_t AudioMixer::sOnceControl = PTHREAD_ONCE_INIT;
1413
1414/*static*/ void AudioMixer::sInitRoutine()
1415{
1416 LocalClock lc;
1417 sLocalTimeFreq = lc.getLocalFreq();
John Grossman4ff14ba2012-02-08 16:37:41 -08001418}
1419
Mathias Agopian65ab4712010-07-14 17:59:35 -07001420// ----------------------------------------------------------------------------
1421}; // namespace android