blob: 7c7fa5618e9bedec69eb19e1b64d13b57447606b [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
21#include <stdint.h>
22#include <string.h>
23#include <stdlib.h>
24#include <sys/types.h>
25
26#include <utils/Errors.h>
27#include <utils/Log.h>
28
Jean-Michel Trivi54392232011-05-24 15:53:33 -070029#include <cutils/bitops.h>
30
31#include <system/audio.h>
32
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033#include "AudioMixer.h"
34
35namespace android {
36// ----------------------------------------------------------------------------
37
38static inline int16_t clamp16(int32_t sample)
39{
40 if ((sample>>15) ^ (sample>>31))
41 sample = 0x7FFF ^ (sample>>31);
42 return sample;
43}
44
45// ----------------------------------------------------------------------------
46
47AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
48 : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
49{
50 mState.enabledTracks= 0;
51 mState.needsChanged = 0;
52 mState.frameCount = frameCount;
53 mState.outputTemp = 0;
54 mState.resampleTemp = 0;
55 mState.hook = process__nop;
56 track_t* t = mState.tracks;
57 for (int i=0 ; i<32 ; i++) {
58 t->needs = 0;
59 t->volume[0] = UNITY_GAIN;
60 t->volume[1] = UNITY_GAIN;
61 t->volumeInc[0] = 0;
62 t->volumeInc[1] = 0;
Eric Laurent65b65452010-06-01 23:49:17 -070063 t->auxLevel = 0;
64 t->auxInc = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 t->channelCount = 2;
66 t->enabled = 0;
67 t->format = 16;
Jean-Michel Trivi54392232011-05-24 15:53:33 -070068 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 t->buffer.raw = 0;
70 t->bufferProvider = 0;
71 t->hook = 0;
72 t->resampler = 0;
73 t->sampleRate = mSampleRate;
74 t->in = 0;
Eric Laurent65b65452010-06-01 23:49:17 -070075 t->mainBuffer = NULL;
76 t->auxBuffer = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 t++;
78 }
79}
80
81 AudioMixer::~AudioMixer()
82 {
83 track_t* t = mState.tracks;
84 for (int i=0 ; i<32 ; i++) {
85 delete t->resampler;
86 t++;
87 }
88 delete [] mState.outputTemp;
89 delete [] mState.resampleTemp;
90 }
91
92 int AudioMixer::getTrackName()
93 {
94 uint32_t names = mTrackNames;
95 uint32_t mask = 1;
96 int n = 0;
97 while (names & mask) {
98 mask <<= 1;
99 n++;
100 }
101 if (mask) {
Steve Block71f2cf12011-10-20 11:56:00 +0100102 ALOGV("add track (%d)", n);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 mTrackNames |= mask;
104 return TRACK0 + n;
105 }
106 return -1;
107 }
108
109 void AudioMixer::invalidateState(uint32_t mask)
110 {
111 if (mask) {
112 mState.needsChanged |= mask;
113 mState.hook = process__validate;
114 }
115 }
116
117 void AudioMixer::deleteTrackName(int name)
118 {
119 name -= TRACK0;
120 if (uint32_t(name) < MAX_NUM_TRACKS) {
Steve Block71f2cf12011-10-20 11:56:00 +0100121 ALOGV("deleteTrackName(%d)", name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 track_t& track(mState.tracks[ name ]);
123 if (track.enabled != 0) {
124 track.enabled = 0;
125 invalidateState(1<<name);
126 }
127 if (track.resampler) {
128 // delete the resampler
129 delete track.resampler;
130 track.resampler = 0;
131 track.sampleRate = mSampleRate;
132 invalidateState(1<<name);
133 }
134 track.volumeInc[0] = 0;
135 track.volumeInc[1] = 0;
136 mTrackNames &= ~(1<<name);
137 }
138 }
139
140status_t AudioMixer::enable(int name)
141{
142 switch (name) {
143 case MIXING: {
144 if (mState.tracks[ mActiveTrack ].enabled != 1) {
145 mState.tracks[ mActiveTrack ].enabled = 1;
Steve Block71f2cf12011-10-20 11:56:00 +0100146 ALOGV("enable(%d)", mActiveTrack);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 invalidateState(1<<mActiveTrack);
148 }
149 } break;
150 default:
151 return NAME_NOT_FOUND;
152 }
153 return NO_ERROR;
154}
155
156status_t AudioMixer::disable(int name)
157{
158 switch (name) {
159 case MIXING: {
160 if (mState.tracks[ mActiveTrack ].enabled != 0) {
161 mState.tracks[ mActiveTrack ].enabled = 0;
Steve Block71f2cf12011-10-20 11:56:00 +0100162 ALOGV("disable(%d)", mActiveTrack);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 invalidateState(1<<mActiveTrack);
164 }
165 } break;
166 default:
167 return NAME_NOT_FOUND;
168 }
169 return NO_ERROR;
170}
171
172status_t AudioMixer::setActiveTrack(int track)
173{
174 if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) {
175 return BAD_VALUE;
176 }
177 mActiveTrack = track - TRACK0;
178 return NO_ERROR;
179}
180
Eric Laurent65b65452010-06-01 23:49:17 -0700181status_t AudioMixer::setParameter(int target, int name, void *value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182{
Eric Laurent65b65452010-06-01 23:49:17 -0700183 int valueInt = (int)value;
184 int32_t *valueBuf = (int32_t *)value;
185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 switch (target) {
187 case TRACK:
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700188 if (name == CHANNEL_MASK) {
189 uint32_t mask = (uint32_t)value;
190 if (mState.tracks[ mActiveTrack ].channelMask != mask) {
191 uint8_t channelCount = popcount(mask);
192 if ((channelCount <= MAX_NUM_CHANNELS) && (channelCount)) {
193 mState.tracks[ mActiveTrack ].channelMask = mask;
194 mState.tracks[ mActiveTrack ].channelCount = channelCount;
Steve Block71f2cf12011-10-20 11:56:00 +0100195 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 invalidateState(1<<mActiveTrack);
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700197 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 }
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700199 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 return NO_ERROR;
201 }
202 }
Eric Laurent65b65452010-06-01 23:49:17 -0700203 if (name == MAIN_BUFFER) {
204 if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
205 mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
Steve Block71f2cf12011-10-20 11:56:00 +0100206 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Eric Laurent65b65452010-06-01 23:49:17 -0700207 invalidateState(1<<mActiveTrack);
208 }
209 return NO_ERROR;
210 }
211 if (name == AUX_BUFFER) {
212 if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
213 mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
Steve Block71f2cf12011-10-20 11:56:00 +0100214 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Eric Laurent65b65452010-06-01 23:49:17 -0700215 invalidateState(1<<mActiveTrack);
216 }
217 return NO_ERROR;
218 }
219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 break;
221 case RESAMPLE:
222 if (name == SAMPLE_RATE) {
Eric Laurent65b65452010-06-01 23:49:17 -0700223 if (valueInt > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 track_t& track = mState.tracks[ mActiveTrack ];
Eric Laurent65b65452010-06-01 23:49:17 -0700225 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
Steve Block71f2cf12011-10-20 11:56:00 +0100226 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
Eric Laurent65b65452010-06-01 23:49:17 -0700227 uint32_t(valueInt));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 invalidateState(1<<mActiveTrack);
229 }
230 return NO_ERROR;
231 }
232 }
Eric Laurent4bb21c42011-02-28 16:52:51 -0800233 if (name == RESET) {
234 track_t& track = mState.tracks[ mActiveTrack ];
235 track.resetResampler();
236 invalidateState(1<<mActiveTrack);
237 return NO_ERROR;
238 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 break;
240 case RAMP_VOLUME:
241 case VOLUME:
242 if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) {
243 track_t& track = mState.tracks[ mActiveTrack ];
Eric Laurent65b65452010-06-01 23:49:17 -0700244 if (track.volume[name-VOLUME0] != valueInt) {
Steve Block71f2cf12011-10-20 11:56:00 +0100245 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
Eric Laurent65b65452010-06-01 23:49:17 -0700247 track.volume[name-VOLUME0] = valueInt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 if (target == VOLUME) {
Eric Laurent65b65452010-06-01 23:49:17 -0700249 track.prevVolume[name-VOLUME0] = valueInt << 16;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 track.volumeInc[name-VOLUME0] = 0;
251 } else {
Eric Laurent65b65452010-06-01 23:49:17 -0700252 int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 int32_t volInc = d / int32_t(mState.frameCount);
254 track.volumeInc[name-VOLUME0] = volInc;
255 if (volInc == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -0700256 track.prevVolume[name-VOLUME0] = valueInt << 16;
257 }
258 }
259 invalidateState(1<<mActiveTrack);
260 }
261 return NO_ERROR;
262 } else if (name == AUXLEVEL) {
263 track_t& track = mState.tracks[ mActiveTrack ];
264 if (track.auxLevel != valueInt) {
Steve Block71f2cf12011-10-20 11:56:00 +0100265 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Eric Laurent65b65452010-06-01 23:49:17 -0700266 track.prevAuxLevel = track.auxLevel << 16;
267 track.auxLevel = valueInt;
268 if (target == VOLUME) {
269 track.prevAuxLevel = valueInt << 16;
270 track.auxInc = 0;
271 } else {
272 int32_t d = (valueInt<<16) - track.prevAuxLevel;
273 int32_t volInc = d / int32_t(mState.frameCount);
274 track.auxInc = volInc;
275 if (volInc == 0) {
276 track.prevAuxLevel = valueInt << 16;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 }
278 }
279 invalidateState(1<<mActiveTrack);
280 }
281 return NO_ERROR;
282 }
283 break;
284 }
285 return BAD_VALUE;
286}
287
288bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
289{
290 if (value!=devSampleRate || resampler) {
291 if (sampleRate != value) {
292 sampleRate = value;
293 if (resampler == 0) {
294 resampler = AudioResampler::create(
295 format, channelCount, devSampleRate);
296 }
297 return true;
298 }
299 }
300 return false;
301}
302
303bool AudioMixer::track_t::doesResample() const
304{
305 return resampler != 0;
306}
307
Eric Laurent4bb21c42011-02-28 16:52:51 -0800308void AudioMixer::track_t::resetResampler()
309{
310 if (resampler != 0) {
311 resampler->reset();
312 }
313}
314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315inline
Eric Laurent65b65452010-06-01 23:49:17 -0700316void AudioMixer::track_t::adjustVolumeRamp(bool aux)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317{
318 for (int i=0 ; i<2 ; i++) {
319 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
320 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
321 volumeInc[i] = 0;
322 prevVolume[i] = volume[i]<<16;
323 }
324 }
Eric Laurent65b65452010-06-01 23:49:17 -0700325 if (aux) {
326 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
327 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
328 auxInc = 0;
329 prevAuxLevel = auxLevel<<16;
330 }
331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332}
333
334
335status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
336{
337 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
338 return NO_ERROR;
339}
340
341
342
Eric Laurent65b65452010-06-01 23:49:17 -0700343void AudioMixer::process()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344{
Eric Laurent65b65452010-06-01 23:49:17 -0700345 mState.hook(&mState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346}
347
348
Eric Laurent65b65452010-06-01 23:49:17 -0700349void AudioMixer::process__validate(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350{
351 LOGW_IF(!state->needsChanged,
352 "in process__validate() but nothing's invalid");
353
354 uint32_t changed = state->needsChanged;
355 state->needsChanged = 0; // clear the validation flag
356
357 // recompute which tracks are enabled / disabled
358 uint32_t enabled = 0;
359 uint32_t disabled = 0;
360 while (changed) {
361 const int i = 31 - __builtin_clz(changed);
362 const uint32_t mask = 1<<i;
363 changed &= ~mask;
364 track_t& t = state->tracks[i];
365 (t.enabled ? enabled : disabled) |= mask;
366 }
367 state->enabledTracks &= ~disabled;
368 state->enabledTracks |= enabled;
369
370 // compute everything we need...
371 int countActiveTracks = 0;
372 int all16BitsStereoNoResample = 1;
373 int resampling = 0;
374 int volumeRamp = 0;
375 uint32_t en = state->enabledTracks;
376 while (en) {
377 const int i = 31 - __builtin_clz(en);
378 en &= ~(1<<i);
379
380 countActiveTracks++;
381 track_t& t = state->tracks[i];
382 uint32_t n = 0;
383 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
384 n |= NEEDS_FORMAT_16;
385 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
Eric Laurent65b65452010-06-01 23:49:17 -0700386 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
387 n |= NEEDS_AUX_ENABLED;
388 }
389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 if (t.volumeInc[0]|t.volumeInc[1]) {
391 volumeRamp = 1;
392 } else if (!t.doesResample() && t.volumeRL == 0) {
393 n |= NEEDS_MUTE_ENABLED;
394 }
395 t.needs = n;
396
397 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
398 t.hook = track__nop;
399 } else {
Eric Laurent65b65452010-06-01 23:49:17 -0700400 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
401 all16BitsStereoNoResample = 0;
402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
404 all16BitsStereoNoResample = 0;
405 resampling = 1;
406 t.hook = track__genericResample;
407 } else {
408 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
409 t.hook = track__16BitsMono;
410 all16BitsStereoNoResample = 0;
411 }
412 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
413 t.hook = track__16BitsStereo;
414 }
415 }
416 }
417 }
418
419 // select the processing hooks
420 state->hook = process__nop;
421 if (countActiveTracks) {
422 if (resampling) {
423 if (!state->outputTemp) {
424 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
425 }
426 if (!state->resampleTemp) {
427 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
428 }
429 state->hook = process__genericResampling;
430 } else {
431 if (state->outputTemp) {
432 delete [] state->outputTemp;
433 state->outputTemp = 0;
434 }
435 if (state->resampleTemp) {
436 delete [] state->resampleTemp;
437 state->resampleTemp = 0;
438 }
439 state->hook = process__genericNoResampling;
440 if (all16BitsStereoNoResample && !volumeRamp) {
441 if (countActiveTracks == 1) {
442 state->hook = process__OneTrack16BitsStereoNoResampling;
443 }
444 }
445 }
446 }
447
Steve Block71f2cf12011-10-20 11:56:00 +0100448 ALOGV("mixer configuration change: %d activeTracks (%08x) "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
450 countActiveTracks, state->enabledTracks,
451 all16BitsStereoNoResample, resampling, volumeRamp);
452
Eric Laurent65b65452010-06-01 23:49:17 -0700453 state->hook(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454
455 // Now that the volume ramp has been done, set optimal state and
456 // track hooks for subsequent mixer process
457 if (countActiveTracks) {
458 int allMuted = 1;
459 uint32_t en = state->enabledTracks;
460 while (en) {
461 const int i = 31 - __builtin_clz(en);
462 en &= ~(1<<i);
463 track_t& t = state->tracks[i];
464 if (!t.doesResample() && t.volumeRL == 0)
465 {
466 t.needs |= NEEDS_MUTE_ENABLED;
467 t.hook = track__nop;
468 } else {
469 allMuted = 0;
470 }
471 }
472 if (allMuted) {
473 state->hook = process__nop;
Eric Laurent65b65452010-06-01 23:49:17 -0700474 } else if (all16BitsStereoNoResample) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 if (countActiveTracks == 1) {
476 state->hook = process__OneTrack16BitsStereoNoResampling;
477 }
478 }
479 }
480}
481
482static inline
483int32_t mulAdd(int16_t in, int16_t v, int32_t a)
484{
485#if defined(__arm__) && !defined(__thumb__)
486 int32_t out;
487 asm( "smlabb %[out], %[in], %[v], %[a] \n"
488 : [out]"=r"(out)
489 : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
490 : );
491 return out;
492#else
493 return a + in * int32_t(v);
494#endif
495}
496
497static inline
498int32_t mul(int16_t in, int16_t v)
499{
500#if defined(__arm__) && !defined(__thumb__)
501 int32_t out;
502 asm( "smulbb %[out], %[in], %[v] \n"
503 : [out]"=r"(out)
504 : [in]"%r"(in), [v]"r"(v)
505 : );
506 return out;
507#else
508 return in * int32_t(v);
509#endif
510}
511
512static inline
513int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
514{
515#if defined(__arm__) && !defined(__thumb__)
516 int32_t out;
517 if (left) {
518 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
519 : [out]"=r"(out)
520 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
521 : );
522 } else {
523 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
524 : [out]"=r"(out)
525 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
526 : );
527 }
528 return out;
529#else
530 if (left) {
531 return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
532 } else {
533 return a + int16_t(inRL>>16) * int16_t(vRL>>16);
534 }
535#endif
536}
537
538static inline
539int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
540{
541#if defined(__arm__) && !defined(__thumb__)
542 int32_t out;
543 if (left) {
544 asm( "smulbb %[out], %[inRL], %[vRL] \n"
545 : [out]"=r"(out)
546 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
547 : );
548 } else {
549 asm( "smultt %[out], %[inRL], %[vRL] \n"
550 : [out]"=r"(out)
551 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
552 : );
553 }
554 return out;
555#else
556 if (left) {
557 return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
558 } else {
559 return int16_t(inRL>>16) * int16_t(vRL>>16);
560 }
561#endif
562}
563
564
Eric Laurent65b65452010-06-01 23:49:17 -0700565void 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 -0800566{
567 t->resampler->setSampleRate(t->sampleRate);
568
569 // ramp gain - resample to temp buffer and scale/mix in 2nd step
Eric Laurent65b65452010-06-01 23:49:17 -0700570 if (aux != NULL) {
571 // always resample with unity gain when sending to auxiliary buffer to be able
572 // to apply send level after resampling
573 // TODO: modify each resampler to support aux channel?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
575 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
576 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Eric Laurent65b65452010-06-01 23:49:17 -0700577 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
578 volumeRampStereo(t, out, outFrameCount, temp, aux);
579 } else {
580 volumeStereo(t, out, outFrameCount, temp, aux);
581 }
582 } else {
583 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
584 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
585 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
586 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
587 volumeRampStereo(t, out, outFrameCount, temp, aux);
588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589
Eric Laurent65b65452010-06-01 23:49:17 -0700590 // constant gain
591 else {
592 t->resampler->setVolume(t->volume[0], t->volume[1]);
593 t->resampler->resample(out, outFrameCount, t->bufferProvider);
594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 }
596}
597
Eric Laurent65b65452010-06-01 23:49:17 -0700598void 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 -0800599{
600}
601
Eric Laurent65b65452010-06-01 23:49:17 -0700602void 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 -0800603{
604 int32_t vl = t->prevVolume[0];
605 int32_t vr = t->prevVolume[1];
606 const int32_t vlInc = t->volumeInc[0];
607 const int32_t vrInc = t->volumeInc[1];
608
609 //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
610 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
611 // (vl + vlInc*frameCount)/65536.0f, frameCount);
Eric Laurent65b65452010-06-01 23:49:17 -0700612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 // ramp volume
Eric Laurent65b65452010-06-01 23:49:17 -0700614 if UNLIKELY(aux != NULL) {
615 int32_t va = t->prevAuxLevel;
616 const int32_t vaInc = t->auxInc;
617 int32_t l;
618 int32_t r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619
620 do {
Eric Laurent65b65452010-06-01 23:49:17 -0700621 l = (*temp++ >> 12);
622 r = (*temp++ >> 12);
623 *out++ += (vl >> 16) * l;
624 *out++ += (vr >> 16) * r;
625 *aux++ += (va >> 17) * (l + r);
626 vl += vlInc;
627 vr += vrInc;
628 va += vaInc;
629 } while (--frameCount);
630 t->prevAuxLevel = va;
631 } else {
632 do {
633 *out++ += (vl >> 16) * (*temp++ >> 12);
634 *out++ += (vr >> 16) * (*temp++ >> 12);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 vl += vlInc;
636 vr += vrInc;
637 } while (--frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 }
Eric Laurent65b65452010-06-01 23:49:17 -0700639 t->prevVolume[0] = vl;
640 t->prevVolume[1] = vr;
641 t->adjustVolumeRamp((aux != NULL));
642}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643
Eric Laurent65b65452010-06-01 23:49:17 -0700644void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
645{
646 const int16_t vl = t->volume[0];
647 const int16_t vr = t->volume[1];
648
649 if UNLIKELY(aux != NULL) {
650 const int16_t va = (int16_t)t->auxLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 do {
Eric Laurent65b65452010-06-01 23:49:17 -0700652 int16_t l = (int16_t)(*temp++ >> 12);
653 int16_t r = (int16_t)(*temp++ >> 12);
654 out[0] = mulAdd(l, vl, out[0]);
655 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
656 out[1] = mulAdd(r, vr, out[1]);
657 out += 2;
658 aux[0] = mulAdd(a, va, aux[0]);
659 aux++;
660 } while (--frameCount);
661 } else {
662 do {
663 int16_t l = (int16_t)(*temp++ >> 12);
664 int16_t r = (int16_t)(*temp++ >> 12);
665 out[0] = mulAdd(l, vl, out[0]);
666 out[1] = mulAdd(r, vr, out[1]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 out += 2;
668 } while (--frameCount);
669 }
Eric Laurent65b65452010-06-01 23:49:17 -0700670}
671
672void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
673{
674 int16_t const *in = static_cast<int16_t const *>(t->in);
675
676 if UNLIKELY(aux != NULL) {
677 int32_t l;
678 int32_t r;
679 // ramp gain
680 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
681 int32_t vl = t->prevVolume[0];
682 int32_t vr = t->prevVolume[1];
683 int32_t va = t->prevAuxLevel;
684 const int32_t vlInc = t->volumeInc[0];
685 const int32_t vrInc = t->volumeInc[1];
686 const int32_t vaInc = t->auxInc;
687 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
688 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
689 // (vl + vlInc*frameCount)/65536.0f, frameCount);
690
691 do {
692 l = (int32_t)*in++;
693 r = (int32_t)*in++;
694 *out++ += (vl >> 16) * l;
695 *out++ += (vr >> 16) * r;
696 *aux++ += (va >> 17) * (l + r);
697 vl += vlInc;
698 vr += vrInc;
699 va += vaInc;
700 } while (--frameCount);
701
702 t->prevVolume[0] = vl;
703 t->prevVolume[1] = vr;
704 t->prevAuxLevel = va;
705 t->adjustVolumeRamp(true);
706 }
707
708 // constant gain
709 else {
710 const uint32_t vrl = t->volumeRL;
711 const int16_t va = (int16_t)t->auxLevel;
712 do {
713 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
714 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
715 in += 2;
716 out[0] = mulAddRL(1, rl, vrl, out[0]);
717 out[1] = mulAddRL(0, rl, vrl, out[1]);
718 out += 2;
719 aux[0] = mulAdd(a, va, aux[0]);
720 aux++;
721 } while (--frameCount);
722 }
723 } else {
724 // ramp gain
725 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
726 int32_t vl = t->prevVolume[0];
727 int32_t vr = t->prevVolume[1];
728 const int32_t vlInc = t->volumeInc[0];
729 const int32_t vrInc = t->volumeInc[1];
730
731 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
732 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
733 // (vl + vlInc*frameCount)/65536.0f, frameCount);
734
735 do {
736 *out++ += (vl >> 16) * (int32_t) *in++;
737 *out++ += (vr >> 16) * (int32_t) *in++;
738 vl += vlInc;
739 vr += vrInc;
740 } while (--frameCount);
741
742 t->prevVolume[0] = vl;
743 t->prevVolume[1] = vr;
744 t->adjustVolumeRamp(false);
745 }
746
747 // constant gain
748 else {
749 const uint32_t vrl = t->volumeRL;
750 do {
751 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
752 in += 2;
753 out[0] = mulAddRL(1, rl, vrl, out[0]);
754 out[1] = mulAddRL(0, rl, vrl, out[1]);
755 out += 2;
756 } while (--frameCount);
757 }
758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 t->in = in;
760}
761
Eric Laurent65b65452010-06-01 23:49:17 -0700762void 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 -0800763{
764 int16_t const *in = static_cast<int16_t const *>(t->in);
765
Eric Laurent65b65452010-06-01 23:49:17 -0700766 if UNLIKELY(aux != NULL) {
767 // ramp gain
768 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
769 int32_t vl = t->prevVolume[0];
770 int32_t vr = t->prevVolume[1];
771 int32_t va = t->prevAuxLevel;
772 const int32_t vlInc = t->volumeInc[0];
773 const int32_t vrInc = t->volumeInc[1];
774 const int32_t vaInc = t->auxInc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775
Eric Laurent65b65452010-06-01 23:49:17 -0700776 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
777 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
778 // (vl + vlInc*frameCount)/65536.0f, frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779
Eric Laurent65b65452010-06-01 23:49:17 -0700780 do {
781 int32_t l = *in++;
782 *out++ += (vl >> 16) * l;
783 *out++ += (vr >> 16) * l;
784 *aux++ += (va >> 16) * l;
785 vl += vlInc;
786 vr += vrInc;
787 va += vaInc;
788 } while (--frameCount);
789
790 t->prevVolume[0] = vl;
791 t->prevVolume[1] = vr;
792 t->prevAuxLevel = va;
793 t->adjustVolumeRamp(true);
794 }
795 // constant gain
796 else {
797 const int16_t vl = t->volume[0];
798 const int16_t vr = t->volume[1];
799 const int16_t va = (int16_t)t->auxLevel;
800 do {
801 int16_t l = *in++;
802 out[0] = mulAdd(l, vl, out[0]);
803 out[1] = mulAdd(l, vr, out[1]);
804 out += 2;
805 aux[0] = mulAdd(l, va, aux[0]);
806 aux++;
807 } while (--frameCount);
808 }
809 } else {
810 // ramp gain
811 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
812 int32_t vl = t->prevVolume[0];
813 int32_t vr = t->prevVolume[1];
814 const int32_t vlInc = t->volumeInc[0];
815 const int32_t vrInc = t->volumeInc[1];
816
817 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
818 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
819 // (vl + vlInc*frameCount)/65536.0f, frameCount);
820
821 do {
822 int32_t l = *in++;
823 *out++ += (vl >> 16) * l;
824 *out++ += (vr >> 16) * l;
825 vl += vlInc;
826 vr += vrInc;
827 } while (--frameCount);
828
829 t->prevVolume[0] = vl;
830 t->prevVolume[1] = vr;
831 t->adjustVolumeRamp(false);
832 }
833 // constant gain
834 else {
835 const int16_t vl = t->volume[0];
836 const int16_t vr = t->volume[1];
837 do {
838 int16_t l = *in++;
839 out[0] = mulAdd(l, vl, out[0]);
840 out[1] = mulAdd(l, vr, out[1]);
841 out += 2;
842 } while (--frameCount);
843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 }
845 t->in = in;
846}
847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
849{
850 for (size_t i=0 ; i<c ; i++) {
851 int32_t l = *sums++;
852 int32_t r = *sums++;
853 int32_t nl = l >> 12;
854 int32_t nr = r >> 12;
855 l = clamp16(nl);
856 r = clamp16(nr);
857 *out++ = (r<<16) | (l & 0xFFFF);
858 }
859}
860
861// no-op case
Eric Laurent65b65452010-06-01 23:49:17 -0700862void AudioMixer::process__nop(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863{
Eric Laurent65b65452010-06-01 23:49:17 -0700864 uint32_t e0 = state->enabledTracks;
865 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
866 while (e0) {
867 // process by group of tracks with same output buffer to
868 // avoid multiple memset() on same buffer
869 uint32_t e1 = e0, e2 = e0;
870 int i = 31 - __builtin_clz(e1);
871 track_t& t1 = state->tracks[i];
872 e2 &= ~(1<<i);
873 while (e2) {
874 i = 31 - __builtin_clz(e2);
875 e2 &= ~(1<<i);
876 track_t& t2 = state->tracks[i];
877 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
878 e1 &= ~(1<<i);
879 }
880 }
881 e0 &= ~(e1);
882
883 memset(t1.mainBuffer, 0, bufSize);
884
885 while (e1) {
886 i = 31 - __builtin_clz(e1);
887 e1 &= ~(1<<i);
888 t1 = state->tracks[i];
889 size_t outFrames = state->frameCount;
890 while (outFrames) {
891 t1.buffer.frameCount = outFrames;
892 t1.bufferProvider->getNextBuffer(&t1.buffer);
893 if (!t1.buffer.raw) break;
894 outFrames -= t1.buffer.frameCount;
895 t1.bufferProvider->releaseBuffer(&t1.buffer);
896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 }
898 }
899}
900
901// generic code without resampling
Eric Laurent65b65452010-06-01 23:49:17 -0700902void AudioMixer::process__genericNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903{
904 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
905
906 // acquire each track's buffer
907 uint32_t enabledTracks = state->enabledTracks;
Eric Laurent65b65452010-06-01 23:49:17 -0700908 uint32_t e0 = enabledTracks;
909 while (e0) {
910 const int i = 31 - __builtin_clz(e0);
911 e0 &= ~(1<<i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 track_t& t = state->tracks[i];
913 t.buffer.frameCount = state->frameCount;
914 t.bufferProvider->getNextBuffer(&t.buffer);
915 t.frameCount = t.buffer.frameCount;
916 t.in = t.buffer.raw;
917 // t.in == NULL can happen if the track was flushed just after having
918 // been enabled for mixing.
919 if (t.in == NULL)
920 enabledTracks &= ~(1<<i);
921 }
922
Eric Laurent65b65452010-06-01 23:49:17 -0700923 e0 = enabledTracks;
924 while (e0) {
925 // process by group of tracks with same output buffer to
926 // optimize cache use
927 uint32_t e1 = e0, e2 = e0;
928 int j = 31 - __builtin_clz(e1);
929 track_t& t1 = state->tracks[j];
930 e2 &= ~(1<<j);
931 while (e2) {
932 j = 31 - __builtin_clz(e2);
933 e2 &= ~(1<<j);
934 track_t& t2 = state->tracks[j];
935 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
936 e1 &= ~(1<<j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 }
938 }
Eric Laurent65b65452010-06-01 23:49:17 -0700939 e0 &= ~(e1);
940 // this assumes output 16 bits stereo, no resampling
941 int32_t *out = t1.mainBuffer;
942 size_t numFrames = 0;
943 do {
944 memset(outTemp, 0, sizeof(outTemp));
945 e2 = e1;
946 while (e2) {
947 const int i = 31 - __builtin_clz(e2);
948 e2 &= ~(1<<i);
949 track_t& t = state->tracks[i];
950 size_t outFrames = BLOCKSIZE;
951 int32_t *aux = NULL;
952 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
953 aux = t.auxBuffer + numFrames;
954 }
955 while (outFrames) {
956 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
957 if (inFrames) {
958 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
959 t.frameCount -= inFrames;
960 outFrames -= inFrames;
961 if UNLIKELY(aux != NULL) {
962 aux += inFrames;
963 }
964 }
965 if (t.frameCount == 0 && outFrames) {
966 t.bufferProvider->releaseBuffer(&t.buffer);
967 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
968 t.bufferProvider->getNextBuffer(&t.buffer);
969 t.in = t.buffer.raw;
970 if (t.in == NULL) {
971 enabledTracks &= ~(1<<i);
972 e1 &= ~(1<<i);
973 break;
974 }
975 t.frameCount = t.buffer.frameCount;
976 }
977 }
978 }
979 ditherAndClamp(out, outTemp, BLOCKSIZE);
980 out += BLOCKSIZE;
981 numFrames += BLOCKSIZE;
982 } while (numFrames < state->frameCount);
983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984
985 // release each track's buffer
Eric Laurent65b65452010-06-01 23:49:17 -0700986 e0 = enabledTracks;
987 while (e0) {
988 const int i = 31 - __builtin_clz(e0);
989 e0 &= ~(1<<i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 track_t& t = state->tracks[i];
991 t.bufferProvider->releaseBuffer(&t.buffer);
992 }
993}
994
Eric Laurent65b65452010-06-01 23:49:17 -0700995
996 // generic code with resampling
997void AudioMixer::process__genericResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998{
999 int32_t* const outTemp = state->outputTemp;
1000 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 size_t numFrames = state->frameCount;
1003
Eric Laurent65b65452010-06-01 23:49:17 -07001004 uint32_t e0 = state->enabledTracks;
1005 while (e0) {
1006 // process by group of tracks with same output buffer
1007 // to optimize cache use
1008 uint32_t e1 = e0, e2 = e0;
1009 int j = 31 - __builtin_clz(e1);
1010 track_t& t1 = state->tracks[j];
1011 e2 &= ~(1<<j);
1012 while (e2) {
1013 j = 31 - __builtin_clz(e2);
1014 e2 &= ~(1<<j);
1015 track_t& t2 = state->tracks[j];
1016 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
1017 e1 &= ~(1<<j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 }
1019 }
Eric Laurent65b65452010-06-01 23:49:17 -07001020 e0 &= ~(e1);
1021 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi681d8182011-02-04 15:24:34 +01001022 memset(outTemp, 0, size);
Eric Laurent65b65452010-06-01 23:49:17 -07001023 while (e1) {
1024 const int i = 31 - __builtin_clz(e1);
1025 e1 &= ~(1<<i);
1026 track_t& t = state->tracks[i];
1027 int32_t *aux = NULL;
1028 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
1029 aux = t.auxBuffer;
1030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031
Eric Laurent65b65452010-06-01 23:49:17 -07001032 // this is a little goofy, on the resampling case we don't
1033 // acquire/release the buffers because it's done by
1034 // the resampler.
1035 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
1036 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
1037 } else {
1038
1039 size_t outFrames = 0;
1040
1041 while (outFrames < numFrames) {
1042 t.buffer.frameCount = numFrames - outFrames;
1043 t.bufferProvider->getNextBuffer(&t.buffer);
1044 t.in = t.buffer.raw;
1045 // t.in == NULL can happen if the track was flushed just after having
1046 // been enabled for mixing.
1047 if (t.in == NULL) break;
1048
1049 if UNLIKELY(aux != NULL) {
1050 aux += outFrames;
1051 }
1052 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
1053 outFrames += t.buffer.frameCount;
1054 t.bufferProvider->releaseBuffer(&t.buffer);
1055 }
1056 }
1057 }
1058 ditherAndClamp(out, outTemp, numFrames);
1059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060}
1061
1062// one track, 16 bits stereo without resampling is the most common case
Eric Laurent65b65452010-06-01 23:49:17 -07001063void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064{
1065 const int i = 31 - __builtin_clz(state->enabledTracks);
1066 const track_t& t = state->tracks[i];
1067
1068 AudioBufferProvider::Buffer& b(t.buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001069
1070 int32_t* out = t.mainBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 size_t numFrames = state->frameCount;
Eric Laurent65b65452010-06-01 23:49:17 -07001072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073 const int16_t vl = t.volume[0];
1074 const int16_t vr = t.volume[1];
1075 const uint32_t vrl = t.volumeRL;
1076 while (numFrames) {
1077 b.frameCount = numFrames;
1078 t.bufferProvider->getNextBuffer(&b);
1079 int16_t const *in = b.i16;
1080
1081 // in == NULL can happen if the track was flushed just after having
1082 // been enabled for mixing.
The Android Open Source Project10592532009-03-18 17:39:46 -07001083 if (in == NULL || ((unsigned long)in & 3)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
The Android Open Source Project10592532009-03-18 17:39:46 -07001085 LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
1086 in, i, t.channelCount, t.needs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 return;
1088 }
1089 size_t outFrames = b.frameCount;
Eric Laurent65b65452010-06-01 23:49:17 -07001090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
1092 // volume is boosted, so we might need to clamp even though
1093 // we process only one track.
1094 do {
1095 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1096 in += 2;
1097 int32_t l = mulRL(1, rl, vrl) >> 12;
1098 int32_t r = mulRL(0, rl, vrl) >> 12;
1099 // clamping...
1100 l = clamp16(l);
1101 r = clamp16(r);
1102 *out++ = (r<<16) | (l & 0xFFFF);
1103 } while (--outFrames);
1104 } else {
1105 do {
1106 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1107 in += 2;
1108 int32_t l = mulRL(1, rl, vrl) >> 12;
1109 int32_t r = mulRL(0, rl, vrl) >> 12;
1110 *out++ = (r<<16) | (l & 0xFFFF);
1111 } while (--outFrames);
1112 }
1113 numFrames -= b.frameCount;
1114 t.bufferProvider->releaseBuffer(&b);
1115 }
1116}
1117
1118// 2 tracks is also a common case
Eric Laurent65b65452010-06-01 23:49:17 -07001119// NEVER used in current implementation of process__validate()
1120// only use if the 2 tracks have the same output buffer
1121void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122{
1123 int i;
1124 uint32_t en = state->enabledTracks;
1125
1126 i = 31 - __builtin_clz(en);
1127 const track_t& t0 = state->tracks[i];
1128 AudioBufferProvider::Buffer& b0(t0.buffer);
1129
1130 en &= ~(1<<i);
1131 i = 31 - __builtin_clz(en);
1132 const track_t& t1 = state->tracks[i];
1133 AudioBufferProvider::Buffer& b1(t1.buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 int16_t const *in0;
1136 const int16_t vl0 = t0.volume[0];
1137 const int16_t vr0 = t0.volume[1];
1138 size_t frameCount0 = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 int16_t const *in1;
1141 const int16_t vl1 = t1.volume[0];
1142 const int16_t vr1 = t1.volume[1];
1143 size_t frameCount1 = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001144
1145 //FIXME: only works if two tracks use same buffer
1146 int32_t* out = t0.mainBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 size_t numFrames = state->frameCount;
1148 int16_t const *buff = NULL;
1149
Eric Laurent65b65452010-06-01 23:49:17 -07001150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 while (numFrames) {
Eric Laurent65b65452010-06-01 23:49:17 -07001152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 if (frameCount0 == 0) {
1154 b0.frameCount = numFrames;
1155 t0.bufferProvider->getNextBuffer(&b0);
1156 if (b0.i16 == NULL) {
1157 if (buff == NULL) {
1158 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1159 }
1160 in0 = buff;
1161 b0.frameCount = numFrames;
1162 } else {
1163 in0 = b0.i16;
1164 }
1165 frameCount0 = b0.frameCount;
1166 }
1167 if (frameCount1 == 0) {
1168 b1.frameCount = numFrames;
1169 t1.bufferProvider->getNextBuffer(&b1);
1170 if (b1.i16 == NULL) {
1171 if (buff == NULL) {
1172 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1173 }
1174 in1 = buff;
1175 b1.frameCount = numFrames;
1176 } else {
1177 in1 = b1.i16;
1178 }
1179 frameCount1 = b1.frameCount;
1180 }
Eric Laurent65b65452010-06-01 23:49:17 -07001181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1183
1184 numFrames -= outFrames;
1185 frameCount0 -= outFrames;
1186 frameCount1 -= outFrames;
Eric Laurent65b65452010-06-01 23:49:17 -07001187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 do {
1189 int32_t l0 = *in0++;
1190 int32_t r0 = *in0++;
1191 l0 = mul(l0, vl0);
1192 r0 = mul(r0, vr0);
1193 int32_t l = *in1++;
1194 int32_t r = *in1++;
1195 l = mulAdd(l, vl1, l0) >> 12;
1196 r = mulAdd(r, vr1, r0) >> 12;
1197 // clamping...
1198 l = clamp16(l);
1199 r = clamp16(r);
1200 *out++ = (r<<16) | (l & 0xFFFF);
1201 } while (--outFrames);
Eric Laurent65b65452010-06-01 23:49:17 -07001202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 if (frameCount0 == 0) {
1204 t0.bufferProvider->releaseBuffer(&b0);
1205 }
1206 if (frameCount1 == 0) {
1207 t1.bufferProvider->releaseBuffer(&b1);
1208 }
Eric Laurent65b65452010-06-01 23:49:17 -07001209 }
1210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 if (buff != NULL) {
Eric Laurent65b65452010-06-01 23:49:17 -07001212 delete [] buff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 }
1214}
1215
1216// ----------------------------------------------------------------------------
1217}; // namespace android
1218