blob: 1ebcd26f09eabb9df819d9b85f14f24644c9338b [file] [log] [blame]
Mathias Agopian65ab4712010-07-14 17:59:35 -07001/* //device/include/server/AudioFlinger/AudioMixer.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "AudioMixer"
19//#define LOG_NDEBUG 0
20
Glenn Kastenfba380a2011-12-15 15:46:46 -080021#include <assert.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070022#include <stdint.h>
23#include <string.h>
24#include <stdlib.h>
25#include <sys/types.h>
26
27#include <utils/Errors.h>
28#include <utils/Log.h>
29
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070030#include <cutils/bitops.h>
31
32#include <system/audio.h>
33
Mathias Agopian65ab4712010-07-14 17:59:35 -070034#include "AudioMixer.h"
35
36namespace android {
37// ----------------------------------------------------------------------------
38
39static inline int16_t clamp16(int32_t sample)
40{
41 if ((sample>>15) ^ (sample>>31))
42 sample = 0x7FFF ^ (sample>>31);
43 return sample;
44}
45
46// ----------------------------------------------------------------------------
47
48AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
49 : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
50{
51 mState.enabledTracks= 0;
52 mState.needsChanged = 0;
53 mState.frameCount = frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -080054 mState.outputTemp = NULL;
55 mState.resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070056 mState.hook = process__nop;
57 track_t* t = mState.tracks;
58 for (int i=0 ; i<32 ; i++) {
59 t->needs = 0;
60 t->volume[0] = UNITY_GAIN;
61 t->volume[1] = UNITY_GAIN;
Glenn Kasten0cfd8232011-12-13 11:58:23 -080062 // no initialization needed
63 // t->prevVolume[0]
64 // t->prevVolume[1]
Mathias Agopian65ab4712010-07-14 17:59:35 -070065 t->volumeInc[0] = 0;
66 t->volumeInc[1] = 0;
67 t->auxLevel = 0;
68 t->auxInc = 0;
Glenn Kasten0cfd8232011-12-13 11:58:23 -080069 // no initialization needed
70 // t->prevAuxLevel
71 // t->frameCount
Mathias Agopian65ab4712010-07-14 17:59:35 -070072 t->channelCount = 2;
73 t->enabled = 0;
74 t->format = 16;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070075 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -070076 t->buffer.raw = 0;
Glenn Kastene0feee32011-12-13 11:53:26 -080077 t->bufferProvider = NULL;
78 t->hook = NULL;
79 t->resampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070080 t->sampleRate = mSampleRate;
Glenn Kastene0feee32011-12-13 11:53:26 -080081 t->in = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070082 t->mainBuffer = NULL;
83 t->auxBuffer = NULL;
84 t++;
85 }
86}
87
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080088AudioMixer::~AudioMixer()
89{
90 track_t* t = mState.tracks;
91 for (int i=0 ; i<32 ; i++) {
92 delete t->resampler;
93 t++;
94 }
95 delete [] mState.outputTemp;
96 delete [] mState.resampleTemp;
97}
Mathias Agopian65ab4712010-07-14 17:59:35 -070098
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080099int AudioMixer::getTrackName()
100{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700101 uint32_t names = mTrackNames;
102 uint32_t mask = 1;
103 int n = 0;
104 while (names & mask) {
105 mask <<= 1;
106 n++;
107 }
108 if (mask) {
Steve Block3856b092011-10-20 11:56:00 +0100109 ALOGV("add track (%d)", n);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700110 mTrackNames |= mask;
111 return TRACK0 + n;
112 }
113 return -1;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800114}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700115
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800116void AudioMixer::invalidateState(uint32_t mask)
117{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700118 if (mask) {
119 mState.needsChanged |= mask;
120 mState.hook = process__validate;
121 }
122 }
123
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800124void AudioMixer::deleteTrackName(int name)
125{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700126 name -= TRACK0;
127 if (uint32_t(name) < MAX_NUM_TRACKS) {
Steve Block3856b092011-10-20 11:56:00 +0100128 ALOGV("deleteTrackName(%d)", name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700129 track_t& track(mState.tracks[ name ]);
130 if (track.enabled != 0) {
131 track.enabled = 0;
132 invalidateState(1<<name);
133 }
134 if (track.resampler) {
135 // delete the resampler
136 delete track.resampler;
Glenn Kastene0feee32011-12-13 11:53:26 -0800137 track.resampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700138 track.sampleRate = mSampleRate;
139 invalidateState(1<<name);
140 }
141 track.volumeInc[0] = 0;
142 track.volumeInc[1] = 0;
143 mTrackNames &= ~(1<<name);
144 }
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800145}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700146
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800147void AudioMixer::enable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700148{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800149 if (mState.tracks[ mActiveTrack ].enabled != 1) {
150 mState.tracks[ mActiveTrack ].enabled = 1;
151 ALOGV("enable(%d)", mActiveTrack);
152 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700153 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700154}
155
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800156void AudioMixer::disable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700157{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800158 if (mState.tracks[ mActiveTrack ].enabled != 0) {
159 mState.tracks[ mActiveTrack ].enabled = 0;
160 ALOGV("disable(%d)", mActiveTrack);
161 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700162 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700163}
164
Glenn Kastenfba380a2011-12-15 15:46:46 -0800165void AudioMixer::setActiveTrack(int track)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700166{
Glenn Kastenfba380a2011-12-15 15:46:46 -0800167 // this also catches track < TRACK0
168 track -= TRACK0;
169 assert(uint32_t(track) < MAX_NUM_TRACKS);
170 mActiveTrack = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700171}
172
173status_t AudioMixer::setParameter(int target, int name, void *value)
174{
175 int valueInt = (int)value;
176 int32_t *valueBuf = (int32_t *)value;
177
178 switch (target) {
179 case TRACK:
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700180 if (name == CHANNEL_MASK) {
181 uint32_t mask = (uint32_t)value;
182 if (mState.tracks[ mActiveTrack ].channelMask != mask) {
183 uint8_t channelCount = popcount(mask);
184 if ((channelCount <= MAX_NUM_CHANNELS) && (channelCount)) {
185 mState.tracks[ mActiveTrack ].channelMask = mask;
186 mState.tracks[ mActiveTrack ].channelCount = channelCount;
Steve Block3856b092011-10-20 11:56:00 +0100187 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700188 invalidateState(1<<mActiveTrack);
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700189 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700190 }
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700191 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700192 return NO_ERROR;
193 }
194 }
195 if (name == MAIN_BUFFER) {
196 if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
197 mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100198 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700199 invalidateState(1<<mActiveTrack);
200 }
201 return NO_ERROR;
202 }
203 if (name == AUX_BUFFER) {
204 if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
205 mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100206 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700207 invalidateState(1<<mActiveTrack);
208 }
209 return NO_ERROR;
210 }
211
212 break;
213 case RESAMPLE:
214 if (name == SAMPLE_RATE) {
215 if (valueInt > 0) {
216 track_t& track = mState.tracks[ mActiveTrack ];
217 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
Steve Block3856b092011-10-20 11:56:00 +0100218 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700219 uint32_t(valueInt));
220 invalidateState(1<<mActiveTrack);
221 }
222 return NO_ERROR;
223 }
224 }
Eric Laurent243f5f92011-02-28 16:52:51 -0800225 if (name == RESET) {
226 track_t& track = mState.tracks[ mActiveTrack ];
227 track.resetResampler();
228 invalidateState(1<<mActiveTrack);
229 return NO_ERROR;
230 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700231 break;
232 case RAMP_VOLUME:
233 case VOLUME:
234 if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) {
235 track_t& track = mState.tracks[ mActiveTrack ];
236 if (track.volume[name-VOLUME0] != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100237 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700238 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
239 track.volume[name-VOLUME0] = valueInt;
240 if (target == VOLUME) {
241 track.prevVolume[name-VOLUME0] = valueInt << 16;
242 track.volumeInc[name-VOLUME0] = 0;
243 } else {
244 int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
245 int32_t volInc = d / int32_t(mState.frameCount);
246 track.volumeInc[name-VOLUME0] = volInc;
247 if (volInc == 0) {
248 track.prevVolume[name-VOLUME0] = valueInt << 16;
249 }
250 }
251 invalidateState(1<<mActiveTrack);
252 }
253 return NO_ERROR;
254 } else if (name == AUXLEVEL) {
255 track_t& track = mState.tracks[ mActiveTrack ];
256 if (track.auxLevel != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100257 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700258 track.prevAuxLevel = track.auxLevel << 16;
259 track.auxLevel = valueInt;
260 if (target == VOLUME) {
261 track.prevAuxLevel = valueInt << 16;
262 track.auxInc = 0;
263 } else {
264 int32_t d = (valueInt<<16) - track.prevAuxLevel;
265 int32_t volInc = d / int32_t(mState.frameCount);
266 track.auxInc = volInc;
267 if (volInc == 0) {
268 track.prevAuxLevel = valueInt << 16;
269 }
270 }
271 invalidateState(1<<mActiveTrack);
272 }
273 return NO_ERROR;
274 }
275 break;
276 }
277 return BAD_VALUE;
278}
279
280bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
281{
282 if (value!=devSampleRate || resampler) {
283 if (sampleRate != value) {
284 sampleRate = value;
Glenn Kastene0feee32011-12-13 11:53:26 -0800285 if (resampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700286 resampler = AudioResampler::create(
287 format, channelCount, devSampleRate);
288 }
289 return true;
290 }
291 }
292 return false;
293}
294
295bool AudioMixer::track_t::doesResample() const
296{
Glenn Kastene0feee32011-12-13 11:53:26 -0800297 return resampler != NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700298}
299
Eric Laurent243f5f92011-02-28 16:52:51 -0800300void AudioMixer::track_t::resetResampler()
301{
Glenn Kastene0feee32011-12-13 11:53:26 -0800302 if (resampler != NULL) {
Eric Laurent243f5f92011-02-28 16:52:51 -0800303 resampler->reset();
304 }
305}
306
Mathias Agopian65ab4712010-07-14 17:59:35 -0700307inline
308void AudioMixer::track_t::adjustVolumeRamp(bool aux)
309{
310 for (int i=0 ; i<2 ; i++) {
311 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
312 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
313 volumeInc[i] = 0;
314 prevVolume[i] = volume[i]<<16;
315 }
316 }
317 if (aux) {
318 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
319 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
320 auxInc = 0;
321 prevAuxLevel = auxLevel<<16;
322 }
323 }
324}
325
326
Glenn Kastenfba380a2011-12-15 15:46:46 -0800327void AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700328{
329 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700330}
331
332
333
334void AudioMixer::process()
335{
336 mState.hook(&mState);
337}
338
339
340void AudioMixer::process__validate(state_t* state)
341{
342 LOGW_IF(!state->needsChanged,
343 "in process__validate() but nothing's invalid");
344
345 uint32_t changed = state->needsChanged;
346 state->needsChanged = 0; // clear the validation flag
347
348 // recompute which tracks are enabled / disabled
349 uint32_t enabled = 0;
350 uint32_t disabled = 0;
351 while (changed) {
352 const int i = 31 - __builtin_clz(changed);
353 const uint32_t mask = 1<<i;
354 changed &= ~mask;
355 track_t& t = state->tracks[i];
356 (t.enabled ? enabled : disabled) |= mask;
357 }
358 state->enabledTracks &= ~disabled;
359 state->enabledTracks |= enabled;
360
361 // compute everything we need...
362 int countActiveTracks = 0;
363 int all16BitsStereoNoResample = 1;
364 int resampling = 0;
365 int volumeRamp = 0;
366 uint32_t en = state->enabledTracks;
367 while (en) {
368 const int i = 31 - __builtin_clz(en);
369 en &= ~(1<<i);
370
371 countActiveTracks++;
372 track_t& t = state->tracks[i];
373 uint32_t n = 0;
374 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
375 n |= NEEDS_FORMAT_16;
376 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
377 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
378 n |= NEEDS_AUX_ENABLED;
379 }
380
381 if (t.volumeInc[0]|t.volumeInc[1]) {
382 volumeRamp = 1;
383 } else if (!t.doesResample() && t.volumeRL == 0) {
384 n |= NEEDS_MUTE_ENABLED;
385 }
386 t.needs = n;
387
388 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
389 t.hook = track__nop;
390 } else {
391 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
392 all16BitsStereoNoResample = 0;
393 }
394 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
395 all16BitsStereoNoResample = 0;
396 resampling = 1;
397 t.hook = track__genericResample;
398 } else {
399 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
400 t.hook = track__16BitsMono;
401 all16BitsStereoNoResample = 0;
402 }
403 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
404 t.hook = track__16BitsStereo;
405 }
406 }
407 }
408 }
409
410 // select the processing hooks
411 state->hook = process__nop;
412 if (countActiveTracks) {
413 if (resampling) {
414 if (!state->outputTemp) {
415 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
416 }
417 if (!state->resampleTemp) {
418 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
419 }
420 state->hook = process__genericResampling;
421 } else {
422 if (state->outputTemp) {
423 delete [] state->outputTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800424 state->outputTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700425 }
426 if (state->resampleTemp) {
427 delete [] state->resampleTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800428 state->resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700429 }
430 state->hook = process__genericNoResampling;
431 if (all16BitsStereoNoResample && !volumeRamp) {
432 if (countActiveTracks == 1) {
433 state->hook = process__OneTrack16BitsStereoNoResampling;
434 }
435 }
436 }
437 }
438
Steve Block3856b092011-10-20 11:56:00 +0100439 ALOGV("mixer configuration change: %d activeTracks (%08x) "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700440 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
441 countActiveTracks, state->enabledTracks,
442 all16BitsStereoNoResample, resampling, volumeRamp);
443
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800444 state->hook(state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700445
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800446 // Now that the volume ramp has been done, set optimal state and
447 // track hooks for subsequent mixer process
448 if (countActiveTracks) {
449 int allMuted = 1;
450 uint32_t en = state->enabledTracks;
451 while (en) {
452 const int i = 31 - __builtin_clz(en);
453 en &= ~(1<<i);
454 track_t& t = state->tracks[i];
455 if (!t.doesResample() && t.volumeRL == 0)
456 {
457 t.needs |= NEEDS_MUTE_ENABLED;
458 t.hook = track__nop;
459 } else {
460 allMuted = 0;
461 }
462 }
463 if (allMuted) {
464 state->hook = process__nop;
465 } else if (all16BitsStereoNoResample) {
466 if (countActiveTracks == 1) {
467 state->hook = process__OneTrack16BitsStereoNoResampling;
468 }
469 }
470 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700471}
472
473static inline
474int32_t mulAdd(int16_t in, int16_t v, int32_t a)
475{
476#if defined(__arm__) && !defined(__thumb__)
477 int32_t out;
478 asm( "smlabb %[out], %[in], %[v], %[a] \n"
479 : [out]"=r"(out)
480 : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
481 : );
482 return out;
483#else
484 return a + in * int32_t(v);
485#endif
486}
487
488static inline
489int32_t mul(int16_t in, int16_t v)
490{
491#if defined(__arm__) && !defined(__thumb__)
492 int32_t out;
493 asm( "smulbb %[out], %[in], %[v] \n"
494 : [out]"=r"(out)
495 : [in]"%r"(in), [v]"r"(v)
496 : );
497 return out;
498#else
499 return in * int32_t(v);
500#endif
501}
502
503static inline
504int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
505{
506#if defined(__arm__) && !defined(__thumb__)
507 int32_t out;
508 if (left) {
509 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
510 : [out]"=r"(out)
511 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
512 : );
513 } else {
514 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
515 : [out]"=r"(out)
516 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
517 : );
518 }
519 return out;
520#else
521 if (left) {
522 return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
523 } else {
524 return a + int16_t(inRL>>16) * int16_t(vRL>>16);
525 }
526#endif
527}
528
529static inline
530int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
531{
532#if defined(__arm__) && !defined(__thumb__)
533 int32_t out;
534 if (left) {
535 asm( "smulbb %[out], %[inRL], %[vRL] \n"
536 : [out]"=r"(out)
537 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
538 : );
539 } else {
540 asm( "smultt %[out], %[inRL], %[vRL] \n"
541 : [out]"=r"(out)
542 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
543 : );
544 }
545 return out;
546#else
547 if (left) {
548 return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
549 } else {
550 return int16_t(inRL>>16) * int16_t(vRL>>16);
551 }
552#endif
553}
554
555
556void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
557{
558 t->resampler->setSampleRate(t->sampleRate);
559
560 // ramp gain - resample to temp buffer and scale/mix in 2nd step
561 if (aux != NULL) {
562 // always resample with unity gain when sending to auxiliary buffer to be able
563 // to apply send level after resampling
564 // TODO: modify each resampler to support aux channel?
565 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
566 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
567 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
568 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
569 volumeRampStereo(t, out, outFrameCount, temp, aux);
570 } else {
571 volumeStereo(t, out, outFrameCount, temp, aux);
572 }
573 } else {
574 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
575 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
576 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
577 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
578 volumeRampStereo(t, out, outFrameCount, temp, aux);
579 }
580
581 // constant gain
582 else {
583 t->resampler->setVolume(t->volume[0], t->volume[1]);
584 t->resampler->resample(out, outFrameCount, t->bufferProvider);
585 }
586 }
587}
588
589void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
590{
591}
592
593void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
594{
595 int32_t vl = t->prevVolume[0];
596 int32_t vr = t->prevVolume[1];
597 const int32_t vlInc = t->volumeInc[0];
598 const int32_t vrInc = t->volumeInc[1];
599
600 //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
601 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
602 // (vl + vlInc*frameCount)/65536.0f, frameCount);
603
604 // ramp volume
605 if UNLIKELY(aux != NULL) {
606 int32_t va = t->prevAuxLevel;
607 const int32_t vaInc = t->auxInc;
608 int32_t l;
609 int32_t r;
610
611 do {
612 l = (*temp++ >> 12);
613 r = (*temp++ >> 12);
614 *out++ += (vl >> 16) * l;
615 *out++ += (vr >> 16) * r;
616 *aux++ += (va >> 17) * (l + r);
617 vl += vlInc;
618 vr += vrInc;
619 va += vaInc;
620 } while (--frameCount);
621 t->prevAuxLevel = va;
622 } else {
623 do {
624 *out++ += (vl >> 16) * (*temp++ >> 12);
625 *out++ += (vr >> 16) * (*temp++ >> 12);
626 vl += vlInc;
627 vr += vrInc;
628 } while (--frameCount);
629 }
630 t->prevVolume[0] = vl;
631 t->prevVolume[1] = vr;
632 t->adjustVolumeRamp((aux != NULL));
633}
634
635void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
636{
637 const int16_t vl = t->volume[0];
638 const int16_t vr = t->volume[1];
639
640 if UNLIKELY(aux != NULL) {
641 const int16_t va = (int16_t)t->auxLevel;
642 do {
643 int16_t l = (int16_t)(*temp++ >> 12);
644 int16_t r = (int16_t)(*temp++ >> 12);
645 out[0] = mulAdd(l, vl, out[0]);
646 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
647 out[1] = mulAdd(r, vr, out[1]);
648 out += 2;
649 aux[0] = mulAdd(a, va, aux[0]);
650 aux++;
651 } while (--frameCount);
652 } else {
653 do {
654 int16_t l = (int16_t)(*temp++ >> 12);
655 int16_t r = (int16_t)(*temp++ >> 12);
656 out[0] = mulAdd(l, vl, out[0]);
657 out[1] = mulAdd(r, vr, out[1]);
658 out += 2;
659 } while (--frameCount);
660 }
661}
662
663void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
664{
665 int16_t const *in = static_cast<int16_t const *>(t->in);
666
667 if UNLIKELY(aux != NULL) {
668 int32_t l;
669 int32_t r;
670 // ramp gain
671 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
672 int32_t vl = t->prevVolume[0];
673 int32_t vr = t->prevVolume[1];
674 int32_t va = t->prevAuxLevel;
675 const int32_t vlInc = t->volumeInc[0];
676 const int32_t vrInc = t->volumeInc[1];
677 const int32_t vaInc = t->auxInc;
678 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
679 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
680 // (vl + vlInc*frameCount)/65536.0f, frameCount);
681
682 do {
683 l = (int32_t)*in++;
684 r = (int32_t)*in++;
685 *out++ += (vl >> 16) * l;
686 *out++ += (vr >> 16) * r;
687 *aux++ += (va >> 17) * (l + r);
688 vl += vlInc;
689 vr += vrInc;
690 va += vaInc;
691 } while (--frameCount);
692
693 t->prevVolume[0] = vl;
694 t->prevVolume[1] = vr;
695 t->prevAuxLevel = va;
696 t->adjustVolumeRamp(true);
697 }
698
699 // constant gain
700 else {
701 const uint32_t vrl = t->volumeRL;
702 const int16_t va = (int16_t)t->auxLevel;
703 do {
704 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
705 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
706 in += 2;
707 out[0] = mulAddRL(1, rl, vrl, out[0]);
708 out[1] = mulAddRL(0, rl, vrl, out[1]);
709 out += 2;
710 aux[0] = mulAdd(a, va, aux[0]);
711 aux++;
712 } while (--frameCount);
713 }
714 } else {
715 // ramp gain
716 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
717 int32_t vl = t->prevVolume[0];
718 int32_t vr = t->prevVolume[1];
719 const int32_t vlInc = t->volumeInc[0];
720 const int32_t vrInc = t->volumeInc[1];
721
722 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
723 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
724 // (vl + vlInc*frameCount)/65536.0f, frameCount);
725
726 do {
727 *out++ += (vl >> 16) * (int32_t) *in++;
728 *out++ += (vr >> 16) * (int32_t) *in++;
729 vl += vlInc;
730 vr += vrInc;
731 } while (--frameCount);
732
733 t->prevVolume[0] = vl;
734 t->prevVolume[1] = vr;
735 t->adjustVolumeRamp(false);
736 }
737
738 // constant gain
739 else {
740 const uint32_t vrl = t->volumeRL;
741 do {
742 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
743 in += 2;
744 out[0] = mulAddRL(1, rl, vrl, out[0]);
745 out[1] = mulAddRL(0, rl, vrl, out[1]);
746 out += 2;
747 } while (--frameCount);
748 }
749 }
750 t->in = in;
751}
752
753void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
754{
755 int16_t const *in = static_cast<int16_t const *>(t->in);
756
757 if UNLIKELY(aux != NULL) {
758 // ramp gain
759 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
760 int32_t vl = t->prevVolume[0];
761 int32_t vr = t->prevVolume[1];
762 int32_t va = t->prevAuxLevel;
763 const int32_t vlInc = t->volumeInc[0];
764 const int32_t vrInc = t->volumeInc[1];
765 const int32_t vaInc = t->auxInc;
766
767 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
768 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
769 // (vl + vlInc*frameCount)/65536.0f, frameCount);
770
771 do {
772 int32_t l = *in++;
773 *out++ += (vl >> 16) * l;
774 *out++ += (vr >> 16) * l;
775 *aux++ += (va >> 16) * l;
776 vl += vlInc;
777 vr += vrInc;
778 va += vaInc;
779 } while (--frameCount);
780
781 t->prevVolume[0] = vl;
782 t->prevVolume[1] = vr;
783 t->prevAuxLevel = va;
784 t->adjustVolumeRamp(true);
785 }
786 // constant gain
787 else {
788 const int16_t vl = t->volume[0];
789 const int16_t vr = t->volume[1];
790 const int16_t va = (int16_t)t->auxLevel;
791 do {
792 int16_t l = *in++;
793 out[0] = mulAdd(l, vl, out[0]);
794 out[1] = mulAdd(l, vr, out[1]);
795 out += 2;
796 aux[0] = mulAdd(l, va, aux[0]);
797 aux++;
798 } while (--frameCount);
799 }
800 } else {
801 // ramp gain
802 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
803 int32_t vl = t->prevVolume[0];
804 int32_t vr = t->prevVolume[1];
805 const int32_t vlInc = t->volumeInc[0];
806 const int32_t vrInc = t->volumeInc[1];
807
808 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
809 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
810 // (vl + vlInc*frameCount)/65536.0f, frameCount);
811
812 do {
813 int32_t l = *in++;
814 *out++ += (vl >> 16) * l;
815 *out++ += (vr >> 16) * l;
816 vl += vlInc;
817 vr += vrInc;
818 } while (--frameCount);
819
820 t->prevVolume[0] = vl;
821 t->prevVolume[1] = vr;
822 t->adjustVolumeRamp(false);
823 }
824 // constant gain
825 else {
826 const int16_t vl = t->volume[0];
827 const int16_t vr = t->volume[1];
828 do {
829 int16_t l = *in++;
830 out[0] = mulAdd(l, vl, out[0]);
831 out[1] = mulAdd(l, vr, out[1]);
832 out += 2;
833 } while (--frameCount);
834 }
835 }
836 t->in = in;
837}
838
839void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
840{
841 for (size_t i=0 ; i<c ; i++) {
842 int32_t l = *sums++;
843 int32_t r = *sums++;
844 int32_t nl = l >> 12;
845 int32_t nr = r >> 12;
846 l = clamp16(nl);
847 r = clamp16(nr);
848 *out++ = (r<<16) | (l & 0xFFFF);
849 }
850}
851
852// no-op case
853void AudioMixer::process__nop(state_t* state)
854{
855 uint32_t e0 = state->enabledTracks;
856 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
857 while (e0) {
858 // process by group of tracks with same output buffer to
859 // avoid multiple memset() on same buffer
860 uint32_t e1 = e0, e2 = e0;
861 int i = 31 - __builtin_clz(e1);
862 track_t& t1 = state->tracks[i];
863 e2 &= ~(1<<i);
864 while (e2) {
865 i = 31 - __builtin_clz(e2);
866 e2 &= ~(1<<i);
867 track_t& t2 = state->tracks[i];
868 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
869 e1 &= ~(1<<i);
870 }
871 }
872 e0 &= ~(e1);
873
874 memset(t1.mainBuffer, 0, bufSize);
875
876 while (e1) {
877 i = 31 - __builtin_clz(e1);
878 e1 &= ~(1<<i);
879 t1 = state->tracks[i];
880 size_t outFrames = state->frameCount;
881 while (outFrames) {
882 t1.buffer.frameCount = outFrames;
883 t1.bufferProvider->getNextBuffer(&t1.buffer);
884 if (!t1.buffer.raw) break;
885 outFrames -= t1.buffer.frameCount;
886 t1.bufferProvider->releaseBuffer(&t1.buffer);
887 }
888 }
889 }
890}
891
892// generic code without resampling
893void AudioMixer::process__genericNoResampling(state_t* state)
894{
895 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
896
897 // acquire each track's buffer
898 uint32_t enabledTracks = state->enabledTracks;
899 uint32_t e0 = enabledTracks;
900 while (e0) {
901 const int i = 31 - __builtin_clz(e0);
902 e0 &= ~(1<<i);
903 track_t& t = state->tracks[i];
904 t.buffer.frameCount = state->frameCount;
905 t.bufferProvider->getNextBuffer(&t.buffer);
906 t.frameCount = t.buffer.frameCount;
907 t.in = t.buffer.raw;
908 // t.in == NULL can happen if the track was flushed just after having
909 // been enabled for mixing.
910 if (t.in == NULL)
911 enabledTracks &= ~(1<<i);
912 }
913
914 e0 = enabledTracks;
915 while (e0) {
916 // process by group of tracks with same output buffer to
917 // optimize cache use
918 uint32_t e1 = e0, e2 = e0;
919 int j = 31 - __builtin_clz(e1);
920 track_t& t1 = state->tracks[j];
921 e2 &= ~(1<<j);
922 while (e2) {
923 j = 31 - __builtin_clz(e2);
924 e2 &= ~(1<<j);
925 track_t& t2 = state->tracks[j];
926 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
927 e1 &= ~(1<<j);
928 }
929 }
930 e0 &= ~(e1);
931 // this assumes output 16 bits stereo, no resampling
932 int32_t *out = t1.mainBuffer;
933 size_t numFrames = 0;
934 do {
935 memset(outTemp, 0, sizeof(outTemp));
936 e2 = e1;
937 while (e2) {
938 const int i = 31 - __builtin_clz(e2);
939 e2 &= ~(1<<i);
940 track_t& t = state->tracks[i];
941 size_t outFrames = BLOCKSIZE;
942 int32_t *aux = NULL;
943 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
944 aux = t.auxBuffer + numFrames;
945 }
946 while (outFrames) {
947 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
948 if (inFrames) {
949 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
950 t.frameCount -= inFrames;
951 outFrames -= inFrames;
952 if UNLIKELY(aux != NULL) {
953 aux += inFrames;
954 }
955 }
956 if (t.frameCount == 0 && outFrames) {
957 t.bufferProvider->releaseBuffer(&t.buffer);
958 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
959 t.bufferProvider->getNextBuffer(&t.buffer);
960 t.in = t.buffer.raw;
961 if (t.in == NULL) {
962 enabledTracks &= ~(1<<i);
963 e1 &= ~(1<<i);
964 break;
965 }
966 t.frameCount = t.buffer.frameCount;
967 }
968 }
969 }
970 ditherAndClamp(out, outTemp, BLOCKSIZE);
971 out += BLOCKSIZE;
972 numFrames += BLOCKSIZE;
973 } while (numFrames < state->frameCount);
974 }
975
976 // release each track's buffer
977 e0 = enabledTracks;
978 while (e0) {
979 const int i = 31 - __builtin_clz(e0);
980 e0 &= ~(1<<i);
981 track_t& t = state->tracks[i];
982 t.bufferProvider->releaseBuffer(&t.buffer);
983 }
984}
985
986
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800987// generic code with resampling
Mathias Agopian65ab4712010-07-14 17:59:35 -0700988void AudioMixer::process__genericResampling(state_t* state)
989{
990 int32_t* const outTemp = state->outputTemp;
991 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700992
993 size_t numFrames = state->frameCount;
994
995 uint32_t e0 = state->enabledTracks;
996 while (e0) {
997 // process by group of tracks with same output buffer
998 // to optimize cache use
999 uint32_t e1 = e0, e2 = e0;
1000 int j = 31 - __builtin_clz(e1);
1001 track_t& t1 = state->tracks[j];
1002 e2 &= ~(1<<j);
1003 while (e2) {
1004 j = 31 - __builtin_clz(e2);
1005 e2 &= ~(1<<j);
1006 track_t& t2 = state->tracks[j];
1007 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
1008 e1 &= ~(1<<j);
1009 }
1010 }
1011 e0 &= ~(e1);
1012 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi2151d7b2011-02-04 15:24:34 +01001013 memset(outTemp, 0, size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001014 while (e1) {
1015 const int i = 31 - __builtin_clz(e1);
1016 e1 &= ~(1<<i);
1017 track_t& t = state->tracks[i];
1018 int32_t *aux = NULL;
1019 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
1020 aux = t.auxBuffer;
1021 }
1022
1023 // this is a little goofy, on the resampling case we don't
1024 // acquire/release the buffers because it's done by
1025 // the resampler.
1026 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
1027 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
1028 } else {
1029
1030 size_t outFrames = 0;
1031
1032 while (outFrames < numFrames) {
1033 t.buffer.frameCount = numFrames - outFrames;
1034 t.bufferProvider->getNextBuffer(&t.buffer);
1035 t.in = t.buffer.raw;
1036 // t.in == NULL can happen if the track was flushed just after having
1037 // been enabled for mixing.
1038 if (t.in == NULL) break;
1039
1040 if UNLIKELY(aux != NULL) {
1041 aux += outFrames;
1042 }
1043 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
1044 outFrames += t.buffer.frameCount;
1045 t.bufferProvider->releaseBuffer(&t.buffer);
1046 }
1047 }
1048 }
1049 ditherAndClamp(out, outTemp, numFrames);
1050 }
1051}
1052
1053// one track, 16 bits stereo without resampling is the most common case
1054void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
1055{
1056 const int i = 31 - __builtin_clz(state->enabledTracks);
1057 const track_t& t = state->tracks[i];
1058
1059 AudioBufferProvider::Buffer& b(t.buffer);
1060
1061 int32_t* out = t.mainBuffer;
1062 size_t numFrames = state->frameCount;
1063
1064 const int16_t vl = t.volume[0];
1065 const int16_t vr = t.volume[1];
1066 const uint32_t vrl = t.volumeRL;
1067 while (numFrames) {
1068 b.frameCount = numFrames;
1069 t.bufferProvider->getNextBuffer(&b);
1070 int16_t const *in = b.i16;
1071
1072 // in == NULL can happen if the track was flushed just after having
1073 // been enabled for mixing.
1074 if (in == NULL || ((unsigned long)in & 3)) {
1075 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
1076 LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
1077 in, i, t.channelCount, t.needs);
1078 return;
1079 }
1080 size_t outFrames = b.frameCount;
1081
1082 if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
1083 // volume is boosted, so we might need to clamp even though
1084 // we process only one track.
1085 do {
1086 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1087 in += 2;
1088 int32_t l = mulRL(1, rl, vrl) >> 12;
1089 int32_t r = mulRL(0, rl, vrl) >> 12;
1090 // clamping...
1091 l = clamp16(l);
1092 r = clamp16(r);
1093 *out++ = (r<<16) | (l & 0xFFFF);
1094 } while (--outFrames);
1095 } else {
1096 do {
1097 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1098 in += 2;
1099 int32_t l = mulRL(1, rl, vrl) >> 12;
1100 int32_t r = mulRL(0, rl, vrl) >> 12;
1101 *out++ = (r<<16) | (l & 0xFFFF);
1102 } while (--outFrames);
1103 }
1104 numFrames -= b.frameCount;
1105 t.bufferProvider->releaseBuffer(&b);
1106 }
1107}
1108
1109// 2 tracks is also a common case
1110// NEVER used in current implementation of process__validate()
1111// only use if the 2 tracks have the same output buffer
1112void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
1113{
1114 int i;
1115 uint32_t en = state->enabledTracks;
1116
1117 i = 31 - __builtin_clz(en);
1118 const track_t& t0 = state->tracks[i];
1119 AudioBufferProvider::Buffer& b0(t0.buffer);
1120
1121 en &= ~(1<<i);
1122 i = 31 - __builtin_clz(en);
1123 const track_t& t1 = state->tracks[i];
1124 AudioBufferProvider::Buffer& b1(t1.buffer);
1125
1126 int16_t const *in0;
1127 const int16_t vl0 = t0.volume[0];
1128 const int16_t vr0 = t0.volume[1];
1129 size_t frameCount0 = 0;
1130
1131 int16_t const *in1;
1132 const int16_t vl1 = t1.volume[0];
1133 const int16_t vr1 = t1.volume[1];
1134 size_t frameCount1 = 0;
1135
1136 //FIXME: only works if two tracks use same buffer
1137 int32_t* out = t0.mainBuffer;
1138 size_t numFrames = state->frameCount;
1139 int16_t const *buff = NULL;
1140
1141
1142 while (numFrames) {
1143
1144 if (frameCount0 == 0) {
1145 b0.frameCount = numFrames;
1146 t0.bufferProvider->getNextBuffer(&b0);
1147 if (b0.i16 == NULL) {
1148 if (buff == NULL) {
1149 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1150 }
1151 in0 = buff;
1152 b0.frameCount = numFrames;
1153 } else {
1154 in0 = b0.i16;
1155 }
1156 frameCount0 = b0.frameCount;
1157 }
1158 if (frameCount1 == 0) {
1159 b1.frameCount = numFrames;
1160 t1.bufferProvider->getNextBuffer(&b1);
1161 if (b1.i16 == NULL) {
1162 if (buff == NULL) {
1163 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1164 }
1165 in1 = buff;
1166 b1.frameCount = numFrames;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001167 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001168 in1 = b1.i16;
1169 }
1170 frameCount1 = b1.frameCount;
1171 }
1172
1173 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1174
1175 numFrames -= outFrames;
1176 frameCount0 -= outFrames;
1177 frameCount1 -= outFrames;
1178
1179 do {
1180 int32_t l0 = *in0++;
1181 int32_t r0 = *in0++;
1182 l0 = mul(l0, vl0);
1183 r0 = mul(r0, vr0);
1184 int32_t l = *in1++;
1185 int32_t r = *in1++;
1186 l = mulAdd(l, vl1, l0) >> 12;
1187 r = mulAdd(r, vr1, r0) >> 12;
1188 // clamping...
1189 l = clamp16(l);
1190 r = clamp16(r);
1191 *out++ = (r<<16) | (l & 0xFFFF);
1192 } while (--outFrames);
1193
1194 if (frameCount0 == 0) {
1195 t0.bufferProvider->releaseBuffer(&b0);
1196 }
1197 if (frameCount1 == 0) {
1198 t1.bufferProvider->releaseBuffer(&b1);
1199 }
1200 }
1201
1202 if (buff != NULL) {
1203 delete [] buff;
1204 }
1205}
1206
1207// ----------------------------------------------------------------------------
1208}; // namespace android