blob: fb1ca8766eb3724c0262cbd9167ec0f26e3f5bf7 [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)
44 : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
45{
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 Kastenc434c902011-12-13 11:53:26 -080051 mState.outputTemp = NULL;
52 mState.resampleTemp = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 mState.hook = process__nop;
54 track_t* t = mState.tracks;
Glenn Kasten1f6f05d2011-12-13 11:52:35 -080055 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 t->needs = 0;
57 t->volume[0] = UNITY_GAIN;
58 t->volume[1] = UNITY_GAIN;
Glenn Kastena763b442011-12-13 11:58:23 -080059 // no initialization needed
60 // t->prevVolume[0]
61 // t->prevVolume[1]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 t->volumeInc[0] = 0;
63 t->volumeInc[1] = 0;
Eric Laurent65b65452010-06-01 23:49:17 -070064 t->auxLevel = 0;
65 t->auxInc = 0;
Glenn Kastena763b442011-12-13 11:58:23 -080066 // no initialization needed
67 // t->prevAuxLevel
68 // t->frameCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 t->channelCount = 2;
70 t->enabled = 0;
71 t->format = 16;
Jean-Michel Trivi54392232011-05-24 15:53:33 -070072 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 t->buffer.raw = 0;
Glenn Kastenc434c902011-12-13 11:53:26 -080074 t->bufferProvider = NULL;
75 t->hook = NULL;
76 t->resampler = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 t->sampleRate = mSampleRate;
Glenn Kastenc434c902011-12-13 11:53:26 -080078 t->in = NULL;
Eric Laurent65b65452010-06-01 23:49:17 -070079 t->mainBuffer = NULL;
80 t->auxBuffer = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 t++;
82 }
83}
84
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -080085AudioMixer::~AudioMixer()
86{
87 track_t* t = mState.tracks;
Glenn Kasten1f6f05d2011-12-13 11:52:35 -080088 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -080089 delete t->resampler;
90 t++;
91 }
92 delete [] mState.outputTemp;
93 delete [] mState.resampleTemp;
94}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -080096int AudioMixer::getTrackName()
97{
Glenn Kastenc1d810d2011-12-15 14:38:29 -080098 uint32_t names = ~mTrackNames;
99 if (names != 0) {
100 int n = __builtin_ctz(names);
Steve Block71f2cf12011-10-20 11:56:00 +0100101 ALOGV("add track (%d)", n);
Glenn Kastenc1d810d2011-12-15 14:38:29 -0800102 mTrackNames |= 1 << n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 return TRACK0 + n;
104 }
105 return -1;
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800106}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800108void AudioMixer::invalidateState(uint32_t mask)
109{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 if (mask) {
111 mState.needsChanged |= mask;
112 mState.hook = process__validate;
113 }
114 }
115
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800116void AudioMixer::deleteTrackName(int name)
117{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 name -= TRACK0;
Glenn Kastenb3719252011-12-15 15:32:27 -0800119 assert(uint32_t(name) < MAX_NUM_TRACKS);
120 ALOGV("deleteTrackName(%d)", name);
121 track_t& track(mState.tracks[ name ]);
122 if (track.enabled != 0) {
123 track.enabled = 0;
124 invalidateState(1<<name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 }
Glenn Kastenb3719252011-12-15 15:32:27 -0800126 if (track.resampler) {
127 // delete the resampler
128 delete track.resampler;
129 track.resampler = NULL;
130 track.sampleRate = mSampleRate;
131 invalidateState(1<<name);
132 }
133 track.volumeInc[0] = 0;
134 track.volumeInc[1] = 0;
135 mTrackNames &= ~(1<<name);
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800136}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137
Glenn Kastenaf62dbc2011-12-15 14:54:01 -0800138void AudioMixer::enable()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139{
Glenn Kastenaf62dbc2011-12-15 14:54:01 -0800140 if (mState.tracks[ mActiveTrack ].enabled != 1) {
141 mState.tracks[ mActiveTrack ].enabled = 1;
142 ALOGV("enable(%d)", mActiveTrack);
143 invalidateState(1<<mActiveTrack);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145}
146
Glenn Kastenaf62dbc2011-12-15 14:54:01 -0800147void AudioMixer::disable()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148{
Glenn Kastenaf62dbc2011-12-15 14:54:01 -0800149 if (mState.tracks[ mActiveTrack ].enabled != 0) {
150 mState.tracks[ mActiveTrack ].enabled = 0;
151 ALOGV("disable(%d)", mActiveTrack);
152 invalidateState(1<<mActiveTrack);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154}
155
Glenn Kastenafb40b52011-12-15 15:46:46 -0800156void AudioMixer::setActiveTrack(int track)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157{
Glenn Kastenafb40b52011-12-15 15:46:46 -0800158 // this also catches track < TRACK0
159 track -= TRACK0;
160 assert(uint32_t(track) < MAX_NUM_TRACKS);
161 mActiveTrack = track;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162}
163
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700164void AudioMixer::setParameter(int target, int name, void *value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165{
Eric Laurent65b65452010-06-01 23:49:17 -0700166 int valueInt = (int)value;
167 int32_t *valueBuf = (int32_t *)value;
168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 switch (target) {
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 case TRACK:
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700172 switch (name) {
173 case CHANNEL_MASK: {
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700174 uint32_t mask = (uint32_t)value;
175 if (mState.tracks[ mActiveTrack ].channelMask != mask) {
176 uint8_t channelCount = popcount(mask);
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700177 assert((channelCount <= MAX_NUM_CHANNELS) && (channelCount));
178 mState.tracks[ mActiveTrack ].channelMask = mask;
179 mState.tracks[ mActiveTrack ].channelCount = channelCount;
180 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
181 invalidateState(1<<mActiveTrack);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700183 } break;
184 case MAIN_BUFFER:
Eric Laurent65b65452010-06-01 23:49:17 -0700185 if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
186 mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
Steve Block71f2cf12011-10-20 11:56:00 +0100187 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Eric Laurent65b65452010-06-01 23:49:17 -0700188 invalidateState(1<<mActiveTrack);
189 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700190 break;
191 case AUX_BUFFER:
Eric Laurent65b65452010-06-01 23:49:17 -0700192 if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
193 mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
Steve Block71f2cf12011-10-20 11:56:00 +0100194 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Eric Laurent65b65452010-06-01 23:49:17 -0700195 invalidateState(1<<mActiveTrack);
196 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700197 break;
198 default:
199 // bad name
200 assert(false);
Eric Laurent65b65452010-06-01 23:49:17 -0700201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 break;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 case RESAMPLE:
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700205 switch (name) {
206 case SAMPLE_RATE: {
207 assert(valueInt > 0);
208 track_t& track = mState.tracks[ mActiveTrack ];
209 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
210 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
211 uint32_t(valueInt));
212 invalidateState(1<<mActiveTrack);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700214 } break;
215 case RESET: {
Eric Laurent4bb21c42011-02-28 16:52:51 -0800216 track_t& track = mState.tracks[ mActiveTrack ];
217 track.resetResampler();
218 invalidateState(1<<mActiveTrack);
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700219 } break;
220 default:
221 // bad name
222 assert(false);
Eric Laurent4bb21c42011-02-28 16:52:51 -0800223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 break;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 case RAMP_VOLUME:
227 case VOLUME:
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700228 switch (name) {
229 case VOLUME0:
230 case VOLUME1: {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 track_t& track = mState.tracks[ mActiveTrack ];
Eric Laurent65b65452010-06-01 23:49:17 -0700232 if (track.volume[name-VOLUME0] != valueInt) {
Steve Block71f2cf12011-10-20 11:56:00 +0100233 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
Eric Laurent65b65452010-06-01 23:49:17 -0700235 track.volume[name-VOLUME0] = valueInt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 if (target == VOLUME) {
Eric Laurent65b65452010-06-01 23:49:17 -0700237 track.prevVolume[name-VOLUME0] = valueInt << 16;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 track.volumeInc[name-VOLUME0] = 0;
239 } else {
Eric Laurent65b65452010-06-01 23:49:17 -0700240 int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 int32_t volInc = d / int32_t(mState.frameCount);
242 track.volumeInc[name-VOLUME0] = volInc;
243 if (volInc == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -0700244 track.prevVolume[name-VOLUME0] = valueInt << 16;
245 }
246 }
247 invalidateState(1<<mActiveTrack);
248 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700249 } break;
250 case AUXLEVEL: {
Eric Laurent65b65452010-06-01 23:49:17 -0700251 track_t& track = mState.tracks[ mActiveTrack ];
252 if (track.auxLevel != valueInt) {
Steve Block71f2cf12011-10-20 11:56:00 +0100253 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Eric Laurent65b65452010-06-01 23:49:17 -0700254 track.prevAuxLevel = track.auxLevel << 16;
255 track.auxLevel = valueInt;
256 if (target == VOLUME) {
257 track.prevAuxLevel = valueInt << 16;
258 track.auxInc = 0;
259 } else {
260 int32_t d = (valueInt<<16) - track.prevAuxLevel;
261 int32_t volInc = d / int32_t(mState.frameCount);
262 track.auxInc = volInc;
263 if (volInc == 0) {
264 track.prevAuxLevel = valueInt << 16;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 }
266 }
267 invalidateState(1<<mActiveTrack);
268 }
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700269 } break;
270 default:
271 // bad name
272 assert(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 }
274 break;
Glenn Kastenbde164ab2011-05-05 08:19:00 -0700275
276 default:
277 // bad target
278 assert(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280}
281
282bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
283{
284 if (value!=devSampleRate || resampler) {
285 if (sampleRate != value) {
286 sampleRate = value;
Glenn Kastenc434c902011-12-13 11:53:26 -0800287 if (resampler == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 resampler = AudioResampler::create(
289 format, channelCount, devSampleRate);
290 }
291 return true;
292 }
293 }
294 return false;
295}
296
297bool AudioMixer::track_t::doesResample() const
298{
Glenn Kastenc434c902011-12-13 11:53:26 -0800299 return resampler != NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300}
301
Eric Laurent4bb21c42011-02-28 16:52:51 -0800302void AudioMixer::track_t::resetResampler()
303{
Glenn Kastenc434c902011-12-13 11:53:26 -0800304 if (resampler != NULL) {
Eric Laurent4bb21c42011-02-28 16:52:51 -0800305 resampler->reset();
306 }
307}
308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309inline
Eric Laurent65b65452010-06-01 23:49:17 -0700310void AudioMixer::track_t::adjustVolumeRamp(bool aux)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311{
Glenn Kasten1f6f05d2011-12-13 11:52:35 -0800312 for (int i=0 ; i<MAX_NUM_CHANNELS ; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
314 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
315 volumeInc[i] = 0;
316 prevVolume[i] = volume[i]<<16;
317 }
318 }
Eric Laurent65b65452010-06-01 23:49:17 -0700319 if (aux) {
320 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
321 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
322 auxInc = 0;
323 prevAuxLevel = auxLevel<<16;
324 }
325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326}
327
Eric Laurent72dafb22011-12-22 16:08:41 -0800328size_t AudioMixer::track_t::getUnreleasedFrames()
329{
330 if (resampler != NULL) {
331 return resampler->getUnreleasedFrames();
332 }
333 return 0;
334}
335
336size_t AudioMixer::getUnreleasedFrames(int name)
337{
338 name -= TRACK0;
339 if (uint32_t(name) < MAX_NUM_TRACKS) {
340 track_t& track(mState.tracks[name]);
341 return track.getUnreleasedFrames();
342 }
343 return 0;
344}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345
Glenn Kastenafb40b52011-12-15 15:46:46 -0800346void AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347{
348 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349}
350
351
352
Eric Laurent65b65452010-06-01 23:49:17 -0700353void AudioMixer::process()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354{
Eric Laurent65b65452010-06-01 23:49:17 -0700355 mState.hook(&mState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356}
357
358
Eric Laurent65b65452010-06-01 23:49:17 -0700359void AudioMixer::process__validate(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360{
361 LOGW_IF(!state->needsChanged,
362 "in process__validate() but nothing's invalid");
363
364 uint32_t changed = state->needsChanged;
365 state->needsChanged = 0; // clear the validation flag
366
367 // recompute which tracks are enabled / disabled
368 uint32_t enabled = 0;
369 uint32_t disabled = 0;
370 while (changed) {
371 const int i = 31 - __builtin_clz(changed);
372 const uint32_t mask = 1<<i;
373 changed &= ~mask;
374 track_t& t = state->tracks[i];
375 (t.enabled ? enabled : disabled) |= mask;
376 }
377 state->enabledTracks &= ~disabled;
378 state->enabledTracks |= enabled;
379
380 // compute everything we need...
381 int countActiveTracks = 0;
382 int all16BitsStereoNoResample = 1;
383 int resampling = 0;
384 int volumeRamp = 0;
385 uint32_t en = state->enabledTracks;
386 while (en) {
387 const int i = 31 - __builtin_clz(en);
388 en &= ~(1<<i);
389
390 countActiveTracks++;
391 track_t& t = state->tracks[i];
392 uint32_t n = 0;
393 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
394 n |= NEEDS_FORMAT_16;
395 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
Eric Laurent65b65452010-06-01 23:49:17 -0700396 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
397 n |= NEEDS_AUX_ENABLED;
398 }
399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 if (t.volumeInc[0]|t.volumeInc[1]) {
401 volumeRamp = 1;
402 } else if (!t.doesResample() && t.volumeRL == 0) {
403 n |= NEEDS_MUTE_ENABLED;
404 }
405 t.needs = n;
406
407 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
408 t.hook = track__nop;
409 } else {
Eric Laurent65b65452010-06-01 23:49:17 -0700410 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
411 all16BitsStereoNoResample = 0;
412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
414 all16BitsStereoNoResample = 0;
415 resampling = 1;
416 t.hook = track__genericResample;
417 } else {
418 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
419 t.hook = track__16BitsMono;
420 all16BitsStereoNoResample = 0;
421 }
422 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
423 t.hook = track__16BitsStereo;
424 }
425 }
426 }
427 }
428
429 // select the processing hooks
430 state->hook = process__nop;
431 if (countActiveTracks) {
432 if (resampling) {
433 if (!state->outputTemp) {
434 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
435 }
436 if (!state->resampleTemp) {
437 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
438 }
439 state->hook = process__genericResampling;
440 } else {
441 if (state->outputTemp) {
442 delete [] state->outputTemp;
Glenn Kastenc434c902011-12-13 11:53:26 -0800443 state->outputTemp = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 }
445 if (state->resampleTemp) {
446 delete [] state->resampleTemp;
Glenn Kastenc434c902011-12-13 11:53:26 -0800447 state->resampleTemp = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 }
449 state->hook = process__genericNoResampling;
450 if (all16BitsStereoNoResample && !volumeRamp) {
451 if (countActiveTracks == 1) {
452 state->hook = process__OneTrack16BitsStereoNoResampling;
453 }
454 }
455 }
456 }
457
Steve Block71f2cf12011-10-20 11:56:00 +0100458 ALOGV("mixer configuration change: %d activeTracks (%08x) "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
460 countActiveTracks, state->enabledTracks,
461 all16BitsStereoNoResample, resampling, volumeRamp);
462
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800463 state->hook(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800465 // Now that the volume ramp has been done, set optimal state and
466 // track hooks for subsequent mixer process
467 if (countActiveTracks) {
468 int allMuted = 1;
469 uint32_t en = state->enabledTracks;
470 while (en) {
471 const int i = 31 - __builtin_clz(en);
472 en &= ~(1<<i);
473 track_t& t = state->tracks[i];
474 if (!t.doesResample() && t.volumeRL == 0)
475 {
476 t.needs |= NEEDS_MUTE_ENABLED;
477 t.hook = track__nop;
478 } else {
479 allMuted = 0;
480 }
481 }
482 if (allMuted) {
483 state->hook = process__nop;
484 } else if (all16BitsStereoNoResample) {
485 if (countActiveTracks == 1) {
486 state->hook = process__OneTrack16BitsStereoNoResampling;
487 }
488 }
489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490}
491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492
Eric Laurent65b65452010-06-01 23:49:17 -0700493void 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 -0800494{
495 t->resampler->setSampleRate(t->sampleRate);
496
497 // ramp gain - resample to temp buffer and scale/mix in 2nd step
Eric Laurent65b65452010-06-01 23:49:17 -0700498 if (aux != NULL) {
499 // always resample with unity gain when sending to auxiliary buffer to be able
500 // to apply send level after resampling
501 // TODO: modify each resampler to support aux channel?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
503 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
504 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800505 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700506 volumeRampStereo(t, out, outFrameCount, temp, aux);
507 } else {
508 volumeStereo(t, out, outFrameCount, temp, aux);
509 }
510 } else {
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800511 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Eric Laurent65b65452010-06-01 23:49:17 -0700512 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
513 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
514 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
515 volumeRampStereo(t, out, outFrameCount, temp, aux);
516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517
Eric Laurent65b65452010-06-01 23:49:17 -0700518 // constant gain
519 else {
520 t->resampler->setVolume(t->volume[0], t->volume[1]);
521 t->resampler->resample(out, outFrameCount, t->bufferProvider);
522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 }
524}
525
Eric Laurent65b65452010-06-01 23:49:17 -0700526void 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 -0800527{
528}
529
Eric Laurent65b65452010-06-01 23:49:17 -0700530void 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 -0800531{
532 int32_t vl = t->prevVolume[0];
533 int32_t vr = t->prevVolume[1];
534 const int32_t vlInc = t->volumeInc[0];
535 const int32_t vrInc = t->volumeInc[1];
536
Steve Block5baa3a62011-12-20 16:23:08 +0000537 //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
539 // (vl + vlInc*frameCount)/65536.0f, frameCount);
Eric Laurent65b65452010-06-01 23:49:17 -0700540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 // ramp volume
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800542 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700543 int32_t va = t->prevAuxLevel;
544 const int32_t vaInc = t->auxInc;
545 int32_t l;
546 int32_t r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547
548 do {
Eric Laurent65b65452010-06-01 23:49:17 -0700549 l = (*temp++ >> 12);
550 r = (*temp++ >> 12);
551 *out++ += (vl >> 16) * l;
552 *out++ += (vr >> 16) * r;
553 *aux++ += (va >> 17) * (l + r);
554 vl += vlInc;
555 vr += vrInc;
556 va += vaInc;
557 } while (--frameCount);
558 t->prevAuxLevel = va;
559 } else {
560 do {
561 *out++ += (vl >> 16) * (*temp++ >> 12);
562 *out++ += (vr >> 16) * (*temp++ >> 12);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 vl += vlInc;
564 vr += vrInc;
565 } while (--frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 }
Eric Laurent65b65452010-06-01 23:49:17 -0700567 t->prevVolume[0] = vl;
568 t->prevVolume[1] = vr;
569 t->adjustVolumeRamp((aux != NULL));
570}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571
Eric Laurent65b65452010-06-01 23:49:17 -0700572void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
573{
574 const int16_t vl = t->volume[0];
575 const int16_t vr = t->volume[1];
576
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800577 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700578 const int16_t va = (int16_t)t->auxLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 do {
Eric Laurent65b65452010-06-01 23:49:17 -0700580 int16_t l = (int16_t)(*temp++ >> 12);
581 int16_t r = (int16_t)(*temp++ >> 12);
582 out[0] = mulAdd(l, vl, out[0]);
583 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
584 out[1] = mulAdd(r, vr, out[1]);
585 out += 2;
586 aux[0] = mulAdd(a, va, aux[0]);
587 aux++;
588 } while (--frameCount);
589 } else {
590 do {
591 int16_t l = (int16_t)(*temp++ >> 12);
592 int16_t r = (int16_t)(*temp++ >> 12);
593 out[0] = mulAdd(l, vl, out[0]);
594 out[1] = mulAdd(r, vr, out[1]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 out += 2;
596 } while (--frameCount);
597 }
Eric Laurent65b65452010-06-01 23:49:17 -0700598}
599
600void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
601{
602 int16_t const *in = static_cast<int16_t const *>(t->in);
603
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800604 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700605 int32_t l;
606 int32_t r;
607 // ramp gain
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800608 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700609 int32_t vl = t->prevVolume[0];
610 int32_t vr = t->prevVolume[1];
611 int32_t va = t->prevAuxLevel;
612 const int32_t vlInc = t->volumeInc[0];
613 const int32_t vrInc = t->volumeInc[1];
614 const int32_t vaInc = t->auxInc;
Steve Block5baa3a62011-12-20 16:23:08 +0000615 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Eric Laurent65b65452010-06-01 23:49:17 -0700616 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
617 // (vl + vlInc*frameCount)/65536.0f, frameCount);
618
619 do {
620 l = (int32_t)*in++;
621 r = (int32_t)*in++;
622 *out++ += (vl >> 16) * l;
623 *out++ += (vr >> 16) * r;
624 *aux++ += (va >> 17) * (l + r);
625 vl += vlInc;
626 vr += vrInc;
627 va += vaInc;
628 } while (--frameCount);
629
630 t->prevVolume[0] = vl;
631 t->prevVolume[1] = vr;
632 t->prevAuxLevel = va;
633 t->adjustVolumeRamp(true);
634 }
635
636 // constant gain
637 else {
638 const uint32_t vrl = t->volumeRL;
639 const int16_t va = (int16_t)t->auxLevel;
640 do {
641 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
642 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
643 in += 2;
644 out[0] = mulAddRL(1, rl, vrl, out[0]);
645 out[1] = mulAddRL(0, rl, vrl, out[1]);
646 out += 2;
647 aux[0] = mulAdd(a, va, aux[0]);
648 aux++;
649 } while (--frameCount);
650 }
651 } else {
652 // ramp gain
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800653 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Eric Laurent65b65452010-06-01 23:49:17 -0700654 int32_t vl = t->prevVolume[0];
655 int32_t vr = t->prevVolume[1];
656 const int32_t vlInc = t->volumeInc[0];
657 const int32_t vrInc = t->volumeInc[1];
658
Steve Block5baa3a62011-12-20 16:23:08 +0000659 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Eric Laurent65b65452010-06-01 23:49:17 -0700660 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
661 // (vl + vlInc*frameCount)/65536.0f, frameCount);
662
663 do {
664 *out++ += (vl >> 16) * (int32_t) *in++;
665 *out++ += (vr >> 16) * (int32_t) *in++;
666 vl += vlInc;
667 vr += vrInc;
668 } while (--frameCount);
669
670 t->prevVolume[0] = vl;
671 t->prevVolume[1] = vr;
672 t->adjustVolumeRamp(false);
673 }
674
675 // constant gain
676 else {
677 const uint32_t vrl = t->volumeRL;
678 do {
679 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
680 in += 2;
681 out[0] = mulAddRL(1, rl, vrl, out[0]);
682 out[1] = mulAddRL(0, rl, vrl, out[1]);
683 out += 2;
684 } while (--frameCount);
685 }
686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 t->in = in;
688}
689
Eric Laurent65b65452010-06-01 23:49:17 -0700690void 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 -0800691{
692 int16_t const *in = static_cast<int16_t const *>(t->in);
693
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800694 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700695 // ramp gain
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800696 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700697 int32_t vl = t->prevVolume[0];
698 int32_t vr = t->prevVolume[1];
699 int32_t va = t->prevAuxLevel;
700 const int32_t vlInc = t->volumeInc[0];
701 const int32_t vrInc = t->volumeInc[1];
702 const int32_t vaInc = t->auxInc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703
Steve Block5baa3a62011-12-20 16:23:08 +0000704 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Eric Laurent65b65452010-06-01 23:49:17 -0700705 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
706 // (vl + vlInc*frameCount)/65536.0f, frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707
Eric Laurent65b65452010-06-01 23:49:17 -0700708 do {
709 int32_t l = *in++;
710 *out++ += (vl >> 16) * l;
711 *out++ += (vr >> 16) * l;
712 *aux++ += (va >> 16) * l;
713 vl += vlInc;
714 vr += vrInc;
715 va += vaInc;
716 } while (--frameCount);
717
718 t->prevVolume[0] = vl;
719 t->prevVolume[1] = vr;
720 t->prevAuxLevel = va;
721 t->adjustVolumeRamp(true);
722 }
723 // constant gain
724 else {
725 const int16_t vl = t->volume[0];
726 const int16_t vr = t->volume[1];
727 const int16_t va = (int16_t)t->auxLevel;
728 do {
729 int16_t l = *in++;
730 out[0] = mulAdd(l, vl, out[0]);
731 out[1] = mulAdd(l, vr, out[1]);
732 out += 2;
733 aux[0] = mulAdd(l, va, aux[0]);
734 aux++;
735 } while (--frameCount);
736 }
737 } else {
738 // ramp gain
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800739 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Eric Laurent65b65452010-06-01 23:49:17 -0700740 int32_t vl = t->prevVolume[0];
741 int32_t vr = t->prevVolume[1];
742 const int32_t vlInc = t->volumeInc[0];
743 const int32_t vrInc = t->volumeInc[1];
744
Steve Block5baa3a62011-12-20 16:23:08 +0000745 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Eric Laurent65b65452010-06-01 23:49:17 -0700746 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
747 // (vl + vlInc*frameCount)/65536.0f, frameCount);
748
749 do {
750 int32_t l = *in++;
751 *out++ += (vl >> 16) * l;
752 *out++ += (vr >> 16) * l;
753 vl += vlInc;
754 vr += vrInc;
755 } while (--frameCount);
756
757 t->prevVolume[0] = vl;
758 t->prevVolume[1] = vr;
759 t->adjustVolumeRamp(false);
760 }
761 // constant gain
762 else {
763 const int16_t vl = t->volume[0];
764 const int16_t vr = t->volume[1];
765 do {
766 int16_t l = *in++;
767 out[0] = mulAdd(l, vl, out[0]);
768 out[1] = mulAdd(l, vr, out[1]);
769 out += 2;
770 } while (--frameCount);
771 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 }
773 t->in = in;
774}
775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776// no-op case
Eric Laurent65b65452010-06-01 23:49:17 -0700777void AudioMixer::process__nop(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778{
Eric Laurent65b65452010-06-01 23:49:17 -0700779 uint32_t e0 = state->enabledTracks;
780 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
781 while (e0) {
782 // process by group of tracks with same output buffer to
783 // avoid multiple memset() on same buffer
784 uint32_t e1 = e0, e2 = e0;
785 int i = 31 - __builtin_clz(e1);
786 track_t& t1 = state->tracks[i];
787 e2 &= ~(1<<i);
788 while (e2) {
789 i = 31 - __builtin_clz(e2);
790 e2 &= ~(1<<i);
791 track_t& t2 = state->tracks[i];
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800792 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700793 e1 &= ~(1<<i);
794 }
795 }
796 e0 &= ~(e1);
797
798 memset(t1.mainBuffer, 0, bufSize);
799
800 while (e1) {
801 i = 31 - __builtin_clz(e1);
802 e1 &= ~(1<<i);
803 t1 = state->tracks[i];
804 size_t outFrames = state->frameCount;
805 while (outFrames) {
806 t1.buffer.frameCount = outFrames;
807 t1.bufferProvider->getNextBuffer(&t1.buffer);
808 if (!t1.buffer.raw) break;
809 outFrames -= t1.buffer.frameCount;
810 t1.bufferProvider->releaseBuffer(&t1.buffer);
811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 }
813 }
814}
815
816// generic code without resampling
Eric Laurent65b65452010-06-01 23:49:17 -0700817void AudioMixer::process__genericNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818{
819 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
820
821 // acquire each track's buffer
822 uint32_t enabledTracks = state->enabledTracks;
Eric Laurent65b65452010-06-01 23:49:17 -0700823 uint32_t e0 = enabledTracks;
824 while (e0) {
825 const int i = 31 - __builtin_clz(e0);
826 e0 &= ~(1<<i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 track_t& t = state->tracks[i];
828 t.buffer.frameCount = state->frameCount;
829 t.bufferProvider->getNextBuffer(&t.buffer);
830 t.frameCount = t.buffer.frameCount;
831 t.in = t.buffer.raw;
832 // t.in == NULL can happen if the track was flushed just after having
833 // been enabled for mixing.
834 if (t.in == NULL)
835 enabledTracks &= ~(1<<i);
836 }
837
Eric Laurent65b65452010-06-01 23:49:17 -0700838 e0 = enabledTracks;
839 while (e0) {
840 // process by group of tracks with same output buffer to
841 // optimize cache use
842 uint32_t e1 = e0, e2 = e0;
843 int j = 31 - __builtin_clz(e1);
844 track_t& t1 = state->tracks[j];
845 e2 &= ~(1<<j);
846 while (e2) {
847 j = 31 - __builtin_clz(e2);
848 e2 &= ~(1<<j);
849 track_t& t2 = state->tracks[j];
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800850 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700851 e1 &= ~(1<<j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 }
853 }
Eric Laurent65b65452010-06-01 23:49:17 -0700854 e0 &= ~(e1);
855 // this assumes output 16 bits stereo, no resampling
856 int32_t *out = t1.mainBuffer;
857 size_t numFrames = 0;
858 do {
859 memset(outTemp, 0, sizeof(outTemp));
860 e2 = e1;
861 while (e2) {
862 const int i = 31 - __builtin_clz(e2);
863 e2 &= ~(1<<i);
864 track_t& t = state->tracks[i];
865 size_t outFrames = BLOCKSIZE;
866 int32_t *aux = NULL;
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800867 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700868 aux = t.auxBuffer + numFrames;
869 }
870 while (outFrames) {
871 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
872 if (inFrames) {
873 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
874 t.frameCount -= inFrames;
875 outFrames -= inFrames;
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800876 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700877 aux += inFrames;
878 }
879 }
880 if (t.frameCount == 0 && outFrames) {
881 t.bufferProvider->releaseBuffer(&t.buffer);
882 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
883 t.bufferProvider->getNextBuffer(&t.buffer);
884 t.in = t.buffer.raw;
885 if (t.in == NULL) {
886 enabledTracks &= ~(1<<i);
887 e1 &= ~(1<<i);
888 break;
889 }
890 t.frameCount = t.buffer.frameCount;
891 }
892 }
893 }
894 ditherAndClamp(out, outTemp, BLOCKSIZE);
895 out += BLOCKSIZE;
896 numFrames += BLOCKSIZE;
897 } while (numFrames < state->frameCount);
898 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899
900 // release each track's buffer
Eric Laurent65b65452010-06-01 23:49:17 -0700901 e0 = enabledTracks;
902 while (e0) {
903 const int i = 31 - __builtin_clz(e0);
904 e0 &= ~(1<<i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 track_t& t = state->tracks[i];
906 t.bufferProvider->releaseBuffer(&t.buffer);
907 }
908}
909
Eric Laurent65b65452010-06-01 23:49:17 -0700910
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800911// generic code with resampling
Eric Laurent65b65452010-06-01 23:49:17 -0700912void AudioMixer::process__genericResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913{
914 int32_t* const outTemp = state->outputTemp;
915 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 size_t numFrames = state->frameCount;
918
Eric Laurent65b65452010-06-01 23:49:17 -0700919 uint32_t e0 = state->enabledTracks;
920 while (e0) {
921 // process by group of tracks with same output buffer
922 // to optimize cache use
923 uint32_t e1 = e0, e2 = e0;
924 int j = 31 - __builtin_clz(e1);
925 track_t& t1 = state->tracks[j];
926 e2 &= ~(1<<j);
927 while (e2) {
928 j = 31 - __builtin_clz(e2);
929 e2 &= ~(1<<j);
930 track_t& t2 = state->tracks[j];
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800931 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700932 e1 &= ~(1<<j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 }
934 }
Eric Laurent65b65452010-06-01 23:49:17 -0700935 e0 &= ~(e1);
936 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi681d8182011-02-04 15:24:34 +0100937 memset(outTemp, 0, size);
Eric Laurent65b65452010-06-01 23:49:17 -0700938 while (e1) {
939 const int i = 31 - __builtin_clz(e1);
940 e1 &= ~(1<<i);
941 track_t& t = state->tracks[i];
942 int32_t *aux = NULL;
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800943 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700944 aux = t.auxBuffer;
945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946
Eric Laurent65b65452010-06-01 23:49:17 -0700947 // this is a little goofy, on the resampling case we don't
948 // acquire/release the buffers because it's done by
949 // the resampler.
950 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
951 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
952 } else {
953
954 size_t outFrames = 0;
955
956 while (outFrames < numFrames) {
957 t.buffer.frameCount = numFrames - outFrames;
958 t.bufferProvider->getNextBuffer(&t.buffer);
959 t.in = t.buffer.raw;
960 // t.in == NULL can happen if the track was flushed just after having
961 // been enabled for mixing.
962 if (t.in == NULL) break;
963
Glenn Kastene80a4cc2011-12-15 09:51:17 -0800964 if (CC_UNLIKELY(aux != NULL)) {
Eric Laurent65b65452010-06-01 23:49:17 -0700965 aux += outFrames;
966 }
967 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
968 outFrames += t.buffer.frameCount;
969 t.bufferProvider->releaseBuffer(&t.buffer);
970 }
971 }
972 }
973 ditherAndClamp(out, outTemp, numFrames);
974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975}
976
977// one track, 16 bits stereo without resampling is the most common case
Eric Laurent65b65452010-06-01 23:49:17 -0700978void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979{
980 const int i = 31 - __builtin_clz(state->enabledTracks);
981 const track_t& t = state->tracks[i];
982
983 AudioBufferProvider::Buffer& b(t.buffer);
Eric Laurent65b65452010-06-01 23:49:17 -0700984
985 int32_t* out = t.mainBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 size_t numFrames = state->frameCount;
Eric Laurent65b65452010-06-01 23:49:17 -0700987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 const int16_t vl = t.volume[0];
989 const int16_t vr = t.volume[1];
990 const uint32_t vrl = t.volumeRL;
991 while (numFrames) {
992 b.frameCount = numFrames;
993 t.bufferProvider->getNextBuffer(&b);
994 int16_t const *in = b.i16;
995
996 // in == NULL can happen if the track was flushed just after having
997 // been enabled for mixing.
The Android Open Source Project10592532009-03-18 17:39:46 -0700998 if (in == NULL || ((unsigned long)in & 3)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
The Android Open Source Project10592532009-03-18 17:39:46 -07001000 LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
1001 in, i, t.channelCount, t.needs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 return;
1003 }
1004 size_t outFrames = b.frameCount;
Eric Laurent65b65452010-06-01 23:49:17 -07001005
Glenn Kastene80a4cc2011-12-15 09:51:17 -08001006 if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 // volume is boosted, so we might need to clamp even though
1008 // we process only one track.
1009 do {
1010 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1011 in += 2;
1012 int32_t l = mulRL(1, rl, vrl) >> 12;
1013 int32_t r = mulRL(0, rl, vrl) >> 12;
1014 // clamping...
1015 l = clamp16(l);
1016 r = clamp16(r);
1017 *out++ = (r<<16) | (l & 0xFFFF);
1018 } while (--outFrames);
1019 } else {
1020 do {
1021 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1022 in += 2;
1023 int32_t l = mulRL(1, rl, vrl) >> 12;
1024 int32_t r = mulRL(0, rl, vrl) >> 12;
1025 *out++ = (r<<16) | (l & 0xFFFF);
1026 } while (--outFrames);
1027 }
1028 numFrames -= b.frameCount;
1029 t.bufferProvider->releaseBuffer(&b);
1030 }
1031}
1032
Glenn Kasten31ba2e52011-12-15 09:53:12 -08001033#if 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034// 2 tracks is also a common case
Eric Laurent65b65452010-06-01 23:49:17 -07001035// NEVER used in current implementation of process__validate()
1036// only use if the 2 tracks have the same output buffer
1037void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038{
1039 int i;
1040 uint32_t en = state->enabledTracks;
1041
1042 i = 31 - __builtin_clz(en);
1043 const track_t& t0 = state->tracks[i];
1044 AudioBufferProvider::Buffer& b0(t0.buffer);
1045
1046 en &= ~(1<<i);
1047 i = 31 - __builtin_clz(en);
1048 const track_t& t1 = state->tracks[i];
1049 AudioBufferProvider::Buffer& b1(t1.buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 int16_t const *in0;
1052 const int16_t vl0 = t0.volume[0];
1053 const int16_t vr0 = t0.volume[1];
1054 size_t frameCount0 = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 int16_t const *in1;
1057 const int16_t vl1 = t1.volume[0];
1058 const int16_t vr1 = t1.volume[1];
1059 size_t frameCount1 = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001060
1061 //FIXME: only works if two tracks use same buffer
1062 int32_t* out = t0.mainBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 size_t numFrames = state->frameCount;
1064 int16_t const *buff = NULL;
1065
Eric Laurent65b65452010-06-01 23:49:17 -07001066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 while (numFrames) {
Eric Laurent65b65452010-06-01 23:49:17 -07001068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 if (frameCount0 == 0) {
1070 b0.frameCount = numFrames;
1071 t0.bufferProvider->getNextBuffer(&b0);
1072 if (b0.i16 == NULL) {
1073 if (buff == NULL) {
1074 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1075 }
1076 in0 = buff;
1077 b0.frameCount = numFrames;
1078 } else {
1079 in0 = b0.i16;
1080 }
1081 frameCount0 = b0.frameCount;
1082 }
1083 if (frameCount1 == 0) {
1084 b1.frameCount = numFrames;
1085 t1.bufferProvider->getNextBuffer(&b1);
1086 if (b1.i16 == NULL) {
1087 if (buff == NULL) {
1088 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1089 }
1090 in1 = buff;
1091 b1.frameCount = numFrames;
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -08001092 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 in1 = b1.i16;
1094 }
1095 frameCount1 = b1.frameCount;
1096 }
Eric Laurent65b65452010-06-01 23:49:17 -07001097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1099
1100 numFrames -= outFrames;
1101 frameCount0 -= outFrames;
1102 frameCount1 -= outFrames;
Eric Laurent65b65452010-06-01 23:49:17 -07001103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 do {
1105 int32_t l0 = *in0++;
1106 int32_t r0 = *in0++;
1107 l0 = mul(l0, vl0);
1108 r0 = mul(r0, vr0);
1109 int32_t l = *in1++;
1110 int32_t r = *in1++;
1111 l = mulAdd(l, vl1, l0) >> 12;
1112 r = mulAdd(r, vr1, r0) >> 12;
1113 // clamping...
1114 l = clamp16(l);
1115 r = clamp16(r);
1116 *out++ = (r<<16) | (l & 0xFFFF);
1117 } while (--outFrames);
Eric Laurent65b65452010-06-01 23:49:17 -07001118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 if (frameCount0 == 0) {
1120 t0.bufferProvider->releaseBuffer(&b0);
1121 }
1122 if (frameCount1 == 0) {
1123 t1.bufferProvider->releaseBuffer(&b1);
1124 }
Eric Laurent65b65452010-06-01 23:49:17 -07001125 }
1126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 if (buff != NULL) {
Eric Laurent65b65452010-06-01 23:49:17 -07001128 delete [] buff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 }
1130}
Glenn Kasten31ba2e52011-12-15 09:53:12 -08001131#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132
1133// ----------------------------------------------------------------------------
1134}; // namespace android