blob: 760981b5361cc1b0924f87d57d38a55029de31cb [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
Mike J. Chenc94519c2011-08-15 13:28:26 -070021#include <assert.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include <stdint.h>
23#include <string.h>
24#include <stdlib.h>
25#include <sys/types.h>
26
27#include <utils/Errors.h>
28#include <utils/Log.h>
29
Jean-Michel Trivi54392232011-05-24 15:53:33 -070030#include <cutils/bitops.h>
31
32#include <system/audio.h>
33
Mike J. Chenc94519c2011-08-15 13:28:26 -070034#include <aah_timesrv/local_clock.h>
35#include <aah_timesrv/cc_helper.h>
36
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037#include "AudioMixer.h"
38
39namespace android {
40// ----------------------------------------------------------------------------
41
42static inline int16_t clamp16(int32_t sample)
43{
44 if ((sample>>15) ^ (sample>>31))
45 sample = 0x7FFF ^ (sample>>31);
46 return sample;
47}
48
49// ----------------------------------------------------------------------------
50
51AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
52 : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
53{
Mike J. Chenc94519c2011-08-15 13:28:26 -070054 LocalClock lc;
55 mLocalTimeFreq = lc.getLocalFreq();
56
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 mState.enabledTracks= 0;
58 mState.needsChanged = 0;
59 mState.frameCount = frameCount;
60 mState.outputTemp = 0;
61 mState.resampleTemp = 0;
62 mState.hook = process__nop;
63 track_t* t = mState.tracks;
64 for (int i=0 ; i<32 ; i++) {
65 t->needs = 0;
66 t->volume[0] = UNITY_GAIN;
67 t->volume[1] = UNITY_GAIN;
68 t->volumeInc[0] = 0;
69 t->volumeInc[1] = 0;
Eric Laurent65b65452010-06-01 23:49:17 -070070 t->auxLevel = 0;
71 t->auxInc = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 t->channelCount = 2;
73 t->enabled = 0;
74 t->format = 16;
Jean-Michel Trivi54392232011-05-24 15:53:33 -070075 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 t->buffer.raw = 0;
77 t->bufferProvider = 0;
78 t->hook = 0;
79 t->resampler = 0;
80 t->sampleRate = mSampleRate;
81 t->in = 0;
Eric Laurent65b65452010-06-01 23:49:17 -070082 t->mainBuffer = NULL;
83 t->auxBuffer = NULL;
Mike J. Chenc94519c2011-08-15 13:28:26 -070084 t->localTimeFreq = mLocalTimeFreq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 t++;
86 }
87}
88
89 AudioMixer::~AudioMixer()
90 {
91 track_t* t = mState.tracks;
92 for (int i=0 ; i<32 ; i++) {
93 delete t->resampler;
94 t++;
95 }
96 delete [] mState.outputTemp;
97 delete [] mState.resampleTemp;
98 }
99
100 int AudioMixer::getTrackName()
101 {
102 uint32_t names = mTrackNames;
103 uint32_t mask = 1;
104 int n = 0;
105 while (names & mask) {
106 mask <<= 1;
107 n++;
108 }
109 if (mask) {
110 LOGV("add track (%d)", n);
111 mTrackNames |= mask;
112 return TRACK0 + n;
113 }
114 return -1;
115 }
116
117 void AudioMixer::invalidateState(uint32_t mask)
118 {
119 if (mask) {
120 mState.needsChanged |= mask;
121 mState.hook = process__validate;
122 }
123 }
124
125 void AudioMixer::deleteTrackName(int name)
126 {
127 name -= TRACK0;
128 if (uint32_t(name) < MAX_NUM_TRACKS) {
129 LOGV("deleteTrackName(%d)", name);
130 track_t& track(mState.tracks[ name ]);
131 if (track.enabled != 0) {
132 track.enabled = 0;
133 invalidateState(1<<name);
134 }
135 if (track.resampler) {
136 // delete the resampler
137 delete track.resampler;
138 track.resampler = 0;
139 track.sampleRate = mSampleRate;
140 invalidateState(1<<name);
141 }
142 track.volumeInc[0] = 0;
143 track.volumeInc[1] = 0;
144 mTrackNames &= ~(1<<name);
145 }
146 }
147
148status_t AudioMixer::enable(int name)
149{
150 switch (name) {
151 case MIXING: {
152 if (mState.tracks[ mActiveTrack ].enabled != 1) {
153 mState.tracks[ mActiveTrack ].enabled = 1;
154 LOGV("enable(%d)", mActiveTrack);
155 invalidateState(1<<mActiveTrack);
156 }
157 } break;
158 default:
159 return NAME_NOT_FOUND;
160 }
161 return NO_ERROR;
162}
163
164status_t AudioMixer::disable(int name)
165{
166 switch (name) {
167 case MIXING: {
168 if (mState.tracks[ mActiveTrack ].enabled != 0) {
169 mState.tracks[ mActiveTrack ].enabled = 0;
170 LOGV("disable(%d)", mActiveTrack);
171 invalidateState(1<<mActiveTrack);
172 }
173 } break;
174 default:
175 return NAME_NOT_FOUND;
176 }
177 return NO_ERROR;
178}
179
180status_t AudioMixer::setActiveTrack(int track)
181{
182 if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) {
183 return BAD_VALUE;
184 }
185 mActiveTrack = track - TRACK0;
186 return NO_ERROR;
187}
188
Eric Laurent65b65452010-06-01 23:49:17 -0700189status_t AudioMixer::setParameter(int target, int name, void *value)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190{
Eric Laurent65b65452010-06-01 23:49:17 -0700191 int valueInt = (int)value;
192 int32_t *valueBuf = (int32_t *)value;
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 switch (target) {
195 case TRACK:
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700196 if (name == CHANNEL_MASK) {
197 uint32_t mask = (uint32_t)value;
198 if (mState.tracks[ mActiveTrack ].channelMask != mask) {
199 uint8_t channelCount = popcount(mask);
200 if ((channelCount <= MAX_NUM_CHANNELS) && (channelCount)) {
201 mState.tracks[ mActiveTrack ].channelMask = mask;
202 mState.tracks[ mActiveTrack ].channelCount = channelCount;
203 LOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 invalidateState(1<<mActiveTrack);
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700205 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 }
Jean-Michel Trivi54392232011-05-24 15:53:33 -0700207 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 return NO_ERROR;
209 }
210 }
Eric Laurent65b65452010-06-01 23:49:17 -0700211 if (name == MAIN_BUFFER) {
212 if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
213 mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
214 LOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
215 invalidateState(1<<mActiveTrack);
216 }
217 return NO_ERROR;
218 }
219 if (name == AUX_BUFFER) {
220 if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
221 mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
222 LOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
223 invalidateState(1<<mActiveTrack);
224 }
225 return NO_ERROR;
226 }
227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 break;
229 case RESAMPLE:
230 if (name == SAMPLE_RATE) {
Eric Laurent65b65452010-06-01 23:49:17 -0700231 if (valueInt > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 track_t& track = mState.tracks[ mActiveTrack ];
Eric Laurent65b65452010-06-01 23:49:17 -0700233 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 LOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
Eric Laurent65b65452010-06-01 23:49:17 -0700235 uint32_t(valueInt));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 invalidateState(1<<mActiveTrack);
237 }
238 return NO_ERROR;
239 }
240 }
Eric Laurent4bb21c42011-02-28 16:52:51 -0800241 if (name == RESET) {
242 track_t& track = mState.tracks[ mActiveTrack ];
243 track.resetResampler();
244 invalidateState(1<<mActiveTrack);
245 return NO_ERROR;
246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 break;
248 case RAMP_VOLUME:
249 case VOLUME:
250 if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) {
251 track_t& track = mState.tracks[ mActiveTrack ];
Eric Laurent65b65452010-06-01 23:49:17 -0700252 if (track.volume[name-VOLUME0] != valueInt) {
253 LOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
Eric Laurent65b65452010-06-01 23:49:17 -0700255 track.volume[name-VOLUME0] = valueInt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 if (target == VOLUME) {
Eric Laurent65b65452010-06-01 23:49:17 -0700257 track.prevVolume[name-VOLUME0] = valueInt << 16;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 track.volumeInc[name-VOLUME0] = 0;
259 } else {
Eric Laurent65b65452010-06-01 23:49:17 -0700260 int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 int32_t volInc = d / int32_t(mState.frameCount);
262 track.volumeInc[name-VOLUME0] = volInc;
263 if (volInc == 0) {
Eric Laurent65b65452010-06-01 23:49:17 -0700264 track.prevVolume[name-VOLUME0] = valueInt << 16;
265 }
266 }
267 invalidateState(1<<mActiveTrack);
268 }
269 return NO_ERROR;
270 } else if (name == AUXLEVEL) {
271 track_t& track = mState.tracks[ mActiveTrack ];
272 if (track.auxLevel != valueInt) {
273 LOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
274 track.prevAuxLevel = track.auxLevel << 16;
275 track.auxLevel = valueInt;
276 if (target == VOLUME) {
277 track.prevAuxLevel = valueInt << 16;
278 track.auxInc = 0;
279 } else {
280 int32_t d = (valueInt<<16) - track.prevAuxLevel;
281 int32_t volInc = d / int32_t(mState.frameCount);
282 track.auxInc = volInc;
283 if (volInc == 0) {
284 track.prevAuxLevel = valueInt << 16;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 }
286 }
287 invalidateState(1<<mActiveTrack);
288 }
289 return NO_ERROR;
290 }
291 break;
292 }
293 return BAD_VALUE;
294}
295
296bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
297{
298 if (value!=devSampleRate || resampler) {
299 if (sampleRate != value) {
300 sampleRate = value;
301 if (resampler == 0) {
302 resampler = AudioResampler::create(
303 format, channelCount, devSampleRate);
Mike J. Chenc94519c2011-08-15 13:28:26 -0700304 resampler->setLocalTimeFreq(localTimeFreq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 }
306 return true;
307 }
308 }
309 return false;
310}
311
312bool AudioMixer::track_t::doesResample() const
313{
314 return resampler != 0;
315}
316
Eric Laurent4bb21c42011-02-28 16:52:51 -0800317void AudioMixer::track_t::resetResampler()
318{
319 if (resampler != 0) {
320 resampler->reset();
321 }
322}
323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324inline
Eric Laurent65b65452010-06-01 23:49:17 -0700325void AudioMixer::track_t::adjustVolumeRamp(bool aux)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326{
327 for (int i=0 ; i<2 ; i++) {
328 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
329 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
330 volumeInc[i] = 0;
331 prevVolume[i] = volume[i]<<16;
332 }
333 }
Eric Laurent65b65452010-06-01 23:49:17 -0700334 if (aux) {
335 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
336 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
337 auxInc = 0;
338 prevAuxLevel = auxLevel<<16;
339 }
340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341}
342
343
344status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
345{
346 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
347 return NO_ERROR;
348}
349
350
351
Mike J. Chenc94519c2011-08-15 13:28:26 -0700352void AudioMixer::process(int64_t pts)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353{
Mike J. Chenc94519c2011-08-15 13:28:26 -0700354 mState.hook(&mState, pts);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355}
356
357
Mike J. Chenc94519c2011-08-15 13:28:26 -0700358void AudioMixer::process__validate(state_t* state, int64_t pts)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359{
360 LOGW_IF(!state->needsChanged,
361 "in process__validate() but nothing's invalid");
362
363 uint32_t changed = state->needsChanged;
364 state->needsChanged = 0; // clear the validation flag
365
366 // recompute which tracks are enabled / disabled
367 uint32_t enabled = 0;
368 uint32_t disabled = 0;
369 while (changed) {
370 const int i = 31 - __builtin_clz(changed);
371 const uint32_t mask = 1<<i;
372 changed &= ~mask;
373 track_t& t = state->tracks[i];
374 (t.enabled ? enabled : disabled) |= mask;
375 }
376 state->enabledTracks &= ~disabled;
377 state->enabledTracks |= enabled;
378
379 // compute everything we need...
380 int countActiveTracks = 0;
381 int all16BitsStereoNoResample = 1;
382 int resampling = 0;
383 int volumeRamp = 0;
384 uint32_t en = state->enabledTracks;
385 while (en) {
386 const int i = 31 - __builtin_clz(en);
387 en &= ~(1<<i);
388
389 countActiveTracks++;
390 track_t& t = state->tracks[i];
391 uint32_t n = 0;
392 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
393 n |= NEEDS_FORMAT_16;
394 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
Eric Laurent65b65452010-06-01 23:49:17 -0700395 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
396 n |= NEEDS_AUX_ENABLED;
397 }
398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 if (t.volumeInc[0]|t.volumeInc[1]) {
400 volumeRamp = 1;
401 } else if (!t.doesResample() && t.volumeRL == 0) {
402 n |= NEEDS_MUTE_ENABLED;
403 }
404 t.needs = n;
405
406 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
407 t.hook = track__nop;
408 } else {
Eric Laurent65b65452010-06-01 23:49:17 -0700409 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
410 all16BitsStereoNoResample = 0;
411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
413 all16BitsStereoNoResample = 0;
414 resampling = 1;
415 t.hook = track__genericResample;
416 } else {
417 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
418 t.hook = track__16BitsMono;
419 all16BitsStereoNoResample = 0;
420 }
421 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
422 t.hook = track__16BitsStereo;
423 }
424 }
425 }
426 }
427
428 // select the processing hooks
429 state->hook = process__nop;
430 if (countActiveTracks) {
431 if (resampling) {
432 if (!state->outputTemp) {
433 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
434 }
435 if (!state->resampleTemp) {
436 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
437 }
438 state->hook = process__genericResampling;
439 } else {
440 if (state->outputTemp) {
441 delete [] state->outputTemp;
442 state->outputTemp = 0;
443 }
444 if (state->resampleTemp) {
445 delete [] state->resampleTemp;
446 state->resampleTemp = 0;
447 }
448 state->hook = process__genericNoResampling;
449 if (all16BitsStereoNoResample && !volumeRamp) {
450 if (countActiveTracks == 1) {
451 state->hook = process__OneTrack16BitsStereoNoResampling;
452 }
453 }
454 }
455 }
456
457 LOGV("mixer configuration change: %d activeTracks (%08x) "
458 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
459 countActiveTracks, state->enabledTracks,
460 all16BitsStereoNoResample, resampling, volumeRamp);
461
Mike J. Chenc94519c2011-08-15 13:28:26 -0700462 state->hook(state, pts);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463
464 // Now that the volume ramp has been done, set optimal state and
465 // track hooks for subsequent mixer process
466 if (countActiveTracks) {
467 int allMuted = 1;
468 uint32_t en = state->enabledTracks;
469 while (en) {
470 const int i = 31 - __builtin_clz(en);
471 en &= ~(1<<i);
472 track_t& t = state->tracks[i];
473 if (!t.doesResample() && t.volumeRL == 0)
474 {
475 t.needs |= NEEDS_MUTE_ENABLED;
476 t.hook = track__nop;
477 } else {
478 allMuted = 0;
479 }
480 }
481 if (allMuted) {
482 state->hook = process__nop;
Eric Laurent65b65452010-06-01 23:49:17 -0700483 } else if (all16BitsStereoNoResample) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 if (countActiveTracks == 1) {
485 state->hook = process__OneTrack16BitsStereoNoResampling;
486 }
487 }
488 }
489}
490
491static inline
492int32_t mulAdd(int16_t in, int16_t v, int32_t a)
493{
494#if defined(__arm__) && !defined(__thumb__)
495 int32_t out;
496 asm( "smlabb %[out], %[in], %[v], %[a] \n"
497 : [out]"=r"(out)
498 : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
499 : );
500 return out;
501#else
502 return a + in * int32_t(v);
503#endif
504}
505
506static inline
507int32_t mul(int16_t in, int16_t v)
508{
509#if defined(__arm__) && !defined(__thumb__)
510 int32_t out;
511 asm( "smulbb %[out], %[in], %[v] \n"
512 : [out]"=r"(out)
513 : [in]"%r"(in), [v]"r"(v)
514 : );
515 return out;
516#else
517 return in * int32_t(v);
518#endif
519}
520
521static inline
522int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
523{
524#if defined(__arm__) && !defined(__thumb__)
525 int32_t out;
526 if (left) {
527 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
528 : [out]"=r"(out)
529 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
530 : );
531 } else {
532 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
533 : [out]"=r"(out)
534 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
535 : );
536 }
537 return out;
538#else
539 if (left) {
540 return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
541 } else {
542 return a + int16_t(inRL>>16) * int16_t(vRL>>16);
543 }
544#endif
545}
546
547static inline
548int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
549{
550#if defined(__arm__) && !defined(__thumb__)
551 int32_t out;
552 if (left) {
553 asm( "smulbb %[out], %[inRL], %[vRL] \n"
554 : [out]"=r"(out)
555 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
556 : );
557 } else {
558 asm( "smultt %[out], %[inRL], %[vRL] \n"
559 : [out]"=r"(out)
560 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
561 : );
562 }
563 return out;
564#else
565 if (left) {
566 return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
567 } else {
568 return int16_t(inRL>>16) * int16_t(vRL>>16);
569 }
570#endif
571}
572
573
Eric Laurent65b65452010-06-01 23:49:17 -0700574void 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 -0800575{
576 t->resampler->setSampleRate(t->sampleRate);
577
578 // ramp gain - resample to temp buffer and scale/mix in 2nd step
Eric Laurent65b65452010-06-01 23:49:17 -0700579 if (aux != NULL) {
580 // always resample with unity gain when sending to auxiliary buffer to be able
581 // to apply send level after resampling
582 // TODO: modify each resampler to support aux channel?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
584 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
585 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Eric Laurent65b65452010-06-01 23:49:17 -0700586 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
587 volumeRampStereo(t, out, outFrameCount, temp, aux);
588 } else {
589 volumeStereo(t, out, outFrameCount, temp, aux);
590 }
591 } else {
592 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
593 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
594 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
595 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
596 volumeRampStereo(t, out, outFrameCount, temp, aux);
597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598
Eric Laurent65b65452010-06-01 23:49:17 -0700599 // constant gain
600 else {
601 t->resampler->setVolume(t->volume[0], t->volume[1]);
602 t->resampler->resample(out, outFrameCount, t->bufferProvider);
603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 }
605}
606
Eric Laurent65b65452010-06-01 23:49:17 -0700607void 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 -0800608{
609}
610
Eric Laurent65b65452010-06-01 23:49:17 -0700611void 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 -0800612{
613 int32_t vl = t->prevVolume[0];
614 int32_t vr = t->prevVolume[1];
615 const int32_t vlInc = t->volumeInc[0];
616 const int32_t vrInc = t->volumeInc[1];
617
618 //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
619 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
620 // (vl + vlInc*frameCount)/65536.0f, frameCount);
Eric Laurent65b65452010-06-01 23:49:17 -0700621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 // ramp volume
Eric Laurent65b65452010-06-01 23:49:17 -0700623 if UNLIKELY(aux != NULL) {
624 int32_t va = t->prevAuxLevel;
625 const int32_t vaInc = t->auxInc;
626 int32_t l;
627 int32_t r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628
629 do {
Eric Laurent65b65452010-06-01 23:49:17 -0700630 l = (*temp++ >> 12);
631 r = (*temp++ >> 12);
632 *out++ += (vl >> 16) * l;
633 *out++ += (vr >> 16) * r;
634 *aux++ += (va >> 17) * (l + r);
635 vl += vlInc;
636 vr += vrInc;
637 va += vaInc;
638 } while (--frameCount);
639 t->prevAuxLevel = va;
640 } else {
641 do {
642 *out++ += (vl >> 16) * (*temp++ >> 12);
643 *out++ += (vr >> 16) * (*temp++ >> 12);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 vl += vlInc;
645 vr += vrInc;
646 } while (--frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 }
Eric Laurent65b65452010-06-01 23:49:17 -0700648 t->prevVolume[0] = vl;
649 t->prevVolume[1] = vr;
650 t->adjustVolumeRamp((aux != NULL));
651}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652
Eric Laurent65b65452010-06-01 23:49:17 -0700653void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
654{
655 const int16_t vl = t->volume[0];
656 const int16_t vr = t->volume[1];
657
658 if UNLIKELY(aux != NULL) {
659 const int16_t va = (int16_t)t->auxLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 do {
Eric Laurent65b65452010-06-01 23:49:17 -0700661 int16_t l = (int16_t)(*temp++ >> 12);
662 int16_t r = (int16_t)(*temp++ >> 12);
663 out[0] = mulAdd(l, vl, out[0]);
664 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
665 out[1] = mulAdd(r, vr, out[1]);
666 out += 2;
667 aux[0] = mulAdd(a, va, aux[0]);
668 aux++;
669 } while (--frameCount);
670 } else {
671 do {
672 int16_t l = (int16_t)(*temp++ >> 12);
673 int16_t r = (int16_t)(*temp++ >> 12);
674 out[0] = mulAdd(l, vl, out[0]);
675 out[1] = mulAdd(r, vr, out[1]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 out += 2;
677 } while (--frameCount);
678 }
Eric Laurent65b65452010-06-01 23:49:17 -0700679}
680
681void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
682{
683 int16_t const *in = static_cast<int16_t const *>(t->in);
684
685 if UNLIKELY(aux != NULL) {
686 int32_t l;
687 int32_t r;
688 // ramp gain
689 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
690 int32_t vl = t->prevVolume[0];
691 int32_t vr = t->prevVolume[1];
692 int32_t va = t->prevAuxLevel;
693 const int32_t vlInc = t->volumeInc[0];
694 const int32_t vrInc = t->volumeInc[1];
695 const int32_t vaInc = t->auxInc;
696 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
697 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
698 // (vl + vlInc*frameCount)/65536.0f, frameCount);
699
700 do {
701 l = (int32_t)*in++;
702 r = (int32_t)*in++;
703 *out++ += (vl >> 16) * l;
704 *out++ += (vr >> 16) * r;
705 *aux++ += (va >> 17) * (l + r);
706 vl += vlInc;
707 vr += vrInc;
708 va += vaInc;
709 } while (--frameCount);
710
711 t->prevVolume[0] = vl;
712 t->prevVolume[1] = vr;
713 t->prevAuxLevel = va;
714 t->adjustVolumeRamp(true);
715 }
716
717 // constant gain
718 else {
719 const uint32_t vrl = t->volumeRL;
720 const int16_t va = (int16_t)t->auxLevel;
721 do {
722 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
723 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
724 in += 2;
725 out[0] = mulAddRL(1, rl, vrl, out[0]);
726 out[1] = mulAddRL(0, rl, vrl, out[1]);
727 out += 2;
728 aux[0] = mulAdd(a, va, aux[0]);
729 aux++;
730 } while (--frameCount);
731 }
732 } else {
733 // ramp gain
734 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
735 int32_t vl = t->prevVolume[0];
736 int32_t vr = t->prevVolume[1];
737 const int32_t vlInc = t->volumeInc[0];
738 const int32_t vrInc = t->volumeInc[1];
739
740 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
741 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
742 // (vl + vlInc*frameCount)/65536.0f, frameCount);
743
744 do {
745 *out++ += (vl >> 16) * (int32_t) *in++;
746 *out++ += (vr >> 16) * (int32_t) *in++;
747 vl += vlInc;
748 vr += vrInc;
749 } while (--frameCount);
750
751 t->prevVolume[0] = vl;
752 t->prevVolume[1] = vr;
753 t->adjustVolumeRamp(false);
754 }
755
756 // constant gain
757 else {
758 const uint32_t vrl = t->volumeRL;
759 do {
760 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
761 in += 2;
762 out[0] = mulAddRL(1, rl, vrl, out[0]);
763 out[1] = mulAddRL(0, rl, vrl, out[1]);
764 out += 2;
765 } while (--frameCount);
766 }
767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 t->in = in;
769}
770
Eric Laurent65b65452010-06-01 23:49:17 -0700771void 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 -0800772{
773 int16_t const *in = static_cast<int16_t const *>(t->in);
774
Eric Laurent65b65452010-06-01 23:49:17 -0700775 if UNLIKELY(aux != NULL) {
776 // ramp gain
777 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
778 int32_t vl = t->prevVolume[0];
779 int32_t vr = t->prevVolume[1];
780 int32_t va = t->prevAuxLevel;
781 const int32_t vlInc = t->volumeInc[0];
782 const int32_t vrInc = t->volumeInc[1];
783 const int32_t vaInc = t->auxInc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784
Eric Laurent65b65452010-06-01 23:49:17 -0700785 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
786 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
787 // (vl + vlInc*frameCount)/65536.0f, frameCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788
Eric Laurent65b65452010-06-01 23:49:17 -0700789 do {
790 int32_t l = *in++;
791 *out++ += (vl >> 16) * l;
792 *out++ += (vr >> 16) * l;
793 *aux++ += (va >> 16) * l;
794 vl += vlInc;
795 vr += vrInc;
796 va += vaInc;
797 } while (--frameCount);
798
799 t->prevVolume[0] = vl;
800 t->prevVolume[1] = vr;
801 t->prevAuxLevel = va;
802 t->adjustVolumeRamp(true);
803 }
804 // constant gain
805 else {
806 const int16_t vl = t->volume[0];
807 const int16_t vr = t->volume[1];
808 const int16_t va = (int16_t)t->auxLevel;
809 do {
810 int16_t l = *in++;
811 out[0] = mulAdd(l, vl, out[0]);
812 out[1] = mulAdd(l, vr, out[1]);
813 out += 2;
814 aux[0] = mulAdd(l, va, aux[0]);
815 aux++;
816 } while (--frameCount);
817 }
818 } else {
819 // ramp gain
820 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
821 int32_t vl = t->prevVolume[0];
822 int32_t vr = t->prevVolume[1];
823 const int32_t vlInc = t->volumeInc[0];
824 const int32_t vrInc = t->volumeInc[1];
825
826 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
827 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
828 // (vl + vlInc*frameCount)/65536.0f, frameCount);
829
830 do {
831 int32_t l = *in++;
832 *out++ += (vl >> 16) * l;
833 *out++ += (vr >> 16) * l;
834 vl += vlInc;
835 vr += vrInc;
836 } while (--frameCount);
837
838 t->prevVolume[0] = vl;
839 t->prevVolume[1] = vr;
840 t->adjustVolumeRamp(false);
841 }
842 // constant gain
843 else {
844 const int16_t vl = t->volume[0];
845 const int16_t vr = t->volume[1];
846 do {
847 int16_t l = *in++;
848 out[0] = mulAdd(l, vl, out[0]);
849 out[1] = mulAdd(l, vr, out[1]);
850 out += 2;
851 } while (--frameCount);
852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 }
854 t->in = in;
855}
856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
858{
859 for (size_t i=0 ; i<c ; i++) {
860 int32_t l = *sums++;
861 int32_t r = *sums++;
862 int32_t nl = l >> 12;
863 int32_t nr = r >> 12;
864 l = clamp16(nl);
865 r = clamp16(nr);
866 *out++ = (r<<16) | (l & 0xFFFF);
867 }
868}
869
870// no-op case
Mike J. Chenc94519c2011-08-15 13:28:26 -0700871void AudioMixer::process__nop(state_t* state, int64_t pts)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872{
Eric Laurent65b65452010-06-01 23:49:17 -0700873 uint32_t e0 = state->enabledTracks;
874 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
875 while (e0) {
876 // process by group of tracks with same output buffer to
877 // avoid multiple memset() on same buffer
878 uint32_t e1 = e0, e2 = e0;
879 int i = 31 - __builtin_clz(e1);
880 track_t& t1 = state->tracks[i];
881 e2 &= ~(1<<i);
882 while (e2) {
883 i = 31 - __builtin_clz(e2);
884 e2 &= ~(1<<i);
885 track_t& t2 = state->tracks[i];
886 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
887 e1 &= ~(1<<i);
888 }
889 }
890 e0 &= ~(e1);
891
892 memset(t1.mainBuffer, 0, bufSize);
893
894 while (e1) {
895 i = 31 - __builtin_clz(e1);
896 e1 &= ~(1<<i);
897 t1 = state->tracks[i];
898 size_t outFrames = state->frameCount;
899 while (outFrames) {
900 t1.buffer.frameCount = outFrames;
Mike J. Chenc94519c2011-08-15 13:28:26 -0700901 int64_t outputPTS = calculateOutputPTS(
902 t1, pts, state->frameCount - outFrames);
903 t1.bufferProvider->getNextBuffer(&t1.buffer, outputPTS);
Eric Laurent65b65452010-06-01 23:49:17 -0700904 if (!t1.buffer.raw) break;
905 outFrames -= t1.buffer.frameCount;
906 t1.bufferProvider->releaseBuffer(&t1.buffer);
907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 }
909 }
910}
911
912// generic code without resampling
Mike J. Chenc94519c2011-08-15 13:28:26 -0700913void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914{
915 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
916
917 // acquire each track's buffer
918 uint32_t enabledTracks = state->enabledTracks;
Eric Laurent65b65452010-06-01 23:49:17 -0700919 uint32_t e0 = enabledTracks;
920 while (e0) {
921 const int i = 31 - __builtin_clz(e0);
922 e0 &= ~(1<<i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 track_t& t = state->tracks[i];
924 t.buffer.frameCount = state->frameCount;
Mike J. Chenc94519c2011-08-15 13:28:26 -0700925 t.bufferProvider->getNextBuffer(&t.buffer, pts);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 t.frameCount = t.buffer.frameCount;
927 t.in = t.buffer.raw;
928 // t.in == NULL can happen if the track was flushed just after having
929 // been enabled for mixing.
930 if (t.in == NULL)
931 enabledTracks &= ~(1<<i);
932 }
933
Eric Laurent65b65452010-06-01 23:49:17 -0700934 e0 = enabledTracks;
935 while (e0) {
936 // process by group of tracks with same output buffer to
937 // optimize cache use
938 uint32_t e1 = e0, e2 = e0;
939 int j = 31 - __builtin_clz(e1);
940 track_t& t1 = state->tracks[j];
941 e2 &= ~(1<<j);
942 while (e2) {
943 j = 31 - __builtin_clz(e2);
944 e2 &= ~(1<<j);
945 track_t& t2 = state->tracks[j];
946 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
947 e1 &= ~(1<<j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 }
949 }
Eric Laurent65b65452010-06-01 23:49:17 -0700950 e0 &= ~(e1);
951 // this assumes output 16 bits stereo, no resampling
952 int32_t *out = t1.mainBuffer;
953 size_t numFrames = 0;
954 do {
955 memset(outTemp, 0, sizeof(outTemp));
956 e2 = e1;
957 while (e2) {
958 const int i = 31 - __builtin_clz(e2);
959 e2 &= ~(1<<i);
960 track_t& t = state->tracks[i];
961 size_t outFrames = BLOCKSIZE;
962 int32_t *aux = NULL;
963 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
964 aux = t.auxBuffer + numFrames;
965 }
966 while (outFrames) {
967 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
968 if (inFrames) {
969 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
970 t.frameCount -= inFrames;
971 outFrames -= inFrames;
972 if UNLIKELY(aux != NULL) {
973 aux += inFrames;
974 }
975 }
976 if (t.frameCount == 0 && outFrames) {
977 t.bufferProvider->releaseBuffer(&t.buffer);
978 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
Mike J. Chenc94519c2011-08-15 13:28:26 -0700979 int64_t outputPTS = calculateOutputPTS(
980 t, pts, numFrames + (BLOCKSIZE - outFrames));
981 t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
Eric Laurent65b65452010-06-01 23:49:17 -0700982 t.in = t.buffer.raw;
983 if (t.in == NULL) {
984 enabledTracks &= ~(1<<i);
985 e1 &= ~(1<<i);
986 break;
987 }
988 t.frameCount = t.buffer.frameCount;
989 }
990 }
991 }
992 ditherAndClamp(out, outTemp, BLOCKSIZE);
993 out += BLOCKSIZE;
994 numFrames += BLOCKSIZE;
995 } while (numFrames < state->frameCount);
996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997
998 // release each track's buffer
Eric Laurent65b65452010-06-01 23:49:17 -0700999 e0 = enabledTracks;
1000 while (e0) {
1001 const int i = 31 - __builtin_clz(e0);
1002 e0 &= ~(1<<i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 track_t& t = state->tracks[i];
1004 t.bufferProvider->releaseBuffer(&t.buffer);
1005 }
1006}
1007
Eric Laurent65b65452010-06-01 23:49:17 -07001008
1009 // generic code with resampling
Mike J. Chenc94519c2011-08-15 13:28:26 -07001010void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011{
1012 int32_t* const outTemp = state->outputTemp;
1013 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 size_t numFrames = state->frameCount;
1016
Eric Laurent65b65452010-06-01 23:49:17 -07001017 uint32_t e0 = state->enabledTracks;
1018 while (e0) {
1019 // process by group of tracks with same output buffer
1020 // to optimize cache use
1021 uint32_t e1 = e0, e2 = e0;
1022 int j = 31 - __builtin_clz(e1);
1023 track_t& t1 = state->tracks[j];
1024 e2 &= ~(1<<j);
1025 while (e2) {
1026 j = 31 - __builtin_clz(e2);
1027 e2 &= ~(1<<j);
1028 track_t& t2 = state->tracks[j];
1029 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
1030 e1 &= ~(1<<j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 }
1032 }
Eric Laurent65b65452010-06-01 23:49:17 -07001033 e0 &= ~(e1);
1034 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi681d8182011-02-04 15:24:34 +01001035 memset(outTemp, 0, size);
Eric Laurent65b65452010-06-01 23:49:17 -07001036 while (e1) {
1037 const int i = 31 - __builtin_clz(e1);
1038 e1 &= ~(1<<i);
1039 track_t& t = state->tracks[i];
1040 int32_t *aux = NULL;
1041 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
1042 aux = t.auxBuffer;
1043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044
Eric Laurent65b65452010-06-01 23:49:17 -07001045 // this is a little goofy, on the resampling case we don't
1046 // acquire/release the buffers because it's done by
1047 // the resampler.
1048 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
Mike J. Chenc94519c2011-08-15 13:28:26 -07001049 t.resampler->setPTS(pts);
Eric Laurent65b65452010-06-01 23:49:17 -07001050 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
1051 } else {
1052
1053 size_t outFrames = 0;
1054
1055 while (outFrames < numFrames) {
1056 t.buffer.frameCount = numFrames - outFrames;
Mike J. Chenc94519c2011-08-15 13:28:26 -07001057 int64_t outputPTS = calculateOutputPTS(t, pts, outFrames);
1058 t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
Eric Laurent65b65452010-06-01 23:49:17 -07001059 t.in = t.buffer.raw;
1060 // t.in == NULL can happen if the track was flushed just after having
1061 // been enabled for mixing.
1062 if (t.in == NULL) break;
1063
1064 if UNLIKELY(aux != NULL) {
1065 aux += outFrames;
1066 }
1067 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
1068 outFrames += t.buffer.frameCount;
1069 t.bufferProvider->releaseBuffer(&t.buffer);
1070 }
1071 }
1072 }
1073 ditherAndClamp(out, outTemp, numFrames);
1074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075}
1076
1077// one track, 16 bits stereo without resampling is the most common case
Mike J. Chenc94519c2011-08-15 13:28:26 -07001078void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state,
1079 int64_t pts)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080{
1081 const int i = 31 - __builtin_clz(state->enabledTracks);
1082 const track_t& t = state->tracks[i];
1083
1084 AudioBufferProvider::Buffer& b(t.buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001085
1086 int32_t* out = t.mainBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 size_t numFrames = state->frameCount;
Eric Laurent65b65452010-06-01 23:49:17 -07001088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 const int16_t vl = t.volume[0];
1090 const int16_t vr = t.volume[1];
1091 const uint32_t vrl = t.volumeRL;
1092 while (numFrames) {
1093 b.frameCount = numFrames;
Mike J. Chenc94519c2011-08-15 13:28:26 -07001094 int64_t outputPTS = calculateOutputPTS(t, pts, out - t.mainBuffer);
1095 t.bufferProvider->getNextBuffer(&b, outputPTS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 int16_t const *in = b.i16;
1097
1098 // in == NULL can happen if the track was flushed just after having
1099 // been enabled for mixing.
The Android Open Source Project10592532009-03-18 17:39:46 -07001100 if (in == NULL || ((unsigned long)in & 3)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
The Android Open Source Project10592532009-03-18 17:39:46 -07001102 LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
1103 in, i, t.channelCount, t.needs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 return;
1105 }
1106 size_t outFrames = b.frameCount;
Eric Laurent65b65452010-06-01 23:49:17 -07001107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
1109 // volume is boosted, so we might need to clamp even though
1110 // we process only one track.
1111 do {
1112 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1113 in += 2;
1114 int32_t l = mulRL(1, rl, vrl) >> 12;
1115 int32_t r = mulRL(0, rl, vrl) >> 12;
1116 // clamping...
1117 l = clamp16(l);
1118 r = clamp16(r);
1119 *out++ = (r<<16) | (l & 0xFFFF);
1120 } while (--outFrames);
1121 } else {
1122 do {
1123 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1124 in += 2;
1125 int32_t l = mulRL(1, rl, vrl) >> 12;
1126 int32_t r = mulRL(0, rl, vrl) >> 12;
1127 *out++ = (r<<16) | (l & 0xFFFF);
1128 } while (--outFrames);
1129 }
1130 numFrames -= b.frameCount;
1131 t.bufferProvider->releaseBuffer(&b);
1132 }
1133}
1134
1135// 2 tracks is also a common case
Eric Laurent65b65452010-06-01 23:49:17 -07001136// NEVER used in current implementation of process__validate()
1137// only use if the 2 tracks have the same output buffer
Mike J. Chenc94519c2011-08-15 13:28:26 -07001138void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state,
1139 int64_t pts)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140{
1141 int i;
1142 uint32_t en = state->enabledTracks;
1143
1144 i = 31 - __builtin_clz(en);
1145 const track_t& t0 = state->tracks[i];
1146 AudioBufferProvider::Buffer& b0(t0.buffer);
1147
1148 en &= ~(1<<i);
1149 i = 31 - __builtin_clz(en);
1150 const track_t& t1 = state->tracks[i];
1151 AudioBufferProvider::Buffer& b1(t1.buffer);
Eric Laurent65b65452010-06-01 23:49:17 -07001152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 int16_t const *in0;
1154 const int16_t vl0 = t0.volume[0];
1155 const int16_t vr0 = t0.volume[1];
1156 size_t frameCount0 = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 int16_t const *in1;
1159 const int16_t vl1 = t1.volume[0];
1160 const int16_t vr1 = t1.volume[1];
1161 size_t frameCount1 = 0;
Eric Laurent65b65452010-06-01 23:49:17 -07001162
1163 //FIXME: only works if two tracks use same buffer
1164 int32_t* out = t0.mainBuffer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165 size_t numFrames = state->frameCount;
1166 int16_t const *buff = NULL;
1167
Eric Laurent65b65452010-06-01 23:49:17 -07001168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 while (numFrames) {
Eric Laurent65b65452010-06-01 23:49:17 -07001170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 if (frameCount0 == 0) {
1172 b0.frameCount = numFrames;
Mike J. Chenc94519c2011-08-15 13:28:26 -07001173 int64_t outputPTS = calculateOutputPTS(t0, pts,
1174 out - t0.mainBuffer);
1175 t0.bufferProvider->getNextBuffer(&b0, outputPTS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 if (b0.i16 == NULL) {
1177 if (buff == NULL) {
1178 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1179 }
1180 in0 = buff;
1181 b0.frameCount = numFrames;
1182 } else {
1183 in0 = b0.i16;
1184 }
1185 frameCount0 = b0.frameCount;
1186 }
1187 if (frameCount1 == 0) {
1188 b1.frameCount = numFrames;
Mike J. Chenc94519c2011-08-15 13:28:26 -07001189 int64_t outputPTS = calculateOutputPTS(t1, pts,
1190 out - t0.mainBuffer);
1191 t1.bufferProvider->getNextBuffer(&b1, outputPTS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 if (b1.i16 == NULL) {
1193 if (buff == NULL) {
1194 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1195 }
1196 in1 = buff;
1197 b1.frameCount = numFrames;
1198 } else {
1199 in1 = b1.i16;
1200 }
1201 frameCount1 = b1.frameCount;
1202 }
Eric Laurent65b65452010-06-01 23:49:17 -07001203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1205
1206 numFrames -= outFrames;
1207 frameCount0 -= outFrames;
1208 frameCount1 -= outFrames;
Eric Laurent65b65452010-06-01 23:49:17 -07001209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 do {
1211 int32_t l0 = *in0++;
1212 int32_t r0 = *in0++;
1213 l0 = mul(l0, vl0);
1214 r0 = mul(r0, vr0);
1215 int32_t l = *in1++;
1216 int32_t r = *in1++;
1217 l = mulAdd(l, vl1, l0) >> 12;
1218 r = mulAdd(r, vr1, r0) >> 12;
1219 // clamping...
1220 l = clamp16(l);
1221 r = clamp16(r);
1222 *out++ = (r<<16) | (l & 0xFFFF);
1223 } while (--outFrames);
Eric Laurent65b65452010-06-01 23:49:17 -07001224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 if (frameCount0 == 0) {
1226 t0.bufferProvider->releaseBuffer(&b0);
1227 }
1228 if (frameCount1 == 0) {
1229 t1.bufferProvider->releaseBuffer(&b1);
1230 }
Eric Laurent65b65452010-06-01 23:49:17 -07001231 }
1232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001233 if (buff != NULL) {
Eric Laurent65b65452010-06-01 23:49:17 -07001234 delete [] buff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001235 }
1236}
1237
Mike J. Chenc94519c2011-08-15 13:28:26 -07001238int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS,
1239 int outputFrameIndex)
1240{
1241 return basePTS + ((outputFrameIndex * t.localTimeFreq) / t.sampleRate);
1242}
1243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244// ----------------------------------------------------------------------------
1245}; // namespace android