blob: dc1d1a7df21bdb711db5ee108b3ffc26ba27aa92 [file] [log] [blame]
Mathias Agopian65ab4712010-07-14 17:59:35 -07001/* //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"
19//#define LOG_NDEBUG 0
20
Glenn Kastenfba380a2011-12-15 15:46:46 -080021#include <assert.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070022#include <stdint.h>
23#include <string.h>
24#include <stdlib.h>
25#include <sys/types.h>
26
27#include <utils/Errors.h>
28#include <utils/Log.h>
29
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070030#include <cutils/bitops.h>
31
32#include <system/audio.h>
33
Glenn Kasten3b21c502011-12-15 09:52:39 -080034#include <audio_utils/primitives.h>
35
Mathias Agopian65ab4712010-07-14 17:59:35 -070036#include "AudioMixer.h"
37
38namespace android {
Mathias Agopian65ab4712010-07-14 17:59:35 -070039
40// ----------------------------------------------------------------------------
41
42AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
43 : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
44{
Glenn Kasten788040c2011-05-05 08:19:00 -070045 // AudioMixer is not yet capable of multi-channel beyond stereo
46 assert(2 == MAX_NUM_CHANNELS);
Mathias Agopian65ab4712010-07-14 17:59:35 -070047 mState.enabledTracks= 0;
48 mState.needsChanged = 0;
49 mState.frameCount = frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -080050 mState.outputTemp = NULL;
51 mState.resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070052 mState.hook = process__nop;
53 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -080054 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -070055 t->needs = 0;
56 t->volume[0] = UNITY_GAIN;
57 t->volume[1] = UNITY_GAIN;
Glenn Kasten0cfd8232011-12-13 11:58:23 -080058 // no initialization needed
59 // t->prevVolume[0]
60 // t->prevVolume[1]
Mathias Agopian65ab4712010-07-14 17:59:35 -070061 t->volumeInc[0] = 0;
62 t->volumeInc[1] = 0;
63 t->auxLevel = 0;
64 t->auxInc = 0;
Glenn Kasten0cfd8232011-12-13 11:58:23 -080065 // no initialization needed
66 // t->prevAuxLevel
67 // t->frameCount
Mathias Agopian65ab4712010-07-14 17:59:35 -070068 t->channelCount = 2;
69 t->enabled = 0;
70 t->format = 16;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070071 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -070072 t->buffer.raw = 0;
Glenn Kastene0feee32011-12-13 11:53:26 -080073 t->bufferProvider = NULL;
74 t->hook = NULL;
75 t->resampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070076 t->sampleRate = mSampleRate;
Glenn Kastene0feee32011-12-13 11:53:26 -080077 t->in = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070078 t->mainBuffer = NULL;
79 t->auxBuffer = NULL;
80 t++;
81 }
82}
83
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080084AudioMixer::~AudioMixer()
85{
86 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -080087 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080088 delete t->resampler;
89 t++;
90 }
91 delete [] mState.outputTemp;
92 delete [] mState.resampleTemp;
93}
Mathias Agopian65ab4712010-07-14 17:59:35 -070094
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080095int AudioMixer::getTrackName()
96{
Mathias Agopian65ab4712010-07-14 17:59:35 -070097 uint32_t names = mTrackNames;
98 uint32_t mask = 1;
99 int n = 0;
100 while (names & mask) {
101 mask <<= 1;
102 n++;
103 }
104 if (mask) {
Steve Block3856b092011-10-20 11:56:00 +0100105 ALOGV("add track (%d)", n);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700106 mTrackNames |= mask;
107 return TRACK0 + n;
108 }
109 return -1;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800110}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700111
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800112void AudioMixer::invalidateState(uint32_t mask)
113{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700114 if (mask) {
115 mState.needsChanged |= mask;
116 mState.hook = process__validate;
117 }
118 }
119
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800120void AudioMixer::deleteTrackName(int name)
121{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700122 name -= TRACK0;
Glenn Kasten237a6242011-12-15 15:32:27 -0800123 assert(uint32_t(name) < MAX_NUM_TRACKS);
124 ALOGV("deleteTrackName(%d)", name);
125 track_t& track(mState.tracks[ name ]);
126 if (track.enabled != 0) {
127 track.enabled = 0;
128 invalidateState(1<<name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700129 }
Glenn Kasten237a6242011-12-15 15:32:27 -0800130 if (track.resampler) {
131 // delete the resampler
132 delete track.resampler;
133 track.resampler = NULL;
134 track.sampleRate = mSampleRate;
135 invalidateState(1<<name);
136 }
137 track.volumeInc[0] = 0;
138 track.volumeInc[1] = 0;
139 mTrackNames &= ~(1<<name);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800140}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700141
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800142void AudioMixer::enable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700143{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800144 if (mState.tracks[ mActiveTrack ].enabled != 1) {
145 mState.tracks[ mActiveTrack ].enabled = 1;
146 ALOGV("enable(%d)", mActiveTrack);
147 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700148 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700149}
150
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800151void AudioMixer::disable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700152{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800153 if (mState.tracks[ mActiveTrack ].enabled != 0) {
154 mState.tracks[ mActiveTrack ].enabled = 0;
155 ALOGV("disable(%d)", mActiveTrack);
156 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700157 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700158}
159
Glenn Kastenfba380a2011-12-15 15:46:46 -0800160void AudioMixer::setActiveTrack(int track)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700161{
Glenn Kastenfba380a2011-12-15 15:46:46 -0800162 // this also catches track < TRACK0
163 track -= TRACK0;
164 assert(uint32_t(track) < MAX_NUM_TRACKS);
165 mActiveTrack = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700166}
167
Glenn Kasten788040c2011-05-05 08:19:00 -0700168void AudioMixer::setParameter(int target, int name, void *value)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700169{
170 int valueInt = (int)value;
171 int32_t *valueBuf = (int32_t *)value;
172
173 switch (target) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700174
Mathias Agopian65ab4712010-07-14 17:59:35 -0700175 case TRACK:
Glenn Kasten788040c2011-05-05 08:19:00 -0700176 switch (name) {
177 case CHANNEL_MASK: {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700178 uint32_t mask = (uint32_t)value;
179 if (mState.tracks[ mActiveTrack ].channelMask != mask) {
180 uint8_t channelCount = popcount(mask);
Glenn Kasten788040c2011-05-05 08:19:00 -0700181 assert((channelCount <= MAX_NUM_CHANNELS) && (channelCount));
182 mState.tracks[ mActiveTrack ].channelMask = mask;
183 mState.tracks[ mActiveTrack ].channelCount = channelCount;
184 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
185 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700186 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700187 } break;
188 case MAIN_BUFFER:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700189 if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
190 mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100191 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700192 invalidateState(1<<mActiveTrack);
193 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700194 break;
195 case AUX_BUFFER:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700196 if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
197 mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100198 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700199 invalidateState(1<<mActiveTrack);
200 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700201 break;
202 default:
203 // bad name
204 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700205 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700206 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700207
Mathias Agopian65ab4712010-07-14 17:59:35 -0700208 case RESAMPLE:
Glenn Kasten788040c2011-05-05 08:19:00 -0700209 switch (name) {
210 case SAMPLE_RATE: {
211 assert(valueInt > 0);
212 track_t& track = mState.tracks[ mActiveTrack ];
213 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
214 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
215 uint32_t(valueInt));
216 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700217 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700218 } break;
219 case RESET: {
Eric Laurent243f5f92011-02-28 16:52:51 -0800220 track_t& track = mState.tracks[ mActiveTrack ];
221 track.resetResampler();
222 invalidateState(1<<mActiveTrack);
Glenn Kasten788040c2011-05-05 08:19:00 -0700223 } break;
224 default:
225 // bad name
226 assert(false);
Eric Laurent243f5f92011-02-28 16:52:51 -0800227 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700228 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700229
Mathias Agopian65ab4712010-07-14 17:59:35 -0700230 case RAMP_VOLUME:
231 case VOLUME:
Glenn Kasten788040c2011-05-05 08:19:00 -0700232 switch (name) {
233 case VOLUME0:
234 case VOLUME1: {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700235 track_t& track = mState.tracks[ mActiveTrack ];
236 if (track.volume[name-VOLUME0] != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100237 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700238 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
239 track.volume[name-VOLUME0] = valueInt;
240 if (target == VOLUME) {
241 track.prevVolume[name-VOLUME0] = valueInt << 16;
242 track.volumeInc[name-VOLUME0] = 0;
243 } else {
244 int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
245 int32_t volInc = d / int32_t(mState.frameCount);
246 track.volumeInc[name-VOLUME0] = volInc;
247 if (volInc == 0) {
248 track.prevVolume[name-VOLUME0] = valueInt << 16;
249 }
250 }
251 invalidateState(1<<mActiveTrack);
252 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700253 } break;
254 case AUXLEVEL: {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700255 track_t& track = mState.tracks[ mActiveTrack ];
256 if (track.auxLevel != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100257 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700258 track.prevAuxLevel = track.auxLevel << 16;
259 track.auxLevel = valueInt;
260 if (target == VOLUME) {
261 track.prevAuxLevel = valueInt << 16;
262 track.auxInc = 0;
263 } else {
264 int32_t d = (valueInt<<16) - track.prevAuxLevel;
265 int32_t volInc = d / int32_t(mState.frameCount);
266 track.auxInc = volInc;
267 if (volInc == 0) {
268 track.prevAuxLevel = valueInt << 16;
269 }
270 }
271 invalidateState(1<<mActiveTrack);
272 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700273 } break;
274 default:
275 // bad name
276 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700277 }
278 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700279
280 default:
281 // bad target
282 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700283 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700284}
285
286bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
287{
288 if (value!=devSampleRate || resampler) {
289 if (sampleRate != value) {
290 sampleRate = value;
Glenn Kastene0feee32011-12-13 11:53:26 -0800291 if (resampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700292 resampler = AudioResampler::create(
293 format, channelCount, devSampleRate);
294 }
295 return true;
296 }
297 }
298 return false;
299}
300
301bool AudioMixer::track_t::doesResample() const
302{
Glenn Kastene0feee32011-12-13 11:53:26 -0800303 return resampler != NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700304}
305
Eric Laurent243f5f92011-02-28 16:52:51 -0800306void AudioMixer::track_t::resetResampler()
307{
Glenn Kastene0feee32011-12-13 11:53:26 -0800308 if (resampler != NULL) {
Eric Laurent243f5f92011-02-28 16:52:51 -0800309 resampler->reset();
310 }
311}
312
Mathias Agopian65ab4712010-07-14 17:59:35 -0700313inline
314void AudioMixer::track_t::adjustVolumeRamp(bool aux)
315{
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800316 for (int i=0 ; i<MAX_NUM_CHANNELS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700317 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
318 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
319 volumeInc[i] = 0;
320 prevVolume[i] = volume[i]<<16;
321 }
322 }
323 if (aux) {
324 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
325 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
326 auxInc = 0;
327 prevAuxLevel = auxLevel<<16;
328 }
329 }
330}
331
332
Glenn Kastenfba380a2011-12-15 15:46:46 -0800333void AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700334{
335 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700336}
337
338
339
340void AudioMixer::process()
341{
342 mState.hook(&mState);
343}
344
345
346void AudioMixer::process__validate(state_t* state)
347{
348 LOGW_IF(!state->needsChanged,
349 "in process__validate() but nothing's invalid");
350
351 uint32_t changed = state->needsChanged;
352 state->needsChanged = 0; // clear the validation flag
353
354 // recompute which tracks are enabled / disabled
355 uint32_t enabled = 0;
356 uint32_t disabled = 0;
357 while (changed) {
358 const int i = 31 - __builtin_clz(changed);
359 const uint32_t mask = 1<<i;
360 changed &= ~mask;
361 track_t& t = state->tracks[i];
362 (t.enabled ? enabled : disabled) |= mask;
363 }
364 state->enabledTracks &= ~disabled;
365 state->enabledTracks |= enabled;
366
367 // compute everything we need...
368 int countActiveTracks = 0;
369 int all16BitsStereoNoResample = 1;
370 int resampling = 0;
371 int volumeRamp = 0;
372 uint32_t en = state->enabledTracks;
373 while (en) {
374 const int i = 31 - __builtin_clz(en);
375 en &= ~(1<<i);
376
377 countActiveTracks++;
378 track_t& t = state->tracks[i];
379 uint32_t n = 0;
380 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
381 n |= NEEDS_FORMAT_16;
382 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
383 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
384 n |= NEEDS_AUX_ENABLED;
385 }
386
387 if (t.volumeInc[0]|t.volumeInc[1]) {
388 volumeRamp = 1;
389 } else if (!t.doesResample() && t.volumeRL == 0) {
390 n |= NEEDS_MUTE_ENABLED;
391 }
392 t.needs = n;
393
394 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
395 t.hook = track__nop;
396 } else {
397 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
398 all16BitsStereoNoResample = 0;
399 }
400 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
401 all16BitsStereoNoResample = 0;
402 resampling = 1;
403 t.hook = track__genericResample;
404 } else {
405 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
406 t.hook = track__16BitsMono;
407 all16BitsStereoNoResample = 0;
408 }
409 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
410 t.hook = track__16BitsStereo;
411 }
412 }
413 }
414 }
415
416 // select the processing hooks
417 state->hook = process__nop;
418 if (countActiveTracks) {
419 if (resampling) {
420 if (!state->outputTemp) {
421 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
422 }
423 if (!state->resampleTemp) {
424 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
425 }
426 state->hook = process__genericResampling;
427 } else {
428 if (state->outputTemp) {
429 delete [] state->outputTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800430 state->outputTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700431 }
432 if (state->resampleTemp) {
433 delete [] state->resampleTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800434 state->resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700435 }
436 state->hook = process__genericNoResampling;
437 if (all16BitsStereoNoResample && !volumeRamp) {
438 if (countActiveTracks == 1) {
439 state->hook = process__OneTrack16BitsStereoNoResampling;
440 }
441 }
442 }
443 }
444
Steve Block3856b092011-10-20 11:56:00 +0100445 ALOGV("mixer configuration change: %d activeTracks (%08x) "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700446 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
447 countActiveTracks, state->enabledTracks,
448 all16BitsStereoNoResample, resampling, volumeRamp);
449
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800450 state->hook(state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700451
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800452 // Now that the volume ramp has been done, set optimal state and
453 // track hooks for subsequent mixer process
454 if (countActiveTracks) {
455 int allMuted = 1;
456 uint32_t en = state->enabledTracks;
457 while (en) {
458 const int i = 31 - __builtin_clz(en);
459 en &= ~(1<<i);
460 track_t& t = state->tracks[i];
461 if (!t.doesResample() && t.volumeRL == 0)
462 {
463 t.needs |= NEEDS_MUTE_ENABLED;
464 t.hook = track__nop;
465 } else {
466 allMuted = 0;
467 }
468 }
469 if (allMuted) {
470 state->hook = process__nop;
471 } else if (all16BitsStereoNoResample) {
472 if (countActiveTracks == 1) {
473 state->hook = process__OneTrack16BitsStereoNoResampling;
474 }
475 }
476 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700477}
478
Mathias Agopian65ab4712010-07-14 17:59:35 -0700479
480void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
481{
482 t->resampler->setSampleRate(t->sampleRate);
483
484 // ramp gain - resample to temp buffer and scale/mix in 2nd step
485 if (aux != NULL) {
486 // always resample with unity gain when sending to auxiliary buffer to be able
487 // to apply send level after resampling
488 // TODO: modify each resampler to support aux channel?
489 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
490 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
491 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
492 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
493 volumeRampStereo(t, out, outFrameCount, temp, aux);
494 } else {
495 volumeStereo(t, out, outFrameCount, temp, aux);
496 }
497 } else {
498 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
499 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
500 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
501 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
502 volumeRampStereo(t, out, outFrameCount, temp, aux);
503 }
504
505 // constant gain
506 else {
507 t->resampler->setVolume(t->volume[0], t->volume[1]);
508 t->resampler->resample(out, outFrameCount, t->bufferProvider);
509 }
510 }
511}
512
513void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
514{
515}
516
517void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
518{
519 int32_t vl = t->prevVolume[0];
520 int32_t vr = t->prevVolume[1];
521 const int32_t vlInc = t->volumeInc[0];
522 const int32_t vrInc = t->volumeInc[1];
523
Steve Blockb8a80522011-12-20 16:23:08 +0000524 //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700525 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
526 // (vl + vlInc*frameCount)/65536.0f, frameCount);
527
528 // ramp volume
529 if UNLIKELY(aux != NULL) {
530 int32_t va = t->prevAuxLevel;
531 const int32_t vaInc = t->auxInc;
532 int32_t l;
533 int32_t r;
534
535 do {
536 l = (*temp++ >> 12);
537 r = (*temp++ >> 12);
538 *out++ += (vl >> 16) * l;
539 *out++ += (vr >> 16) * r;
540 *aux++ += (va >> 17) * (l + r);
541 vl += vlInc;
542 vr += vrInc;
543 va += vaInc;
544 } while (--frameCount);
545 t->prevAuxLevel = va;
546 } else {
547 do {
548 *out++ += (vl >> 16) * (*temp++ >> 12);
549 *out++ += (vr >> 16) * (*temp++ >> 12);
550 vl += vlInc;
551 vr += vrInc;
552 } while (--frameCount);
553 }
554 t->prevVolume[0] = vl;
555 t->prevVolume[1] = vr;
556 t->adjustVolumeRamp((aux != NULL));
557}
558
559void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
560{
561 const int16_t vl = t->volume[0];
562 const int16_t vr = t->volume[1];
563
564 if UNLIKELY(aux != NULL) {
565 const int16_t va = (int16_t)t->auxLevel;
566 do {
567 int16_t l = (int16_t)(*temp++ >> 12);
568 int16_t r = (int16_t)(*temp++ >> 12);
569 out[0] = mulAdd(l, vl, out[0]);
570 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
571 out[1] = mulAdd(r, vr, out[1]);
572 out += 2;
573 aux[0] = mulAdd(a, va, aux[0]);
574 aux++;
575 } while (--frameCount);
576 } else {
577 do {
578 int16_t l = (int16_t)(*temp++ >> 12);
579 int16_t r = (int16_t)(*temp++ >> 12);
580 out[0] = mulAdd(l, vl, out[0]);
581 out[1] = mulAdd(r, vr, out[1]);
582 out += 2;
583 } while (--frameCount);
584 }
585}
586
587void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
588{
589 int16_t const *in = static_cast<int16_t const *>(t->in);
590
591 if UNLIKELY(aux != NULL) {
592 int32_t l;
593 int32_t r;
594 // ramp gain
595 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
596 int32_t vl = t->prevVolume[0];
597 int32_t vr = t->prevVolume[1];
598 int32_t va = t->prevAuxLevel;
599 const int32_t vlInc = t->volumeInc[0];
600 const int32_t vrInc = t->volumeInc[1];
601 const int32_t vaInc = t->auxInc;
Steve Blockb8a80522011-12-20 16:23:08 +0000602 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700603 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
604 // (vl + vlInc*frameCount)/65536.0f, frameCount);
605
606 do {
607 l = (int32_t)*in++;
608 r = (int32_t)*in++;
609 *out++ += (vl >> 16) * l;
610 *out++ += (vr >> 16) * r;
611 *aux++ += (va >> 17) * (l + r);
612 vl += vlInc;
613 vr += vrInc;
614 va += vaInc;
615 } while (--frameCount);
616
617 t->prevVolume[0] = vl;
618 t->prevVolume[1] = vr;
619 t->prevAuxLevel = va;
620 t->adjustVolumeRamp(true);
621 }
622
623 // constant gain
624 else {
625 const uint32_t vrl = t->volumeRL;
626 const int16_t va = (int16_t)t->auxLevel;
627 do {
628 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
629 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
630 in += 2;
631 out[0] = mulAddRL(1, rl, vrl, out[0]);
632 out[1] = mulAddRL(0, rl, vrl, out[1]);
633 out += 2;
634 aux[0] = mulAdd(a, va, aux[0]);
635 aux++;
636 } while (--frameCount);
637 }
638 } else {
639 // ramp gain
640 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
641 int32_t vl = t->prevVolume[0];
642 int32_t vr = t->prevVolume[1];
643 const int32_t vlInc = t->volumeInc[0];
644 const int32_t vrInc = t->volumeInc[1];
645
Steve Blockb8a80522011-12-20 16:23:08 +0000646 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700647 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
648 // (vl + vlInc*frameCount)/65536.0f, frameCount);
649
650 do {
651 *out++ += (vl >> 16) * (int32_t) *in++;
652 *out++ += (vr >> 16) * (int32_t) *in++;
653 vl += vlInc;
654 vr += vrInc;
655 } while (--frameCount);
656
657 t->prevVolume[0] = vl;
658 t->prevVolume[1] = vr;
659 t->adjustVolumeRamp(false);
660 }
661
662 // constant gain
663 else {
664 const uint32_t vrl = t->volumeRL;
665 do {
666 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
667 in += 2;
668 out[0] = mulAddRL(1, rl, vrl, out[0]);
669 out[1] = mulAddRL(0, rl, vrl, out[1]);
670 out += 2;
671 } while (--frameCount);
672 }
673 }
674 t->in = in;
675}
676
677void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
678{
679 int16_t const *in = static_cast<int16_t const *>(t->in);
680
681 if UNLIKELY(aux != NULL) {
682 // ramp gain
683 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
684 int32_t vl = t->prevVolume[0];
685 int32_t vr = t->prevVolume[1];
686 int32_t va = t->prevAuxLevel;
687 const int32_t vlInc = t->volumeInc[0];
688 const int32_t vrInc = t->volumeInc[1];
689 const int32_t vaInc = t->auxInc;
690
Steve Blockb8a80522011-12-20 16:23:08 +0000691 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700692 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
693 // (vl + vlInc*frameCount)/65536.0f, frameCount);
694
695 do {
696 int32_t l = *in++;
697 *out++ += (vl >> 16) * l;
698 *out++ += (vr >> 16) * l;
699 *aux++ += (va >> 16) * l;
700 vl += vlInc;
701 vr += vrInc;
702 va += vaInc;
703 } while (--frameCount);
704
705 t->prevVolume[0] = vl;
706 t->prevVolume[1] = vr;
707 t->prevAuxLevel = va;
708 t->adjustVolumeRamp(true);
709 }
710 // constant gain
711 else {
712 const int16_t vl = t->volume[0];
713 const int16_t vr = t->volume[1];
714 const int16_t va = (int16_t)t->auxLevel;
715 do {
716 int16_t l = *in++;
717 out[0] = mulAdd(l, vl, out[0]);
718 out[1] = mulAdd(l, vr, out[1]);
719 out += 2;
720 aux[0] = mulAdd(l, va, aux[0]);
721 aux++;
722 } while (--frameCount);
723 }
724 } else {
725 // ramp gain
726 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
727 int32_t vl = t->prevVolume[0];
728 int32_t vr = t->prevVolume[1];
729 const int32_t vlInc = t->volumeInc[0];
730 const int32_t vrInc = t->volumeInc[1];
731
Steve Blockb8a80522011-12-20 16:23:08 +0000732 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700733 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
734 // (vl + vlInc*frameCount)/65536.0f, frameCount);
735
736 do {
737 int32_t l = *in++;
738 *out++ += (vl >> 16) * l;
739 *out++ += (vr >> 16) * l;
740 vl += vlInc;
741 vr += vrInc;
742 } while (--frameCount);
743
744 t->prevVolume[0] = vl;
745 t->prevVolume[1] = vr;
746 t->adjustVolumeRamp(false);
747 }
748 // constant gain
749 else {
750 const int16_t vl = t->volume[0];
751 const int16_t vr = t->volume[1];
752 do {
753 int16_t l = *in++;
754 out[0] = mulAdd(l, vl, out[0]);
755 out[1] = mulAdd(l, vr, out[1]);
756 out += 2;
757 } while (--frameCount);
758 }
759 }
760 t->in = in;
761}
762
Mathias Agopian65ab4712010-07-14 17:59:35 -0700763// no-op case
764void AudioMixer::process__nop(state_t* state)
765{
766 uint32_t e0 = state->enabledTracks;
767 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
768 while (e0) {
769 // process by group of tracks with same output buffer to
770 // avoid multiple memset() on same buffer
771 uint32_t e1 = e0, e2 = e0;
772 int i = 31 - __builtin_clz(e1);
773 track_t& t1 = state->tracks[i];
774 e2 &= ~(1<<i);
775 while (e2) {
776 i = 31 - __builtin_clz(e2);
777 e2 &= ~(1<<i);
778 track_t& t2 = state->tracks[i];
779 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
780 e1 &= ~(1<<i);
781 }
782 }
783 e0 &= ~(e1);
784
785 memset(t1.mainBuffer, 0, bufSize);
786
787 while (e1) {
788 i = 31 - __builtin_clz(e1);
789 e1 &= ~(1<<i);
790 t1 = state->tracks[i];
791 size_t outFrames = state->frameCount;
792 while (outFrames) {
793 t1.buffer.frameCount = outFrames;
794 t1.bufferProvider->getNextBuffer(&t1.buffer);
795 if (!t1.buffer.raw) break;
796 outFrames -= t1.buffer.frameCount;
797 t1.bufferProvider->releaseBuffer(&t1.buffer);
798 }
799 }
800 }
801}
802
803// generic code without resampling
804void AudioMixer::process__genericNoResampling(state_t* state)
805{
806 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
807
808 // acquire each track's buffer
809 uint32_t enabledTracks = state->enabledTracks;
810 uint32_t e0 = enabledTracks;
811 while (e0) {
812 const int i = 31 - __builtin_clz(e0);
813 e0 &= ~(1<<i);
814 track_t& t = state->tracks[i];
815 t.buffer.frameCount = state->frameCount;
816 t.bufferProvider->getNextBuffer(&t.buffer);
817 t.frameCount = t.buffer.frameCount;
818 t.in = t.buffer.raw;
819 // t.in == NULL can happen if the track was flushed just after having
820 // been enabled for mixing.
821 if (t.in == NULL)
822 enabledTracks &= ~(1<<i);
823 }
824
825 e0 = enabledTracks;
826 while (e0) {
827 // process by group of tracks with same output buffer to
828 // optimize cache use
829 uint32_t e1 = e0, e2 = e0;
830 int j = 31 - __builtin_clz(e1);
831 track_t& t1 = state->tracks[j];
832 e2 &= ~(1<<j);
833 while (e2) {
834 j = 31 - __builtin_clz(e2);
835 e2 &= ~(1<<j);
836 track_t& t2 = state->tracks[j];
837 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
838 e1 &= ~(1<<j);
839 }
840 }
841 e0 &= ~(e1);
842 // this assumes output 16 bits stereo, no resampling
843 int32_t *out = t1.mainBuffer;
844 size_t numFrames = 0;
845 do {
846 memset(outTemp, 0, sizeof(outTemp));
847 e2 = e1;
848 while (e2) {
849 const int i = 31 - __builtin_clz(e2);
850 e2 &= ~(1<<i);
851 track_t& t = state->tracks[i];
852 size_t outFrames = BLOCKSIZE;
853 int32_t *aux = NULL;
854 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
855 aux = t.auxBuffer + numFrames;
856 }
857 while (outFrames) {
858 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
859 if (inFrames) {
860 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
861 t.frameCount -= inFrames;
862 outFrames -= inFrames;
863 if UNLIKELY(aux != NULL) {
864 aux += inFrames;
865 }
866 }
867 if (t.frameCount == 0 && outFrames) {
868 t.bufferProvider->releaseBuffer(&t.buffer);
869 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
870 t.bufferProvider->getNextBuffer(&t.buffer);
871 t.in = t.buffer.raw;
872 if (t.in == NULL) {
873 enabledTracks &= ~(1<<i);
874 e1 &= ~(1<<i);
875 break;
876 }
877 t.frameCount = t.buffer.frameCount;
878 }
879 }
880 }
881 ditherAndClamp(out, outTemp, BLOCKSIZE);
882 out += BLOCKSIZE;
883 numFrames += BLOCKSIZE;
884 } while (numFrames < state->frameCount);
885 }
886
887 // release each track's buffer
888 e0 = enabledTracks;
889 while (e0) {
890 const int i = 31 - __builtin_clz(e0);
891 e0 &= ~(1<<i);
892 track_t& t = state->tracks[i];
893 t.bufferProvider->releaseBuffer(&t.buffer);
894 }
895}
896
897
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800898// generic code with resampling
Mathias Agopian65ab4712010-07-14 17:59:35 -0700899void AudioMixer::process__genericResampling(state_t* state)
900{
901 int32_t* const outTemp = state->outputTemp;
902 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700903
904 size_t numFrames = state->frameCount;
905
906 uint32_t e0 = state->enabledTracks;
907 while (e0) {
908 // process by group of tracks with same output buffer
909 // to optimize cache use
910 uint32_t e1 = e0, e2 = e0;
911 int j = 31 - __builtin_clz(e1);
912 track_t& t1 = state->tracks[j];
913 e2 &= ~(1<<j);
914 while (e2) {
915 j = 31 - __builtin_clz(e2);
916 e2 &= ~(1<<j);
917 track_t& t2 = state->tracks[j];
918 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
919 e1 &= ~(1<<j);
920 }
921 }
922 e0 &= ~(e1);
923 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi2151d7b2011-02-04 15:24:34 +0100924 memset(outTemp, 0, size);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700925 while (e1) {
926 const int i = 31 - __builtin_clz(e1);
927 e1 &= ~(1<<i);
928 track_t& t = state->tracks[i];
929 int32_t *aux = NULL;
930 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
931 aux = t.auxBuffer;
932 }
933
934 // this is a little goofy, on the resampling case we don't
935 // acquire/release the buffers because it's done by
936 // the resampler.
937 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
938 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
939 } else {
940
941 size_t outFrames = 0;
942
943 while (outFrames < numFrames) {
944 t.buffer.frameCount = numFrames - outFrames;
945 t.bufferProvider->getNextBuffer(&t.buffer);
946 t.in = t.buffer.raw;
947 // t.in == NULL can happen if the track was flushed just after having
948 // been enabled for mixing.
949 if (t.in == NULL) break;
950
951 if UNLIKELY(aux != NULL) {
952 aux += outFrames;
953 }
954 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
955 outFrames += t.buffer.frameCount;
956 t.bufferProvider->releaseBuffer(&t.buffer);
957 }
958 }
959 }
960 ditherAndClamp(out, outTemp, numFrames);
961 }
962}
963
964// one track, 16 bits stereo without resampling is the most common case
965void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
966{
967 const int i = 31 - __builtin_clz(state->enabledTracks);
968 const track_t& t = state->tracks[i];
969
970 AudioBufferProvider::Buffer& b(t.buffer);
971
972 int32_t* out = t.mainBuffer;
973 size_t numFrames = state->frameCount;
974
975 const int16_t vl = t.volume[0];
976 const int16_t vr = t.volume[1];
977 const uint32_t vrl = t.volumeRL;
978 while (numFrames) {
979 b.frameCount = numFrames;
980 t.bufferProvider->getNextBuffer(&b);
981 int16_t const *in = b.i16;
982
983 // in == NULL can happen if the track was flushed just after having
984 // been enabled for mixing.
985 if (in == NULL || ((unsigned long)in & 3)) {
986 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
987 LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
988 in, i, t.channelCount, t.needs);
989 return;
990 }
991 size_t outFrames = b.frameCount;
992
993 if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
994 // volume is boosted, so we might need to clamp even though
995 // we process only one track.
996 do {
997 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
998 in += 2;
999 int32_t l = mulRL(1, rl, vrl) >> 12;
1000 int32_t r = mulRL(0, rl, vrl) >> 12;
1001 // clamping...
1002 l = clamp16(l);
1003 r = clamp16(r);
1004 *out++ = (r<<16) | (l & 0xFFFF);
1005 } while (--outFrames);
1006 } else {
1007 do {
1008 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1009 in += 2;
1010 int32_t l = mulRL(1, rl, vrl) >> 12;
1011 int32_t r = mulRL(0, rl, vrl) >> 12;
1012 *out++ = (r<<16) | (l & 0xFFFF);
1013 } while (--outFrames);
1014 }
1015 numFrames -= b.frameCount;
1016 t.bufferProvider->releaseBuffer(&b);
1017 }
1018}
1019
Glenn Kasten81a028f2011-12-15 09:53:12 -08001020#if 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07001021// 2 tracks is also a common case
1022// NEVER used in current implementation of process__validate()
1023// only use if the 2 tracks have the same output buffer
1024void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
1025{
1026 int i;
1027 uint32_t en = state->enabledTracks;
1028
1029 i = 31 - __builtin_clz(en);
1030 const track_t& t0 = state->tracks[i];
1031 AudioBufferProvider::Buffer& b0(t0.buffer);
1032
1033 en &= ~(1<<i);
1034 i = 31 - __builtin_clz(en);
1035 const track_t& t1 = state->tracks[i];
1036 AudioBufferProvider::Buffer& b1(t1.buffer);
1037
1038 int16_t const *in0;
1039 const int16_t vl0 = t0.volume[0];
1040 const int16_t vr0 = t0.volume[1];
1041 size_t frameCount0 = 0;
1042
1043 int16_t const *in1;
1044 const int16_t vl1 = t1.volume[0];
1045 const int16_t vr1 = t1.volume[1];
1046 size_t frameCount1 = 0;
1047
1048 //FIXME: only works if two tracks use same buffer
1049 int32_t* out = t0.mainBuffer;
1050 size_t numFrames = state->frameCount;
1051 int16_t const *buff = NULL;
1052
1053
1054 while (numFrames) {
1055
1056 if (frameCount0 == 0) {
1057 b0.frameCount = numFrames;
1058 t0.bufferProvider->getNextBuffer(&b0);
1059 if (b0.i16 == NULL) {
1060 if (buff == NULL) {
1061 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1062 }
1063 in0 = buff;
1064 b0.frameCount = numFrames;
1065 } else {
1066 in0 = b0.i16;
1067 }
1068 frameCount0 = b0.frameCount;
1069 }
1070 if (frameCount1 == 0) {
1071 b1.frameCount = numFrames;
1072 t1.bufferProvider->getNextBuffer(&b1);
1073 if (b1.i16 == NULL) {
1074 if (buff == NULL) {
1075 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1076 }
1077 in1 = buff;
1078 b1.frameCount = numFrames;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001079 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001080 in1 = b1.i16;
1081 }
1082 frameCount1 = b1.frameCount;
1083 }
1084
1085 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1086
1087 numFrames -= outFrames;
1088 frameCount0 -= outFrames;
1089 frameCount1 -= outFrames;
1090
1091 do {
1092 int32_t l0 = *in0++;
1093 int32_t r0 = *in0++;
1094 l0 = mul(l0, vl0);
1095 r0 = mul(r0, vr0);
1096 int32_t l = *in1++;
1097 int32_t r = *in1++;
1098 l = mulAdd(l, vl1, l0) >> 12;
1099 r = mulAdd(r, vr1, r0) >> 12;
1100 // clamping...
1101 l = clamp16(l);
1102 r = clamp16(r);
1103 *out++ = (r<<16) | (l & 0xFFFF);
1104 } while (--outFrames);
1105
1106 if (frameCount0 == 0) {
1107 t0.bufferProvider->releaseBuffer(&b0);
1108 }
1109 if (frameCount1 == 0) {
1110 t1.bufferProvider->releaseBuffer(&b1);
1111 }
1112 }
1113
1114 if (buff != NULL) {
1115 delete [] buff;
1116 }
1117}
Glenn Kasten81a028f2011-12-15 09:53:12 -08001118#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001119
1120// ----------------------------------------------------------------------------
1121}; // namespace android