blob: b03467f6ced23d033d67d3cd25aedcec083886a0 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/* //device/include/server/AudioFlinger/AudioMixer.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08005** 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
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07008**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070010**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080011** 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
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070015** limitations under the License.
16*/
17
18#define LOG_TAG "AudioMixer"
19
20#include <stdint.h>
21#include <string.h>
22#include <stdlib.h>
23#include <sys/types.h>
24
25#include <utils/Errors.h>
26#include <utils/Log.h>
27
28#include "AudioMixer.h"
29
30namespace android {
31// ----------------------------------------------------------------------------
32
33static inline int16_t clamp16(int32_t sample)
34{
35 if ((sample>>15) ^ (sample>>31))
36 sample = 0x7FFF ^ (sample>>31);
37 return sample;
38}
39
40// ----------------------------------------------------------------------------
41
42AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
43 : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
44{
45 mState.enabledTracks= 0;
46 mState.needsChanged = 0;
47 mState.frameCount = frameCount;
48 mState.outputTemp = 0;
49 mState.resampleTemp = 0;
50 mState.hook = process__nop;
51 track_t* t = mState.tracks;
52 for (int i=0 ; i<32 ; i++) {
53 t->needs = 0;
54 t->volume[0] = UNITY_GAIN;
55 t->volume[1] = UNITY_GAIN;
56 t->volumeInc[0] = 0;
57 t->volumeInc[1] = 0;
58 t->channelCount = 2;
59 t->enabled = 0;
60 t->format = 16;
61 t->buffer.raw = 0;
62 t->bufferProvider = 0;
63 t->hook = 0;
64 t->resampler = 0;
65 t->sampleRate = mSampleRate;
66 t->in = 0;
67 t++;
68 }
69}
70
71 AudioMixer::~AudioMixer()
72 {
73 track_t* t = mState.tracks;
74 for (int i=0 ; i<32 ; i++) {
75 delete t->resampler;
76 t++;
77 }
78 delete [] mState.outputTemp;
79 delete [] mState.resampleTemp;
80 }
81
82 int AudioMixer::getTrackName()
83 {
84 uint32_t names = mTrackNames;
85 uint32_t mask = 1;
86 int n = 0;
87 while (names & mask) {
88 mask <<= 1;
89 n++;
90 }
91 if (mask) {
92 LOGV("add track (%d)", n);
93 mTrackNames |= mask;
94 return TRACK0 + n;
95 }
96 return -1;
97 }
98
99 void AudioMixer::invalidateState(uint32_t mask)
100 {
101 if (mask) {
102 mState.needsChanged |= mask;
103 mState.hook = process__validate;
104 }
105 }
106
107 void AudioMixer::deleteTrackName(int name)
108 {
109 name -= TRACK0;
110 if (uint32_t(name) < MAX_NUM_TRACKS) {
111 LOGV("deleteTrackName(%d)", name);
112 track_t& track(mState.tracks[ name ]);
113 if (track.enabled != 0) {
114 track.enabled = 0;
115 invalidateState(1<<name);
116 }
117 if (track.resampler) {
118 // delete the resampler
119 delete track.resampler;
120 track.resampler = 0;
121 track.sampleRate = mSampleRate;
122 invalidateState(1<<name);
123 }
124 track.volumeInc[0] = 0;
125 track.volumeInc[1] = 0;
126 mTrackNames &= ~(1<<name);
127 }
128 }
129
130status_t AudioMixer::enable(int name)
131{
132 switch (name) {
133 case MIXING: {
134 if (mState.tracks[ mActiveTrack ].enabled != 1) {
135 mState.tracks[ mActiveTrack ].enabled = 1;
136 LOGV("enable(%d)", mActiveTrack);
137 invalidateState(1<<mActiveTrack);
138 }
139 } break;
140 default:
141 return NAME_NOT_FOUND;
142 }
143 return NO_ERROR;
144}
145
146status_t AudioMixer::disable(int name)
147{
148 switch (name) {
149 case MIXING: {
150 if (mState.tracks[ mActiveTrack ].enabled != 0) {
151 mState.tracks[ mActiveTrack ].enabled = 0;
152 LOGV("disable(%d)", mActiveTrack);
153 invalidateState(1<<mActiveTrack);
154 }
155 } break;
156 default:
157 return NAME_NOT_FOUND;
158 }
159 return NO_ERROR;
160}
161
162status_t AudioMixer::setActiveTrack(int track)
163{
164 if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) {
165 return BAD_VALUE;
166 }
167 mActiveTrack = track - TRACK0;
168 return NO_ERROR;
169}
170
171status_t AudioMixer::setParameter(int target, int name, int value)
172{
173 switch (target) {
174 case TRACK:
175 if (name == CHANNEL_COUNT) {
176 if ((uint32_t(value) <= MAX_NUM_CHANNELS) && (value)) {
177 if (mState.tracks[ mActiveTrack ].channelCount != value) {
178 mState.tracks[ mActiveTrack ].channelCount = value;
179 LOGV("setParameter(TRACK, CHANNEL_COUNT, %d)", value);
180 invalidateState(1<<mActiveTrack);
181 }
182 return NO_ERROR;
183 }
184 }
185 break;
186 case RESAMPLE:
187 if (name == SAMPLE_RATE) {
188 if (value > 0) {
189 track_t& track = mState.tracks[ mActiveTrack ];
190 if (track.setResampler(uint32_t(value), mSampleRate)) {
191 LOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
192 uint32_t(value));
193 invalidateState(1<<mActiveTrack);
194 }
195 return NO_ERROR;
196 }
197 }
198 break;
199 case RAMP_VOLUME:
200 case VOLUME:
201 if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) {
202 track_t& track = mState.tracks[ mActiveTrack ];
203 if (track.volume[name-VOLUME0] != value) {
204 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
205 track.volume[name-VOLUME0] = value;
206 if (target == VOLUME) {
207 track.prevVolume[name-VOLUME0] = value << 16;
208 track.volumeInc[name-VOLUME0] = 0;
209 } else {
210 int32_t d = (value<<16) - track.prevVolume[name-VOLUME0];
211 int32_t volInc = d / int32_t(mState.frameCount);
212 track.volumeInc[name-VOLUME0] = volInc;
213 if (volInc == 0) {
214 track.prevVolume[name-VOLUME0] = value << 16;
215 }
216 }
217 invalidateState(1<<mActiveTrack);
218 }
219 return NO_ERROR;
220 }
221 break;
222 }
223 return BAD_VALUE;
224}
225
226bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
227{
228 if (value!=devSampleRate || resampler) {
229 if (sampleRate != value) {
230 sampleRate = value;
231 if (resampler == 0) {
232 resampler = AudioResampler::create(
233 format, channelCount, devSampleRate);
234 }
235 return true;
236 }
237 }
238 return false;
239}
240
241bool AudioMixer::track_t::doesResample() const
242{
243 return resampler != 0;
244}
245
246inline
247void AudioMixer::track_t::adjustVolumeRamp()
248{
249 for (int i=0 ; i<2 ; i++) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800250 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
251 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700252 volumeInc[i] = 0;
253 prevVolume[i] = volume[i]<<16;
254 }
255 }
256}
257
258
259status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
260{
261 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
262 return NO_ERROR;
263}
264
265
266
267void AudioMixer::process(void* output)
268{
269 mState.hook(&mState, output);
270}
271
272
273void AudioMixer::process__validate(state_t* state, void* output)
274{
275 LOGW_IF(!state->needsChanged,
276 "in process__validate() but nothing's invalid");
277
278 uint32_t changed = state->needsChanged;
279 state->needsChanged = 0; // clear the validation flag
280
281 // recompute which tracks are enabled / disabled
282 uint32_t enabled = 0;
283 uint32_t disabled = 0;
284 while (changed) {
285 const int i = 31 - __builtin_clz(changed);
286 const uint32_t mask = 1<<i;
287 changed &= ~mask;
288 track_t& t = state->tracks[i];
289 (t.enabled ? enabled : disabled) |= mask;
290 }
291 state->enabledTracks &= ~disabled;
292 state->enabledTracks |= enabled;
293
294 // compute everything we need...
295 int countActiveTracks = 0;
296 int all16BitsStereoNoResample = 1;
297 int resampling = 0;
298 int volumeRamp = 0;
299 uint32_t en = state->enabledTracks;
300 while (en) {
301 const int i = 31 - __builtin_clz(en);
302 en &= ~(1<<i);
303
304 countActiveTracks++;
305 track_t& t = state->tracks[i];
306 uint32_t n = 0;
307 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
308 n |= NEEDS_FORMAT_16;
309 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800310
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700311 if (t.volumeInc[0]|t.volumeInc[1]) {
312 volumeRamp = 1;
313 } else if (!t.doesResample() && t.volumeRL == 0) {
314 n |= NEEDS_MUTE_ENABLED;
315 }
316 t.needs = n;
317
318 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
319 t.hook = track__nop;
320 } else {
321 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
322 all16BitsStereoNoResample = 0;
323 resampling = 1;
324 t.hook = track__genericResample;
325 } else {
326 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
327 t.hook = track__16BitsMono;
328 all16BitsStereoNoResample = 0;
329 }
330 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
331 t.hook = track__16BitsStereo;
332 }
333 }
334 }
335 }
336
337 // select the processing hooks
338 state->hook = process__nop;
339 if (countActiveTracks) {
340 if (resampling) {
341 if (!state->outputTemp) {
342 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
343 }
344 if (!state->resampleTemp) {
345 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
346 }
347 state->hook = process__genericResampling;
348 } else {
349 if (state->outputTemp) {
350 delete [] state->outputTemp;
351 state->outputTemp = 0;
352 }
353 if (state->resampleTemp) {
354 delete [] state->resampleTemp;
355 state->resampleTemp = 0;
356 }
357 state->hook = process__genericNoResampling;
358 if (all16BitsStereoNoResample && !volumeRamp) {
359 if (countActiveTracks == 1) {
360 state->hook = process__OneTrack16BitsStereoNoResampling;
361 }
362 }
363 }
364 }
365
366 LOGV("mixer configuration change: %d activeTracks (%08x) "
367 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
368 countActiveTracks, state->enabledTracks,
369 all16BitsStereoNoResample, resampling, volumeRamp);
370
371 state->hook(state, output);
372
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800373 // Now that the volume ramp has been done, set optimal state and
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700374 // track hooks for subsequent mixer process
375 if (countActiveTracks) {
376 int allMuted = 1;
377 uint32_t en = state->enabledTracks;
378 while (en) {
379 const int i = 31 - __builtin_clz(en);
380 en &= ~(1<<i);
381 track_t& t = state->tracks[i];
382 if (!t.doesResample() && t.volumeRL == 0)
383 {
384 t.needs |= NEEDS_MUTE_ENABLED;
385 t.hook = track__nop;
386 } else {
387 allMuted = 0;
388 }
389 }
390 if (allMuted) {
391 state->hook = process__nop;
392 } else if (!resampling && all16BitsStereoNoResample) {
393 if (countActiveTracks == 1) {
394 state->hook = process__OneTrack16BitsStereoNoResampling;
395 }
396 }
397 }
398}
399
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800400static inline
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700401int32_t mulAdd(int16_t in, int16_t v, int32_t a)
402{
403#if defined(__arm__) && !defined(__thumb__)
404 int32_t out;
405 asm( "smlabb %[out], %[in], %[v], %[a] \n"
406 : [out]"=r"(out)
407 : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
408 : );
409 return out;
410#else
411 return a + in * int32_t(v);
412#endif
413}
414
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800415static inline
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700416int32_t mul(int16_t in, int16_t v)
417{
418#if defined(__arm__) && !defined(__thumb__)
419 int32_t out;
420 asm( "smulbb %[out], %[in], %[v] \n"
421 : [out]"=r"(out)
422 : [in]"%r"(in), [v]"r"(v)
423 : );
424 return out;
425#else
426 return in * int32_t(v);
427#endif
428}
429
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800430static inline
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700431int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
432{
433#if defined(__arm__) && !defined(__thumb__)
434 int32_t out;
435 if (left) {
436 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
437 : [out]"=r"(out)
438 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
439 : );
440 } else {
441 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
442 : [out]"=r"(out)
443 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
444 : );
445 }
446 return out;
447#else
448 if (left) {
449 return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
450 } else {
451 return a + int16_t(inRL>>16) * int16_t(vRL>>16);
452 }
453#endif
454}
455
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800456static inline
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700457int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
458{
459#if defined(__arm__) && !defined(__thumb__)
460 int32_t out;
461 if (left) {
462 asm( "smulbb %[out], %[inRL], %[vRL] \n"
463 : [out]"=r"(out)
464 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
465 : );
466 } else {
467 asm( "smultt %[out], %[inRL], %[vRL] \n"
468 : [out]"=r"(out)
469 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
470 : );
471 }
472 return out;
473#else
474 if (left) {
475 return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
476 } else {
477 return int16_t(inRL>>16) * int16_t(vRL>>16);
478 }
479#endif
480}
481
482
483void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp)
484{
485 t->resampler->setSampleRate(t->sampleRate);
486
487 // ramp gain - resample to temp buffer and scale/mix in 2nd step
488 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
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 volumeRampStereo(t, out, outFrameCount, temp);
493 }
494
495 // constant gain
496 else {
497 t->resampler->setVolume(t->volume[0], t->volume[1]);
498 t->resampler->resample(out, outFrameCount, t->bufferProvider);
499 }
500}
501
502void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp)
503{
504}
505
506void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp)
507{
508 int32_t vl = t->prevVolume[0];
509 int32_t vr = t->prevVolume[1];
510 const int32_t vlInc = t->volumeInc[0];
511 const int32_t vrInc = t->volumeInc[1];
512
513 //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
514 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
515 // (vl + vlInc*frameCount)/65536.0f, frameCount);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800516
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700517 // ramp volume
518 do {
519 *out++ += (vl >> 16) * (*temp++ >> 12);
520 *out++ += (vr >> 16) * (*temp++ >> 12);
521 vl += vlInc;
522 vr += vrInc;
523 } while (--frameCount);
524
525 t->prevVolume[0] = vl;
526 t->prevVolume[1] = vr;
527 t->adjustVolumeRamp();
528}
529
530void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp)
531{
532 int16_t const *in = static_cast<int16_t const *>(t->in);
533
534 // ramp gain
535 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
536 int32_t vl = t->prevVolume[0];
537 int32_t vr = t->prevVolume[1];
538 const int32_t vlInc = t->volumeInc[0];
539 const int32_t vrInc = t->volumeInc[1];
540
541 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
542 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
543 // (vl + vlInc*frameCount)/65536.0f, frameCount);
544
545 do {
546 *out++ += (vl >> 16) * (int32_t) *in++;
547 *out++ += (vr >> 16) * (int32_t) *in++;
548 vl += vlInc;
549 vr += vrInc;
550 } while (--frameCount);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800551
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700552 t->prevVolume[0] = vl;
553 t->prevVolume[1] = vr;
554 t->adjustVolumeRamp();
555 }
556
557 // constant gain
558 else {
559 const uint32_t vrl = t->volumeRL;
560 do {
561 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
562 in += 2;
563 out[0] = mulAddRL(1, rl, vrl, out[0]);
564 out[1] = mulAddRL(0, rl, vrl, out[1]);
565 out += 2;
566 } while (--frameCount);
567 }
568 t->in = in;
569}
570
571void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp)
572{
573 int16_t const *in = static_cast<int16_t const *>(t->in);
574
575 // ramp gain
576 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
577 int32_t vl = t->prevVolume[0];
578 int32_t vr = t->prevVolume[1];
579 const int32_t vlInc = t->volumeInc[0];
580 const int32_t vrInc = t->volumeInc[1];
581
582 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
583 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
584 // (vl + vlInc*frameCount)/65536.0f, frameCount);
585
586 do {
587 int32_t l = *in++;
588 *out++ += (vl >> 16) * l;
589 *out++ += (vr >> 16) * l;
590 vl += vlInc;
591 vr += vrInc;
592 } while (--frameCount);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800593
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700594 t->prevVolume[0] = vl;
595 t->prevVolume[1] = vr;
596 t->adjustVolumeRamp();
597 }
598 // constant gain
599 else {
600 const int16_t vl = t->volume[0];
601 const int16_t vr = t->volume[1];
602 do {
603 int16_t l = *in++;
604 out[0] = mulAdd(l, vl, out[0]);
605 out[1] = mulAdd(l, vr, out[1]);
606 out += 2;
607 } while (--frameCount);
608 }
609 t->in = in;
610}
611
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800612inline
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700613void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
614{
615 for (size_t i=0 ; i<c ; i++) {
616 int32_t l = *sums++;
617 int32_t r = *sums++;
618 int32_t nl = l >> 12;
619 int32_t nr = r >> 12;
620 l = clamp16(nl);
621 r = clamp16(nr);
622 *out++ = (r<<16) | (l & 0xFFFF);
623 }
624}
625
626// no-op case
627void AudioMixer::process__nop(state_t* state, void* output)
628{
629 // this assumes output 16 bits stereo, no resampling
630 memset(output, 0, state->frameCount*4);
631 uint32_t en = state->enabledTracks;
632 while (en) {
633 const int i = 31 - __builtin_clz(en);
634 en &= ~(1<<i);
635 track_t& t = state->tracks[i];
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800636 size_t outFrames = state->frameCount;
637 while (outFrames) {
638 t.buffer.frameCount = outFrames;
639 t.bufferProvider->getNextBuffer(&t.buffer);
640 if (!t.buffer.raw) break;
641 outFrames -= t.buffer.frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700642 t.bufferProvider->releaseBuffer(&t.buffer);
643 }
644 }
645}
646
647// generic code without resampling
648void AudioMixer::process__genericNoResampling(state_t* state, void* output)
649{
650 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
651
652 // acquire each track's buffer
653 uint32_t enabledTracks = state->enabledTracks;
654 uint32_t en = enabledTracks;
655 while (en) {
656 const int i = 31 - __builtin_clz(en);
657 en &= ~(1<<i);
658 track_t& t = state->tracks[i];
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800659 t.buffer.frameCount = state->frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700660 t.bufferProvider->getNextBuffer(&t.buffer);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800661 t.frameCount = t.buffer.frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700662 t.in = t.buffer.raw;
663 // t.in == NULL can happen if the track was flushed just after having
664 // been enabled for mixing.
665 if (t.in == NULL)
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800666 enabledTracks &= ~(1<<i);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700667 }
668
669 // this assumes output 16 bits stereo, no resampling
670 int32_t* out = static_cast<int32_t*>(output);
671 size_t numFrames = state->frameCount;
672 do {
673 memset(outTemp, 0, sizeof(outTemp));
674
675 en = enabledTracks;
676 while (en) {
677 const int i = 31 - __builtin_clz(en);
678 en &= ~(1<<i);
679 track_t& t = state->tracks[i];
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800680 size_t outFrames = BLOCKSIZE;
681
682 while (outFrames) {
683 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
684 if (inFrames) {
685 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp);
686 t.frameCount -= inFrames;
687 outFrames -= inFrames;
688 }
689 if (t.frameCount == 0 && outFrames) {
690 t.bufferProvider->releaseBuffer(&t.buffer);
691 t.buffer.frameCount = numFrames - (BLOCKSIZE - outFrames);
692 t.bufferProvider->getNextBuffer(&t.buffer);
693 t.in = t.buffer.raw;
694 if (t.in == NULL) {
695 enabledTracks &= ~(1<<i);
696 break;
697 }
698 t.frameCount = t.buffer.frameCount;
699 }
700 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700701 }
702
703 ditherAndClamp(out, outTemp, BLOCKSIZE);
704 out += BLOCKSIZE;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700705 numFrames -= BLOCKSIZE;
706 } while (numFrames);
707
708
709 // release each track's buffer
710 en = enabledTracks;
711 while (en) {
712 const int i = 31 - __builtin_clz(en);
713 en &= ~(1<<i);
714 track_t& t = state->tracks[i];
715 t.bufferProvider->releaseBuffer(&t.buffer);
716 }
717}
718
719// generic code with resampling
720void AudioMixer::process__genericResampling(state_t* state, void* output)
721{
722 int32_t* const outTemp = state->outputTemp;
723 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
724 memset(outTemp, 0, size);
725
726 int32_t* out = static_cast<int32_t*>(output);
727 size_t numFrames = state->frameCount;
728
729 uint32_t en = state->enabledTracks;
730 while (en) {
731 const int i = 31 - __builtin_clz(en);
732 en &= ~(1<<i);
733 track_t& t = state->tracks[i];
734
735 // this is a little goofy, on the resampling case we don't
736 // acquire/release the buffers because it's done by
737 // the resampler.
738 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
739 (t.hook)(&t, outTemp, numFrames, state->resampleTemp);
740 } else {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800741
742 size_t outFrames = numFrames;
743
744 while (outFrames) {
745 t.buffer.frameCount = outFrames;
746 t.bufferProvider->getNextBuffer(&t.buffer);
747 t.in = t.buffer.raw;
748 // t.in == NULL can happen if the track was flushed just after having
749 // been enabled for mixing.
750 if (t.in == NULL) break;
751
752 (t.hook)(&t, outTemp + (numFrames-outFrames)*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp);
753 outFrames -= t.buffer.frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700754 t.bufferProvider->releaseBuffer(&t.buffer);
755 }
756 }
757 }
758
759 ditherAndClamp(out, outTemp, numFrames);
760}
761
762// one track, 16 bits stereo without resampling is the most common case
763void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, void* output)
764{
765 const int i = 31 - __builtin_clz(state->enabledTracks);
766 const track_t& t = state->tracks[i];
767
768 AudioBufferProvider::Buffer& b(t.buffer);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800769
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700770 int32_t* out = static_cast<int32_t*>(output);
771 size_t numFrames = state->frameCount;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800772
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700773 const int16_t vl = t.volume[0];
774 const int16_t vr = t.volume[1];
775 const uint32_t vrl = t.volumeRL;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800776 while (numFrames) {
777 b.frameCount = numFrames;
778 t.bufferProvider->getNextBuffer(&b);
779 int16_t const *in = b.i16;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700780
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800781 // in == NULL can happen if the track was flushed just after having
782 // been enabled for mixing.
783 if (in == NULL) {
784 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
785 return;
786 }
787 size_t outFrames = b.frameCount;
788
789 if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
790 // volume is boosted, so we might need to clamp even though
791 // we process only one track.
792 do {
793 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
794 in += 2;
795 int32_t l = mulRL(1, rl, vrl) >> 12;
796 int32_t r = mulRL(0, rl, vrl) >> 12;
797 // clamping...
798 l = clamp16(l);
799 r = clamp16(r);
800 *out++ = (r<<16) | (l & 0xFFFF);
801 } while (--outFrames);
802 } else {
803 do {
804 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
805 in += 2;
806 int32_t l = mulRL(1, rl, vrl) >> 12;
807 int32_t r = mulRL(0, rl, vrl) >> 12;
808 *out++ = (r<<16) | (l & 0xFFFF);
809 } while (--outFrames);
810 }
811 numFrames -= b.frameCount;
812 t.bufferProvider->releaseBuffer(&b);
813 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700814}
815
816// 2 tracks is also a common case
817void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state, void* output)
818{
819 int i;
820 uint32_t en = state->enabledTracks;
821
822 i = 31 - __builtin_clz(en);
823 const track_t& t0 = state->tracks[i];
824 AudioBufferProvider::Buffer& b0(t0.buffer);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700825
826 en &= ~(1<<i);
827 i = 31 - __builtin_clz(en);
828 const track_t& t1 = state->tracks[i];
829 AudioBufferProvider::Buffer& b1(t1.buffer);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800830
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700831 int16_t const *in0;
832 const int16_t vl0 = t0.volume[0];
833 const int16_t vr0 = t0.volume[1];
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800834 size_t frameCount0 = 0;
835
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700836 int16_t const *in1;
837 const int16_t vl1 = t1.volume[0];
838 const int16_t vr1 = t1.volume[1];
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800839 size_t frameCount1 = 0;
840
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700841 int32_t* out = static_cast<int32_t*>(output);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800842 size_t numFrames = state->frameCount;
843 int16_t const *buff = NULL;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700844
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800845
846 while (numFrames) {
847
848 if (frameCount0 == 0) {
849 b0.frameCount = numFrames;
850 t0.bufferProvider->getNextBuffer(&b0);
851 if (b0.i16 == NULL) {
852 if (buff == NULL) {
853 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
854 }
855 in0 = buff;
856 b0.frameCount = numFrames;
857 } else {
858 in0 = b0.i16;
859 }
860 frameCount0 = b0.frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700861 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800862 if (frameCount1 == 0) {
863 b1.frameCount = numFrames;
864 t1.bufferProvider->getNextBuffer(&b1);
865 if (b1.i16 == NULL) {
866 if (buff == NULL) {
867 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
868 }
869 in1 = buff;
870 b1.frameCount = numFrames;
871 } else {
872 in1 = b1.i16;
873 }
874 frameCount1 = b1.frameCount;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700875 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800876
877 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700878
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800879 numFrames -= outFrames;
880 frameCount0 -= outFrames;
881 frameCount1 -= outFrames;
882
883 do {
884 int32_t l0 = *in0++;
885 int32_t r0 = *in0++;
886 l0 = mul(l0, vl0);
887 r0 = mul(r0, vr0);
888 int32_t l = *in1++;
889 int32_t r = *in1++;
890 l = mulAdd(l, vl1, l0) >> 12;
891 r = mulAdd(r, vr1, r0) >> 12;
892 // clamping...
893 l = clamp16(l);
894 r = clamp16(r);
895 *out++ = (r<<16) | (l & 0xFFFF);
896 } while (--outFrames);
897
898 if (frameCount0 == 0) {
899 t0.bufferProvider->releaseBuffer(&b0);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700900 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800901 if (frameCount1 == 0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700902 t1.bufferProvider->releaseBuffer(&b1);
903 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800904 }
905
906 if (buff != NULL) {
907 delete [] buff;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700908 }
909}
910
911// ----------------------------------------------------------------------------
912}; // namespace android
913