blob: 3a030928d43ddafb128bbcd946e3f6c1f9f31285 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/include/server/AudioFlinger/AudioMixer.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "AudioMixer"
The Android Open Source Project10592532009-03-18 17:39:46 -070019//#define LOG_NDEBUG 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020
Glenn Kastenafb40b52011-12-15 15:46:46 -080021#include <assert.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include <stdint.h>
23#include <string.h>
24#include <stdlib.h>
25#include <sys/types.h>
26
27#include <utils/Errors.h>
28#include <utils/Log.h>
29
Jean-Michel Trivi54392232011-05-24 15:53:33 -070030#include <cutils/bitops.h>
Glenn Kastene80a4cc2011-12-15 09:51:17 -080031#include <cutils/compiler.h>
Jean-Michel Trivi54392232011-05-24 15:53:33 -070032
33#include <system/audio.h>
34
Glenn Kasten490909d2011-12-15 09:52:39 -080035#include <audio_utils/primitives.h>
36
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037#include "AudioMixer.h"
38
39namespace android {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040
41// ----------------------------------------------------------------------------
42
43AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
Glenn Kasten68deb152011-12-19 15:06:39 -080044 : mTrackNames(0), mSampleRate(sampleRate)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045{
Glenn Kastenbde164ab2011-05-05 08:19:00 -070046 // AudioMixer is not yet capable of multi-channel beyond stereo
47 assert(2 == MAX_NUM_CHANNELS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 mState.enabledTracks= 0;
49 mState.needsChanged = 0;
50 mState.frameCount = frameCount;
Glenn Kastendc3ac852012-01-25 15:28:08 -080051 mState.hook = process__nop;
Glenn Kastenc434c902011-12-13 11:53:26 -080052 mState.outputTemp = NULL;
53 mState.resampleTemp = NULL;
Glenn Kastendc3ac852012-01-25 15:28:08 -080054 // mState.reserved
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 track_t* t = mState.tracks;
Glenn Kasten1f6f05d2011-12-13 11:52:35 -080056 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 t->needs = 0;
58 t->volume[0] = UNITY_GAIN;
59 t->volume[1] = UNITY_GAIN;
Glenn Kastena763b442011-12-13 11:58:23 -080060 // no initialization needed
61 // t->prevVolume[0]
62 // t->prevVolume[1]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 t->volumeInc[0] = 0;
64 t->volumeInc[1] = 0;
Eric Laurent65b65452010-06-01 23:49:17 -070065 t->auxLevel = 0;
66 t->auxInc = 0;
Glenn Kastena763b442011-12-13 11:58:23 -080067 // no initialization needed
68 // t->prevAuxLevel
69 // t->frameCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 t->channelCount = 2;
Glenn Kasten450b9982012-01-27 12:33:54 -080071 t->enabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 t->format = 16;
Jean-Michel Trivi54392232011-05-24 15:53:33 -070073 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
Glenn Kastenc434c902011-12-13 11:53:26 -080074 t->bufferProvider = NULL;
Glenn Kastendc3ac852012-01-25 15:28:08 -080075 t->buffer.raw = NULL;
76 // t->buffer.frameCount
Glenn Kastenc434c902011-12-13 11:53:26 -080077 t->hook = NULL;
Glenn Kastendc3ac852012-01-25 15:28:08 -080078 t->in = NULL;
Glenn Kastenc434c902011-12-13 11:53:26 -080079 t->resampler = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 t->sampleRate = mSampleRate;
Eric Laurent65b65452010-06-01 23:49:17 -070081 t->mainBuffer = NULL;
82 t->auxBuffer = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 t++;
84 }
85}
86
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -080087AudioMixer::~AudioMixer()
88{
89 track_t* t = mState.tracks;
Glenn Kasten1f6f05d2011-12-13 11:52:35 -080090 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -080091 delete t->resampler;
92 t++;
93 }
94 delete [] mState.outputTemp;
95 delete [] mState.resampleTemp;
96}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -080098int AudioMixer::getTrackName()
99{
Glenn Kastenc1d810d2011-12-15 14:38:29 -0800100 uint32_t names = ~mTrackNames;
101 if (names != 0) {
102 int n = __builtin_ctz(names);
Steve Block71f2cf12011-10-20 11:56:00 +0100103 ALOGV("add track (%d)", n);
Glenn Kastenc1d810d2011-12-15 14:38:29 -0800104 mTrackNames |= 1 << n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 return TRACK0 + n;
106 }
107 return -1;
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800108}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800110void AudioMixer::invalidateState(uint32_t mask)
111{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 if (mask) {
113 mState.needsChanged |= mask;
114 mState.hook = process__validate;
115 }
116 }
117
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800118void AudioMixer::deleteTrackName(int name)
119{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 name -= TRACK0;
Glenn Kastenb3719252011-12-15 15:32:27 -0800121 assert(uint32_t(name) < MAX_NUM_TRACKS);
122 ALOGV("deleteTrackName(%d)", name);
123 track_t& track(mState.tracks[ name ]);
Glenn Kasten450b9982012-01-27 12:33:54 -0800124 if (track.enabled) {
125 track.enabled = false;
Glenn Kastenb3719252011-12-15 15:32:27 -0800126 invalidateState(1<<name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 }
Glenn Kasten3694ec12012-01-27 16:47:15 -0800128 if (track.resampler != NULL) {
Glenn Kastenb3719252011-12-15 15:32:27 -0800129 // delete the resampler
130 delete track.resampler;
131 track.resampler = NULL;
132 track.sampleRate = mSampleRate;
133 invalidateState(1<<name);
134 }
135 track.volumeInc[0] = 0;
136 track.volumeInc[1] = 0;
137 mTrackNames &= ~(1<<name);
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800138}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139
Glenn Kasten68deb152011-12-19 15:06:39 -0800140void AudioMixer::enable(int name)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141{
Glenn Kasten68deb152011-12-19 15:06:39 -0800142 name -= TRACK0;
143 assert(uint32_t(name) < MAX_NUM_TRACKS);
144 track_t& track = mState.tracks[name];
145
Glenn Kasten450b9982012-01-27 12:33:54 -0800146 if (!track.enabled) {
147 track.enabled = true;
Glenn Kasten68deb152011-12-19 15:06:39 -0800148 ALOGV("enable(%d)", name);
149 invalidateState(1 << name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151}
152
Glenn Kasten68deb152011-12-19 15:06:39 -0800153void AudioMixer::disable(int name)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154{
Glenn Kasten68deb152011-12-19 15:06:39 -0800155 name -= TRACK0;
156 assert(uint32_t(name) < MAX_NUM_TRACKS);
157 track_t& track = mState.tracks[name];
158
Glenn Kasten450b9982012-01-27 12:33:54 -0800159 if (track.enabled) {
160 track.enabled = false;
Glenn Kasten68deb152011-12-19 15:06:39 -0800161 ALOGV("disable(%d)", name);
162 invalidateState(1 << name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164}
165
Glenn Kasten68deb152011-12-19 15:06:39 -0800166void AudioMixer::setParameter(int name, int target, int param, void *value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167{
Glenn Kasten68deb152011-12-19 15:06:39 -0800168 name -= TRACK0;
169 assert(uint32_t(name) < MAX_NUM_TRACKS);
170 track_t& track = mState.tracks[name];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171
Eric Laurent65b65452010-06-01 23:49:17 -0700172 int valueInt = (int)value;
173 int32_t *valueBuf = (int32_t *)value;
174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 switch (target) {
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 case TRACK:
Glenn Kasten68deb152011-12-19 15:06:39 -0800178 switch (param) {
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700179 case CHANNEL_MASK: {
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700180 uint32_t mask = (uint32_t)value;
Glenn Kasten68deb152011-12-19 15:06:39 -0800181 if (track.channelMask != mask) {
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700182 uint8_t channelCount = popcount(mask);
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700183 assert((channelCount <= MAX_NUM_CHANNELS) && (channelCount));
Glenn Kasten68deb152011-12-19 15:06:39 -0800184 track.channelMask = mask;
185 track.channelCount = channelCount;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700186 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
Glenn Kasten68deb152011-12-19 15:06:39 -0800187 invalidateState(1 << name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700189 } break;
190 case MAIN_BUFFER:
Glenn Kasten68deb152011-12-19 15:06:39 -0800191 if (track.mainBuffer != valueBuf) {
192 track.mainBuffer = valueBuf;
Steve Block71f2cf12011-10-20 11:56:00 +0100193 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Glenn Kasten68deb152011-12-19 15:06:39 -0800194 invalidateState(1 << name);
Eric Laurent65b65452010-06-01 23:49:17 -0700195 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700196 break;
197 case AUX_BUFFER:
Glenn Kasten68deb152011-12-19 15:06:39 -0800198 if (track.auxBuffer != valueBuf) {
199 track.auxBuffer = valueBuf;
Steve Block71f2cf12011-10-20 11:56:00 +0100200 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Glenn Kasten68deb152011-12-19 15:06:39 -0800201 invalidateState(1 << name);
Eric Laurent65b65452010-06-01 23:49:17 -0700202 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700203 break;
204 default:
Glenn Kasten68deb152011-12-19 15:06:39 -0800205 // bad param
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700206 assert(false);
Eric Laurent65b65452010-06-01 23:49:17 -0700207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 break;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 case RESAMPLE:
Glenn Kasten68deb152011-12-19 15:06:39 -0800211 switch (param) {
212 case SAMPLE_RATE:
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700213 assert(valueInt > 0);
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700214 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
215 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
216 uint32_t(valueInt));
Glenn Kasten68deb152011-12-19 15:06:39 -0800217 invalidateState(1 << name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 }
Glenn Kasten68deb152011-12-19 15:06:39 -0800219 break;
220 case RESET:
Eric Laurent4bb21c42011-02-28 16:52:51 -0800221 track.resetResampler();
Glenn Kasten68deb152011-12-19 15:06:39 -0800222 invalidateState(1 << name);
223 break;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700224 default:
Glenn Kasten68deb152011-12-19 15:06:39 -0800225 // bad param
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700226 assert(false);
Eric Laurent4bb21c42011-02-28 16:52:51 -0800227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 break;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 case RAMP_VOLUME:
231 case VOLUME:
Glenn Kasten68deb152011-12-19 15:06:39 -0800232 switch (param) {
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700233 case VOLUME0:
Glenn Kasten68deb152011-12-19 15:06:39 -0800234 case VOLUME1:
235 if (track.volume[param-VOLUME0] != valueInt) {
Steve Block71f2cf12011-10-20 11:56:00 +0100236 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Glenn Kasten68deb152011-12-19 15:06:39 -0800237 track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16;
238 track.volume[param-VOLUME0] = valueInt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 if (target == VOLUME) {
Glenn Kasten68deb152011-12-19 15:06:39 -0800240 track.prevVolume[param-VOLUME0] = valueInt << 16;
241 track.volumeInc[param-VOLUME0] = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 } else {
Glenn Kasten68deb152011-12-19 15:06:39 -0800243 int32_t d = (valueInt<<16) - track.prevVolume[param-VOLUME0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 int32_t volInc = d / int32_t(mState.frameCount);
Glenn Kasten68deb152011-12-19 15:06:39 -0800245 track.volumeInc[param-VOLUME0] = volInc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 if (volInc == 0) {
Glenn Kasten68deb152011-12-19 15:06:39 -0800247 track.prevVolume[param-VOLUME0] = valueInt << 16;
Eric Laurent65b65452010-06-01 23:49:17 -0700248 }
249 }
Glenn Kasten68deb152011-12-19 15:06:39 -0800250 invalidateState(1 << name);
Eric Laurent65b65452010-06-01 23:49:17 -0700251 }
Glenn Kasten68deb152011-12-19 15:06:39 -0800252 break;
253 case AUXLEVEL:
Eric Laurent65b65452010-06-01 23:49:17 -0700254 if (track.auxLevel != valueInt) {
Steve Block71f2cf12011-10-20 11:56:00 +0100255 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Eric Laurent65b65452010-06-01 23:49:17 -0700256 track.prevAuxLevel = track.auxLevel << 16;
257 track.auxLevel = valueInt;
258 if (target == VOLUME) {
259 track.prevAuxLevel = valueInt << 16;
260 track.auxInc = 0;
261 } else {
262 int32_t d = (valueInt<<16) - track.prevAuxLevel;
263 int32_t volInc = d / int32_t(mState.frameCount);
264 track.auxInc = volInc;
265 if (volInc == 0) {
266 track.prevAuxLevel = valueInt << 16;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 }
268 }
Glenn Kasten68deb152011-12-19 15:06:39 -0800269 invalidateState(1 << name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 }
Glenn Kasten68deb152011-12-19 15:06:39 -0800271 break;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700272 default:
Glenn Kasten68deb152011-12-19 15:06:39 -0800273 // bad param
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700274 assert(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 }
276 break;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700277
278 default:
279 // bad target
280 assert(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282}
283
284bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
285{
286 if (value!=devSampleRate || resampler) {
287 if (sampleRate != value) {
288 sampleRate = value;
Glenn Kastenc434c902011-12-13 11:53:26 -0800289 if (resampler == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 resampler = AudioResampler::create(
291 format, channelCount, devSampleRate);
292 }
293 return true;
294 }
295 }
296 return false;
297}
298
299bool AudioMixer::track_t::doesResample() const
300{
Glenn Kastenc434c902011-12-13 11:53:26 -0800301 return resampler != NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302}
303
Eric Laurent4bb21c42011-02-28 16:52:51 -0800304void AudioMixer::track_t::resetResampler()
305{
Glenn Kastenc434c902011-12-13 11:53:26 -0800306 if (resampler != NULL) {
Eric Laurent4bb21c42011-02-28 16:52:51 -0800307 resampler->reset();
308 }
309}
310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311inline
Eric Laurent65b65452010-06-01 23:49:17 -0700312void AudioMixer::track_t::adjustVolumeRamp(bool aux)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313{
Glenn Kastenadda27a2012-01-06 07:47:26 -0800314 for (uint32_t i=0 ; i<MAX_NUM_CHANNELS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
316 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
317 volumeInc[i] = 0;
318 prevVolume[i] = volume[i]<<16;
319 }
320 }
Eric Laurent65b65452010-06-01 23:49:17 -0700321 if (aux) {
322 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
323 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
324 auxInc = 0;
325 prevAuxLevel = auxLevel<<16;
326 }
327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328}
329
Eric Laurent72dafb22011-12-22 16:08:41 -0800330size_t AudioMixer::track_t::getUnreleasedFrames()
331{
332 if (resampler != NULL) {
333 return resampler->getUnreleasedFrames();
334 }
335 return 0;
336}
337
338size_t AudioMixer::getUnreleasedFrames(int name)
339{
340 name -= TRACK0;
341 if (uint32_t(name) < MAX_NUM_TRACKS) {
342 track_t& track(mState.tracks[name]);
343 return track.getUnreleasedFrames();
344 }
345 return 0;
346}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347
Glenn Kasten68deb152011-12-19 15:06:39 -0800348void AudioMixer::setBufferProvider(int name, AudioBufferProvider* buffer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349{
Glenn Kasten68deb152011-12-19 15:06:39 -0800350 name -= TRACK0;
351 assert(uint32_t(name) < MAX_NUM_TRACKS);
352 mState.tracks[name].bufferProvider = buffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353}
354
355
356
Eric Laurent65b65452010-06-01 23:49:17 -0700357void AudioMixer::process()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358{
Eric Laurent65b65452010-06-01 23:49:17 -0700359 mState.hook(&mState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360}
361
362
Eric Laurent65b65452010-06-01 23:49:17 -0700363void AudioMixer::process__validate(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364{
Steve Block8564c8d2012-01-05 23:22:43 +0000365 ALOGW_IF(!state->needsChanged,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 "in process__validate() but nothing's invalid");
367
368 uint32_t changed = state->needsChanged;
369 state->needsChanged = 0; // clear the validation flag
370
371 // recompute which tracks are enabled / disabled
372 uint32_t enabled = 0;
373 uint32_t disabled = 0;
374 while (changed) {
375 const int i = 31 - __builtin_clz(changed);
376 const uint32_t mask = 1<<i;
377 changed &= ~mask;
378 track_t& t = state->tracks[i];
379 (t.enabled ? enabled : disabled) |= mask;
380 }
381 state->enabledTracks &= ~disabled;
382 state->enabledTracks |= enabled;
383
384 // compute everything we need...
385 int countActiveTracks = 0;
Glenn Kasten450b9982012-01-27 12:33:54 -0800386 bool all16BitsStereoNoResample = true;
387 bool resampling = false;
388 bool volumeRamp = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 uint32_t en = state->enabledTracks;
390 while (en) {
391 const int i = 31 - __builtin_clz(en);
392 en &= ~(1<<i);
393
394 countActiveTracks++;
395 track_t& t = state->tracks[i];
396 uint32_t n = 0;
397 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
398 n |= NEEDS_FORMAT_16;
399 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
Eric Laurent65b65452010-06-01 23:49:17 -0700400 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
401 n |= NEEDS_AUX_ENABLED;
402 }
403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 if (t.volumeInc[0]|t.volumeInc[1]) {
Glenn Kasten450b9982012-01-27 12:33:54 -0800405 volumeRamp = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 } else if (!t.doesResample() && t.volumeRL == 0) {
407 n |= NEEDS_MUTE_ENABLED;
408 }
409 t.needs = n;
410
411 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
412 t.hook = track__nop;
413 } else {
Eric Laurent65b65452010-06-01 23:49:17 -0700414 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
Glenn Kasten450b9982012-01-27 12:33:54 -0800415 all16BitsStereoNoResample = false;
Eric Laurent65b65452010-06-01 23:49:17 -0700416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
Glenn Kasten450b9982012-01-27 12:33:54 -0800418 all16BitsStereoNoResample = false;
419 resampling = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 t.hook = track__genericResample;
421 } else {
422 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
423 t.hook = track__16BitsMono;
Glenn Kasten450b9982012-01-27 12:33:54 -0800424 all16BitsStereoNoResample = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 }
426 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
427 t.hook = track__16BitsStereo;
428 }
429 }
430 }
431 }
432
433 // select the processing hooks
434 state->hook = process__nop;
435 if (countActiveTracks) {
436 if (resampling) {
437 if (!state->outputTemp) {
438 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
439 }
440 if (!state->resampleTemp) {
441 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
442 }
443 state->hook = process__genericResampling;
444 } else {
445 if (state->outputTemp) {
446 delete [] state->outputTemp;
Glenn Kastenc434c902011-12-13 11:53:26 -0800447 state->outputTemp = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 }
449 if (state->resampleTemp) {
450 delete [] state->resampleTemp;
Glenn Kastenc434c902011-12-13 11:53:26 -0800451 state->resampleTemp = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 }
453 state->hook = process__genericNoResampling;
454 if (all16BitsStereoNoResample && !volumeRamp) {
455 if (countActiveTracks == 1) {
456 state->hook = process__OneTrack16BitsStereoNoResampling;
457 }
458 }
459 }
460 }
461
Steve Block71f2cf12011-10-20 11:56:00 +0100462 ALOGV("mixer configuration change: %d activeTracks (%08x) "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
464 countActiveTracks, state->enabledTracks,
465 all16BitsStereoNoResample, resampling, volumeRamp);
466
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800467 state->hook(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800469 // Now that the volume ramp has been done, set optimal state and
470 // track hooks for subsequent mixer process
471 if (countActiveTracks) {
Glenn Kasten450b9982012-01-27 12:33:54 -0800472 bool allMuted = true;
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800473 uint32_t en = state->enabledTracks;
474 while (en) {
475 const int i = 31 - __builtin_clz(en);
476 en &= ~(1<<i);
477 track_t& t = state->tracks[i];
478 if (!t.doesResample() && t.volumeRL == 0)
479 {
480 t.needs |= NEEDS_MUTE_ENABLED;
481 t.hook = track__nop;
482 } else {
Glenn Kasten450b9982012-01-27 12:33:54 -0800483 allMuted = false;
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800484 }
485 }
486 if (allMuted) {
487 state->hook = process__nop;
488 } else if (all16BitsStereoNoResample) {
489 if (countActiveTracks == 1) {
490 state->hook = process__OneTrack16BitsStereoNoResampling;
491 }
492 }
493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494}
495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496
Eric Laurent65b65452010-06-01 23:49:17 -0700497void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498{
499 t->resampler->setSampleRate(t->sampleRate);
500
501 // ramp gain - resample to temp buffer and scale/mix in 2nd step
Eric Laurent65b65452010-06-01 23:49:17 -0700502 if (aux != NULL) {
503 // always resample with unity gain when sending to auxiliary buffer to be able
504 // to apply send level after resampling
505 // TODO: modify each resampler to support aux channel?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
507 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
508 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800509 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700510 volumeRampStereo(t, out, outFrameCount, temp, aux);
511 } else {
512 volumeStereo(t, out, outFrameCount, temp, aux);
513 }
514 } else {
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800515 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Eric Laurent65b65452010-06-01 23:49:17 -0700516 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
517 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
518 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
519 volumeRampStereo(t, out, outFrameCount, temp, aux);
520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521
Eric Laurent65b65452010-06-01 23:49:17 -0700522 // constant gain
523 else {
524 t->resampler->setVolume(t->volume[0], t->volume[1]);
525 t->resampler->resample(out, outFrameCount, t->bufferProvider);
526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 }
528}
529
Eric Laurent65b65452010-06-01 23:49:17 -0700530void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531{
532}
533
Eric Laurent65b65452010-06-01 23:49:17 -0700534void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535{
536 int32_t vl = t->prevVolume[0];
537 int32_t vr = t->prevVolume[1];
538 const int32_t vlInc = t->volumeInc[0];
539 const int32_t vrInc = t->volumeInc[1];
540
Steve Block5baa3a62011-12-20 16:23:08 +0000541 //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
543 // (vl + vlInc*frameCount)/65536.0f, frameCount);
Eric Laurent65b65452010-06-01 23:49:17 -0700544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 // ramp volume
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800546 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700547 int32_t va = t->prevAuxLevel;
548 const int32_t vaInc = t->auxInc;
549 int32_t l;
550 int32_t r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551
552 do {
Eric Laurent65b65452010-06-01 23:49:17 -0700553 l = (*temp++ >> 12);
554 r = (*temp++ >> 12);
555 *out++ += (vl >> 16) * l;
556 *out++ += (vr >> 16) * r;
557 *aux++ += (va >> 17) * (l + r);
558 vl += vlInc;
559 vr += vrInc;
560 va += vaInc;
561 } while (--frameCount);
562 t->prevAuxLevel = va;
563 } else {
564 do {
565 *out++ += (vl >> 16) * (*temp++ >> 12);
566 *out++ += (vr >> 16) * (*temp++ >> 12);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 vl += vlInc;
568 vr += vrInc;
569 } while (--frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
Eric Laurent65b65452010-06-01 23:49:17 -0700571 t->prevVolume[0] = vl;
572 t->prevVolume[1] = vr;
573 t->adjustVolumeRamp((aux != NULL));
574}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575
Eric Laurent65b65452010-06-01 23:49:17 -0700576void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
577{
578 const int16_t vl = t->volume[0];
579 const int16_t vr = t->volume[1];
580
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800581 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700582 const int16_t va = (int16_t)t->auxLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 do {
Eric Laurent65b65452010-06-01 23:49:17 -0700584 int16_t l = (int16_t)(*temp++ >> 12);
585 int16_t r = (int16_t)(*temp++ >> 12);
586 out[0] = mulAdd(l, vl, out[0]);
587 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
588 out[1] = mulAdd(r, vr, out[1]);
589 out += 2;
590 aux[0] = mulAdd(a, va, aux[0]);
591 aux++;
592 } while (--frameCount);
593 } else {
594 do {
595 int16_t l = (int16_t)(*temp++ >> 12);
596 int16_t r = (int16_t)(*temp++ >> 12);
597 out[0] = mulAdd(l, vl, out[0]);
598 out[1] = mulAdd(r, vr, out[1]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 out += 2;
600 } while (--frameCount);
601 }
Eric Laurent65b65452010-06-01 23:49:17 -0700602}
603
604void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
605{
Glenn Kasten99c2fd32012-01-06 07:46:30 -0800606 const int16_t *in = static_cast<const int16_t *>(t->in);
Eric Laurent65b65452010-06-01 23:49:17 -0700607
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800608 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700609 int32_t l;
610 int32_t r;
611 // ramp gain
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800612 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700613 int32_t vl = t->prevVolume[0];
614 int32_t vr = t->prevVolume[1];
615 int32_t va = t->prevAuxLevel;
616 const int32_t vlInc = t->volumeInc[0];
617 const int32_t vrInc = t->volumeInc[1];
618 const int32_t vaInc = t->auxInc;
Steve Block5baa3a62011-12-20 16:23:08 +0000619 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Eric Laurent65b65452010-06-01 23:49:17 -0700620 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
621 // (vl + vlInc*frameCount)/65536.0f, frameCount);
622
623 do {
624 l = (int32_t)*in++;
625 r = (int32_t)*in++;
626 *out++ += (vl >> 16) * l;
627 *out++ += (vr >> 16) * r;
628 *aux++ += (va >> 17) * (l + r);
629 vl += vlInc;
630 vr += vrInc;
631 va += vaInc;
632 } while (--frameCount);
633
634 t->prevVolume[0] = vl;
635 t->prevVolume[1] = vr;
636 t->prevAuxLevel = va;
637 t->adjustVolumeRamp(true);
638 }
639
640 // constant gain
641 else {
642 const uint32_t vrl = t->volumeRL;
643 const int16_t va = (int16_t)t->auxLevel;
644 do {
Glenn Kasten99c2fd32012-01-06 07:46:30 -0800645 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Eric Laurent65b65452010-06-01 23:49:17 -0700646 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
647 in += 2;
648 out[0] = mulAddRL(1, rl, vrl, out[0]);
649 out[1] = mulAddRL(0, rl, vrl, out[1]);
650 out += 2;
651 aux[0] = mulAdd(a, va, aux[0]);
652 aux++;
653 } while (--frameCount);
654 }
655 } else {
656 // ramp gain
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800657 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Eric Laurent65b65452010-06-01 23:49:17 -0700658 int32_t vl = t->prevVolume[0];
659 int32_t vr = t->prevVolume[1];
660 const int32_t vlInc = t->volumeInc[0];
661 const int32_t vrInc = t->volumeInc[1];
662
Steve Block5baa3a62011-12-20 16:23:08 +0000663 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Eric Laurent65b65452010-06-01 23:49:17 -0700664 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
665 // (vl + vlInc*frameCount)/65536.0f, frameCount);
666
667 do {
668 *out++ += (vl >> 16) * (int32_t) *in++;
669 *out++ += (vr >> 16) * (int32_t) *in++;
670 vl += vlInc;
671 vr += vrInc;
672 } while (--frameCount);
673
674 t->prevVolume[0] = vl;
675 t->prevVolume[1] = vr;
676 t->adjustVolumeRamp(false);
677 }
678
679 // constant gain
680 else {
681 const uint32_t vrl = t->volumeRL;
682 do {
Glenn Kasten99c2fd32012-01-06 07:46:30 -0800683 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
Eric Laurent65b65452010-06-01 23:49:17 -0700684 in += 2;
685 out[0] = mulAddRL(1, rl, vrl, out[0]);
686 out[1] = mulAddRL(0, rl, vrl, out[1]);
687 out += 2;
688 } while (--frameCount);
689 }
690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 t->in = in;
692}
693
Eric Laurent65b65452010-06-01 23:49:17 -0700694void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695{
Glenn Kasten99c2fd32012-01-06 07:46:30 -0800696 const int16_t *in = static_cast<int16_t const *>(t->in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800698 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700699 // ramp gain
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800700 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700701 int32_t vl = t->prevVolume[0];
702 int32_t vr = t->prevVolume[1];
703 int32_t va = t->prevAuxLevel;
704 const int32_t vlInc = t->volumeInc[0];
705 const int32_t vrInc = t->volumeInc[1];
706 const int32_t vaInc = t->auxInc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707
Steve Block5baa3a62011-12-20 16:23:08 +0000708 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Eric Laurent65b65452010-06-01 23:49:17 -0700709 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
710 // (vl + vlInc*frameCount)/65536.0f, frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711
Eric Laurent65b65452010-06-01 23:49:17 -0700712 do {
713 int32_t l = *in++;
714 *out++ += (vl >> 16) * l;
715 *out++ += (vr >> 16) * l;
716 *aux++ += (va >> 16) * l;
717 vl += vlInc;
718 vr += vrInc;
719 va += vaInc;
720 } while (--frameCount);
721
722 t->prevVolume[0] = vl;
723 t->prevVolume[1] = vr;
724 t->prevAuxLevel = va;
725 t->adjustVolumeRamp(true);
726 }
727 // constant gain
728 else {
729 const int16_t vl = t->volume[0];
730 const int16_t vr = t->volume[1];
731 const int16_t va = (int16_t)t->auxLevel;
732 do {
733 int16_t l = *in++;
734 out[0] = mulAdd(l, vl, out[0]);
735 out[1] = mulAdd(l, vr, out[1]);
736 out += 2;
737 aux[0] = mulAdd(l, va, aux[0]);
738 aux++;
739 } while (--frameCount);
740 }
741 } else {
742 // ramp gain
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800743 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Eric Laurent65b65452010-06-01 23:49:17 -0700744 int32_t vl = t->prevVolume[0];
745 int32_t vr = t->prevVolume[1];
746 const int32_t vlInc = t->volumeInc[0];
747 const int32_t vrInc = t->volumeInc[1];
748
Steve Block5baa3a62011-12-20 16:23:08 +0000749 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Eric Laurent65b65452010-06-01 23:49:17 -0700750 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
751 // (vl + vlInc*frameCount)/65536.0f, frameCount);
752
753 do {
754 int32_t l = *in++;
755 *out++ += (vl >> 16) * l;
756 *out++ += (vr >> 16) * l;
757 vl += vlInc;
758 vr += vrInc;
759 } while (--frameCount);
760
761 t->prevVolume[0] = vl;
762 t->prevVolume[1] = vr;
763 t->adjustVolumeRamp(false);
764 }
765 // constant gain
766 else {
767 const int16_t vl = t->volume[0];
768 const int16_t vr = t->volume[1];
769 do {
770 int16_t l = *in++;
771 out[0] = mulAdd(l, vl, out[0]);
772 out[1] = mulAdd(l, vr, out[1]);
773 out += 2;
774 } while (--frameCount);
775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 }
777 t->in = in;
778}
779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780// no-op case
Eric Laurent65b65452010-06-01 23:49:17 -0700781void AudioMixer::process__nop(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782{
Eric Laurent65b65452010-06-01 23:49:17 -0700783 uint32_t e0 = state->enabledTracks;
784 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
785 while (e0) {
786 // process by group of tracks with same output buffer to
787 // avoid multiple memset() on same buffer
788 uint32_t e1 = e0, e2 = e0;
789 int i = 31 - __builtin_clz(e1);
790 track_t& t1 = state->tracks[i];
791 e2 &= ~(1<<i);
792 while (e2) {
793 i = 31 - __builtin_clz(e2);
794 e2 &= ~(1<<i);
795 track_t& t2 = state->tracks[i];
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800796 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700797 e1 &= ~(1<<i);
798 }
799 }
800 e0 &= ~(e1);
801
802 memset(t1.mainBuffer, 0, bufSize);
803
804 while (e1) {
805 i = 31 - __builtin_clz(e1);
806 e1 &= ~(1<<i);
807 t1 = state->tracks[i];
808 size_t outFrames = state->frameCount;
809 while (outFrames) {
810 t1.buffer.frameCount = outFrames;
811 t1.bufferProvider->getNextBuffer(&t1.buffer);
Glenn Kasten3694ec12012-01-27 16:47:15 -0800812 if (t1.buffer.raw == NULL) break;
Eric Laurent65b65452010-06-01 23:49:17 -0700813 outFrames -= t1.buffer.frameCount;
814 t1.bufferProvider->releaseBuffer(&t1.buffer);
815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 }
817 }
818}
819
820// generic code without resampling
Eric Laurent65b65452010-06-01 23:49:17 -0700821void AudioMixer::process__genericNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822{
823 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
824
825 // acquire each track's buffer
826 uint32_t enabledTracks = state->enabledTracks;
Eric Laurent65b65452010-06-01 23:49:17 -0700827 uint32_t e0 = enabledTracks;
828 while (e0) {
829 const int i = 31 - __builtin_clz(e0);
830 e0 &= ~(1<<i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 track_t& t = state->tracks[i];
832 t.buffer.frameCount = state->frameCount;
833 t.bufferProvider->getNextBuffer(&t.buffer);
834 t.frameCount = t.buffer.frameCount;
835 t.in = t.buffer.raw;
836 // t.in == NULL can happen if the track was flushed just after having
837 // been enabled for mixing.
838 if (t.in == NULL)
839 enabledTracks &= ~(1<<i);
840 }
841
Eric Laurent65b65452010-06-01 23:49:17 -0700842 e0 = enabledTracks;
843 while (e0) {
844 // process by group of tracks with same output buffer to
845 // optimize cache use
846 uint32_t e1 = e0, e2 = e0;
847 int j = 31 - __builtin_clz(e1);
848 track_t& t1 = state->tracks[j];
849 e2 &= ~(1<<j);
850 while (e2) {
851 j = 31 - __builtin_clz(e2);
852 e2 &= ~(1<<j);
853 track_t& t2 = state->tracks[j];
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800854 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700855 e1 &= ~(1<<j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 }
857 }
Eric Laurent65b65452010-06-01 23:49:17 -0700858 e0 &= ~(e1);
859 // this assumes output 16 bits stereo, no resampling
860 int32_t *out = t1.mainBuffer;
861 size_t numFrames = 0;
862 do {
863 memset(outTemp, 0, sizeof(outTemp));
864 e2 = e1;
865 while (e2) {
866 const int i = 31 - __builtin_clz(e2);
867 e2 &= ~(1<<i);
868 track_t& t = state->tracks[i];
869 size_t outFrames = BLOCKSIZE;
870 int32_t *aux = NULL;
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800871 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700872 aux = t.auxBuffer + numFrames;
873 }
874 while (outFrames) {
875 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
876 if (inFrames) {
877 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
878 t.frameCount -= inFrames;
879 outFrames -= inFrames;
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800880 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700881 aux += inFrames;
882 }
883 }
884 if (t.frameCount == 0 && outFrames) {
885 t.bufferProvider->releaseBuffer(&t.buffer);
886 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
887 t.bufferProvider->getNextBuffer(&t.buffer);
888 t.in = t.buffer.raw;
889 if (t.in == NULL) {
890 enabledTracks &= ~(1<<i);
891 e1 &= ~(1<<i);
892 break;
893 }
894 t.frameCount = t.buffer.frameCount;
895 }
896 }
897 }
898 ditherAndClamp(out, outTemp, BLOCKSIZE);
899 out += BLOCKSIZE;
900 numFrames += BLOCKSIZE;
901 } while (numFrames < state->frameCount);
902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903
904 // release each track's buffer
Eric Laurent65b65452010-06-01 23:49:17 -0700905 e0 = enabledTracks;
906 while (e0) {
907 const int i = 31 - __builtin_clz(e0);
908 e0 &= ~(1<<i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 track_t& t = state->tracks[i];
910 t.bufferProvider->releaseBuffer(&t.buffer);
911 }
912}
913
Eric Laurent65b65452010-06-01 23:49:17 -0700914
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800915// generic code with resampling
Eric Laurent65b65452010-06-01 23:49:17 -0700916void AudioMixer::process__genericResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917{
Glenn Kasten99c2fd32012-01-06 07:46:30 -0800918 // this const just means that local variable outTemp doesn't change
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 int32_t* const outTemp = state->outputTemp;
920 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 size_t numFrames = state->frameCount;
923
Eric Laurent65b65452010-06-01 23:49:17 -0700924 uint32_t e0 = state->enabledTracks;
925 while (e0) {
926 // process by group of tracks with same output buffer
927 // to optimize cache use
928 uint32_t e1 = e0, e2 = e0;
929 int j = 31 - __builtin_clz(e1);
930 track_t& t1 = state->tracks[j];
931 e2 &= ~(1<<j);
932 while (e2) {
933 j = 31 - __builtin_clz(e2);
934 e2 &= ~(1<<j);
935 track_t& t2 = state->tracks[j];
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800936 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700937 e1 &= ~(1<<j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 }
939 }
Eric Laurent65b65452010-06-01 23:49:17 -0700940 e0 &= ~(e1);
941 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi681d8182011-02-04 15:24:34 +0100942 memset(outTemp, 0, size);
Eric Laurent65b65452010-06-01 23:49:17 -0700943 while (e1) {
944 const int i = 31 - __builtin_clz(e1);
945 e1 &= ~(1<<i);
946 track_t& t = state->tracks[i];
947 int32_t *aux = NULL;
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800948 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700949 aux = t.auxBuffer;
950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951
Eric Laurent65b65452010-06-01 23:49:17 -0700952 // this is a little goofy, on the resampling case we don't
953 // acquire/release the buffers because it's done by
954 // the resampler.
955 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
956 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
957 } else {
958
959 size_t outFrames = 0;
960
961 while (outFrames < numFrames) {
962 t.buffer.frameCount = numFrames - outFrames;
963 t.bufferProvider->getNextBuffer(&t.buffer);
964 t.in = t.buffer.raw;
965 // t.in == NULL can happen if the track was flushed just after having
966 // been enabled for mixing.
967 if (t.in == NULL) break;
968
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800969 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700970 aux += outFrames;
971 }
972 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
973 outFrames += t.buffer.frameCount;
974 t.bufferProvider->releaseBuffer(&t.buffer);
975 }
976 }
977 }
978 ditherAndClamp(out, outTemp, numFrames);
979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980}
981
982// one track, 16 bits stereo without resampling is the most common case
Eric Laurent65b65452010-06-01 23:49:17 -0700983void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984{
985 const int i = 31 - __builtin_clz(state->enabledTracks);
986 const track_t& t = state->tracks[i];
987
988 AudioBufferProvider::Buffer& b(t.buffer);
Eric Laurent65b65452010-06-01 23:49:17 -0700989
990 int32_t* out = t.mainBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 size_t numFrames = state->frameCount;
Eric Laurent65b65452010-06-01 23:49:17 -0700992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 const int16_t vl = t.volume[0];
994 const int16_t vr = t.volume[1];
995 const uint32_t vrl = t.volumeRL;
996 while (numFrames) {
997 b.frameCount = numFrames;
998 t.bufferProvider->getNextBuffer(&b);
Glenn Kasten99c2fd32012-01-06 07:46:30 -0800999 const int16_t *in = b.i16;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000
1001 // in == NULL can happen if the track was flushed just after having
1002 // been enabled for mixing.
The Android Open Source Project10592532009-03-18 17:39:46 -07001003 if (in == NULL || ((unsigned long)in & 3)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
Steve Block3762c312012-01-06 19:20:56 +00001005 ALOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
The Android Open Source Project10592532009-03-18 17:39:46 -07001006 in, i, t.channelCount, t.needs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 return;
1008 }
1009 size_t outFrames = b.frameCount;
Eric Laurent65b65452010-06-01 23:49:17 -07001010
Glenn Kastene80a4cc2011-12-15 09:51:17 -08001011 if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 // volume is boosted, so we might need to clamp even though
1013 // we process only one track.
1014 do {
Glenn Kasten99c2fd32012-01-06 07:46:30 -08001015 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 in += 2;
1017 int32_t l = mulRL(1, rl, vrl) >> 12;
1018 int32_t r = mulRL(0, rl, vrl) >> 12;
1019 // clamping...
1020 l = clamp16(l);
1021 r = clamp16(r);
1022 *out++ = (r<<16) | (l & 0xFFFF);
1023 } while (--outFrames);
1024 } else {
1025 do {
Glenn Kasten99c2fd32012-01-06 07:46:30 -08001026 uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 in += 2;
1028 int32_t l = mulRL(1, rl, vrl) >> 12;
1029 int32_t r = mulRL(0, rl, vrl) >> 12;
1030 *out++ = (r<<16) | (l & 0xFFFF);
1031 } while (--outFrames);
1032 }
1033 numFrames -= b.frameCount;
1034 t.bufferProvider->releaseBuffer(&b);
1035 }
1036}
1037
Glenn Kasten31ba2e52011-12-15 09:53:12 -08001038#if 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039// 2 tracks is also a common case
Eric Laurent65b65452010-06-01 23:49:17 -07001040// NEVER used in current implementation of process__validate()
1041// only use if the 2 tracks have the same output buffer
1042void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043{
1044 int i;
1045 uint32_t en = state->enabledTracks;
1046
1047 i = 31 - __builtin_clz(en);
1048 const track_t& t0 = state->tracks[i];
1049 AudioBufferProvider::Buffer& b0(t0.buffer);
1050
1051 en &= ~(1<<i);
1052 i = 31 - __builtin_clz(en);
1053 const track_t& t1 = state->tracks[i];
1054 AudioBufferProvider::Buffer& b1(t1.buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001055
Glenn Kasten99c2fd32012-01-06 07:46:30 -08001056 const int16_t *in0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 const int16_t vl0 = t0.volume[0];
1058 const int16_t vr0 = t0.volume[1];
1059 size_t frameCount0 = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001060
Glenn Kasten99c2fd32012-01-06 07:46:30 -08001061 const int16_t *in1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 const int16_t vl1 = t1.volume[0];
1063 const int16_t vr1 = t1.volume[1];
1064 size_t frameCount1 = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001065
1066 //FIXME: only works if two tracks use same buffer
1067 int32_t* out = t0.mainBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 size_t numFrames = state->frameCount;
Glenn Kasten99c2fd32012-01-06 07:46:30 -08001069 const int16_t *buff = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070
Eric Laurent65b65452010-06-01 23:49:17 -07001071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 while (numFrames) {
Eric Laurent65b65452010-06-01 23:49:17 -07001073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 if (frameCount0 == 0) {
1075 b0.frameCount = numFrames;
1076 t0.bufferProvider->getNextBuffer(&b0);
1077 if (b0.i16 == NULL) {
1078 if (buff == NULL) {
1079 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1080 }
1081 in0 = buff;
1082 b0.frameCount = numFrames;
1083 } else {
1084 in0 = b0.i16;
1085 }
1086 frameCount0 = b0.frameCount;
1087 }
1088 if (frameCount1 == 0) {
1089 b1.frameCount = numFrames;
1090 t1.bufferProvider->getNextBuffer(&b1);
1091 if (b1.i16 == NULL) {
1092 if (buff == NULL) {
1093 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1094 }
1095 in1 = buff;
1096 b1.frameCount = numFrames;
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -08001097 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 in1 = b1.i16;
1099 }
1100 frameCount1 = b1.frameCount;
1101 }
Eric Laurent65b65452010-06-01 23:49:17 -07001102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1104
1105 numFrames -= outFrames;
1106 frameCount0 -= outFrames;
1107 frameCount1 -= outFrames;
Eric Laurent65b65452010-06-01 23:49:17 -07001108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 do {
1110 int32_t l0 = *in0++;
1111 int32_t r0 = *in0++;
1112 l0 = mul(l0, vl0);
1113 r0 = mul(r0, vr0);
1114 int32_t l = *in1++;
1115 int32_t r = *in1++;
1116 l = mulAdd(l, vl1, l0) >> 12;
1117 r = mulAdd(r, vr1, r0) >> 12;
1118 // clamping...
1119 l = clamp16(l);
1120 r = clamp16(r);
1121 *out++ = (r<<16) | (l & 0xFFFF);
1122 } while (--outFrames);
Eric Laurent65b65452010-06-01 23:49:17 -07001123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 if (frameCount0 == 0) {
1125 t0.bufferProvider->releaseBuffer(&b0);
1126 }
1127 if (frameCount1 == 0) {
1128 t1.bufferProvider->releaseBuffer(&b1);
1129 }
Eric Laurent65b65452010-06-01 23:49:17 -07001130 }
1131
Glenn Kasten2589cf92012-01-27 18:08:45 -08001132 delete [] buff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133}
Glenn Kasten31ba2e52011-12-15 09:53:12 -08001134#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135
1136// ----------------------------------------------------------------------------
1137}; // namespace android