blob: e367b54a2b8092c856f56ef0a84bc8242ec094b8 [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{
Glenn Kasten788040c2011-05-05 08:19:00 -070051 // AudioMixer is not yet capable of multi-channel beyond stereo
52 assert(2 == MAX_NUM_CHANNELS);
Mathias Agopian65ab4712010-07-14 17:59:35 -070053 mState.enabledTracks= 0;
54 mState.needsChanged = 0;
55 mState.frameCount = frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -080056 mState.outputTemp = NULL;
57 mState.resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070058 mState.hook = process__nop;
59 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -080060 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -070061 t->needs = 0;
62 t->volume[0] = UNITY_GAIN;
63 t->volume[1] = UNITY_GAIN;
Glenn Kasten0cfd8232011-12-13 11:58:23 -080064 // no initialization needed
65 // t->prevVolume[0]
66 // t->prevVolume[1]
Mathias Agopian65ab4712010-07-14 17:59:35 -070067 t->volumeInc[0] = 0;
68 t->volumeInc[1] = 0;
69 t->auxLevel = 0;
70 t->auxInc = 0;
Glenn Kasten0cfd8232011-12-13 11:58:23 -080071 // no initialization needed
72 // t->prevAuxLevel
73 // t->frameCount
Mathias Agopian65ab4712010-07-14 17:59:35 -070074 t->channelCount = 2;
75 t->enabled = 0;
76 t->format = 16;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070077 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -070078 t->buffer.raw = 0;
Glenn Kastene0feee32011-12-13 11:53:26 -080079 t->bufferProvider = NULL;
80 t->hook = NULL;
81 t->resampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070082 t->sampleRate = mSampleRate;
Glenn Kastene0feee32011-12-13 11:53:26 -080083 t->in = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070084 t->mainBuffer = NULL;
85 t->auxBuffer = NULL;
86 t++;
87 }
88}
89
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080090AudioMixer::~AudioMixer()
91{
92 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -080093 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080094 delete t->resampler;
95 t++;
96 }
97 delete [] mState.outputTemp;
98 delete [] mState.resampleTemp;
99}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700100
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800101int AudioMixer::getTrackName()
102{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700103 uint32_t names = mTrackNames;
104 uint32_t mask = 1;
105 int n = 0;
106 while (names & mask) {
107 mask <<= 1;
108 n++;
109 }
110 if (mask) {
Steve Block3856b092011-10-20 11:56:00 +0100111 ALOGV("add track (%d)", n);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700112 mTrackNames |= mask;
113 return TRACK0 + n;
114 }
115 return -1;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800116}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700117
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800118void AudioMixer::invalidateState(uint32_t mask)
119{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700120 if (mask) {
121 mState.needsChanged |= mask;
122 mState.hook = process__validate;
123 }
124 }
125
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800126void AudioMixer::deleteTrackName(int name)
127{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700128 name -= TRACK0;
Glenn Kasten237a6242011-12-15 15:32:27 -0800129 assert(uint32_t(name) < MAX_NUM_TRACKS);
130 ALOGV("deleteTrackName(%d)", name);
131 track_t& track(mState.tracks[ name ]);
132 if (track.enabled != 0) {
133 track.enabled = 0;
134 invalidateState(1<<name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700135 }
Glenn Kasten237a6242011-12-15 15:32:27 -0800136 if (track.resampler) {
137 // delete the resampler
138 delete track.resampler;
139 track.resampler = NULL;
140 track.sampleRate = mSampleRate;
141 invalidateState(1<<name);
142 }
143 track.volumeInc[0] = 0;
144 track.volumeInc[1] = 0;
145 mTrackNames &= ~(1<<name);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800146}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700147
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800148void AudioMixer::enable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700149{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800150 if (mState.tracks[ mActiveTrack ].enabled != 1) {
151 mState.tracks[ mActiveTrack ].enabled = 1;
152 ALOGV("enable(%d)", mActiveTrack);
153 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700154 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700155}
156
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800157void AudioMixer::disable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700158{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800159 if (mState.tracks[ mActiveTrack ].enabled != 0) {
160 mState.tracks[ mActiveTrack ].enabled = 0;
161 ALOGV("disable(%d)", mActiveTrack);
162 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700163 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700164}
165
Glenn Kastenfba380a2011-12-15 15:46:46 -0800166void AudioMixer::setActiveTrack(int track)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700167{
Glenn Kastenfba380a2011-12-15 15:46:46 -0800168 // this also catches track < TRACK0
169 track -= TRACK0;
170 assert(uint32_t(track) < MAX_NUM_TRACKS);
171 mActiveTrack = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700172}
173
Glenn Kasten788040c2011-05-05 08:19:00 -0700174void AudioMixer::setParameter(int target, int name, void *value)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700175{
176 int valueInt = (int)value;
177 int32_t *valueBuf = (int32_t *)value;
178
179 switch (target) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700180
Mathias Agopian65ab4712010-07-14 17:59:35 -0700181 case TRACK:
Glenn Kasten788040c2011-05-05 08:19:00 -0700182 switch (name) {
183 case CHANNEL_MASK: {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700184 uint32_t mask = (uint32_t)value;
185 if (mState.tracks[ mActiveTrack ].channelMask != mask) {
186 uint8_t channelCount = popcount(mask);
Glenn Kasten788040c2011-05-05 08:19:00 -0700187 assert((channelCount <= MAX_NUM_CHANNELS) && (channelCount));
188 mState.tracks[ mActiveTrack ].channelMask = mask;
189 mState.tracks[ mActiveTrack ].channelCount = channelCount;
190 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
191 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700192 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700193 } break;
194 case MAIN_BUFFER:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700195 if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
196 mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100197 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700198 invalidateState(1<<mActiveTrack);
199 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700200 break;
201 case AUX_BUFFER:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700202 if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
203 mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100204 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700205 invalidateState(1<<mActiveTrack);
206 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700207 break;
208 default:
209 // bad name
210 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700211 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700212 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700213
Mathias Agopian65ab4712010-07-14 17:59:35 -0700214 case RESAMPLE:
Glenn Kasten788040c2011-05-05 08:19:00 -0700215 switch (name) {
216 case SAMPLE_RATE: {
217 assert(valueInt > 0);
218 track_t& track = mState.tracks[ mActiveTrack ];
219 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
220 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
221 uint32_t(valueInt));
222 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700223 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700224 } break;
225 case RESET: {
Eric Laurent243f5f92011-02-28 16:52:51 -0800226 track_t& track = mState.tracks[ mActiveTrack ];
227 track.resetResampler();
228 invalidateState(1<<mActiveTrack);
Glenn Kasten788040c2011-05-05 08:19:00 -0700229 } break;
230 default:
231 // bad name
232 assert(false);
Eric Laurent243f5f92011-02-28 16:52:51 -0800233 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700234 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700235
Mathias Agopian65ab4712010-07-14 17:59:35 -0700236 case RAMP_VOLUME:
237 case VOLUME:
Glenn Kasten788040c2011-05-05 08:19:00 -0700238 switch (name) {
239 case VOLUME0:
240 case VOLUME1: {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700241 track_t& track = mState.tracks[ mActiveTrack ];
242 if (track.volume[name-VOLUME0] != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100243 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700244 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
245 track.volume[name-VOLUME0] = valueInt;
246 if (target == VOLUME) {
247 track.prevVolume[name-VOLUME0] = valueInt << 16;
248 track.volumeInc[name-VOLUME0] = 0;
249 } else {
250 int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
251 int32_t volInc = d / int32_t(mState.frameCount);
252 track.volumeInc[name-VOLUME0] = volInc;
253 if (volInc == 0) {
254 track.prevVolume[name-VOLUME0] = valueInt << 16;
255 }
256 }
257 invalidateState(1<<mActiveTrack);
258 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700259 } break;
260 case AUXLEVEL: {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700261 track_t& track = mState.tracks[ mActiveTrack ];
262 if (track.auxLevel != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100263 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700264 track.prevAuxLevel = track.auxLevel << 16;
265 track.auxLevel = valueInt;
266 if (target == VOLUME) {
267 track.prevAuxLevel = valueInt << 16;
268 track.auxInc = 0;
269 } else {
270 int32_t d = (valueInt<<16) - track.prevAuxLevel;
271 int32_t volInc = d / int32_t(mState.frameCount);
272 track.auxInc = volInc;
273 if (volInc == 0) {
274 track.prevAuxLevel = valueInt << 16;
275 }
276 }
277 invalidateState(1<<mActiveTrack);
278 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700279 } break;
280 default:
281 // bad name
282 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700283 }
284 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700285
286 default:
287 // bad target
288 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700289 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700290}
291
292bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
293{
294 if (value!=devSampleRate || resampler) {
295 if (sampleRate != value) {
296 sampleRate = value;
Glenn Kastene0feee32011-12-13 11:53:26 -0800297 if (resampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700298 resampler = AudioResampler::create(
299 format, channelCount, devSampleRate);
300 }
301 return true;
302 }
303 }
304 return false;
305}
306
307bool AudioMixer::track_t::doesResample() const
308{
Glenn Kastene0feee32011-12-13 11:53:26 -0800309 return resampler != NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700310}
311
Eric Laurent243f5f92011-02-28 16:52:51 -0800312void AudioMixer::track_t::resetResampler()
313{
Glenn Kastene0feee32011-12-13 11:53:26 -0800314 if (resampler != NULL) {
Eric Laurent243f5f92011-02-28 16:52:51 -0800315 resampler->reset();
316 }
317}
318
Mathias Agopian65ab4712010-07-14 17:59:35 -0700319inline
320void AudioMixer::track_t::adjustVolumeRamp(bool aux)
321{
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800322 for (int i=0 ; i<MAX_NUM_CHANNELS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700323 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
324 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
325 volumeInc[i] = 0;
326 prevVolume[i] = volume[i]<<16;
327 }
328 }
329 if (aux) {
330 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
331 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
332 auxInc = 0;
333 prevAuxLevel = auxLevel<<16;
334 }
335 }
336}
337
338
Glenn Kastenfba380a2011-12-15 15:46:46 -0800339void AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700340{
341 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700342}
343
344
345
346void AudioMixer::process()
347{
348 mState.hook(&mState);
349}
350
351
352void AudioMixer::process__validate(state_t* state)
353{
354 LOGW_IF(!state->needsChanged,
355 "in process__validate() but nothing's invalid");
356
357 uint32_t changed = state->needsChanged;
358 state->needsChanged = 0; // clear the validation flag
359
360 // recompute which tracks are enabled / disabled
361 uint32_t enabled = 0;
362 uint32_t disabled = 0;
363 while (changed) {
364 const int i = 31 - __builtin_clz(changed);
365 const uint32_t mask = 1<<i;
366 changed &= ~mask;
367 track_t& t = state->tracks[i];
368 (t.enabled ? enabled : disabled) |= mask;
369 }
370 state->enabledTracks &= ~disabled;
371 state->enabledTracks |= enabled;
372
373 // compute everything we need...
374 int countActiveTracks = 0;
375 int all16BitsStereoNoResample = 1;
376 int resampling = 0;
377 int volumeRamp = 0;
378 uint32_t en = state->enabledTracks;
379 while (en) {
380 const int i = 31 - __builtin_clz(en);
381 en &= ~(1<<i);
382
383 countActiveTracks++;
384 track_t& t = state->tracks[i];
385 uint32_t n = 0;
386 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
387 n |= NEEDS_FORMAT_16;
388 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
389 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
390 n |= NEEDS_AUX_ENABLED;
391 }
392
393 if (t.volumeInc[0]|t.volumeInc[1]) {
394 volumeRamp = 1;
395 } else if (!t.doesResample() && t.volumeRL == 0) {
396 n |= NEEDS_MUTE_ENABLED;
397 }
398 t.needs = n;
399
400 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
401 t.hook = track__nop;
402 } else {
403 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
404 all16BitsStereoNoResample = 0;
405 }
406 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
407 all16BitsStereoNoResample = 0;
408 resampling = 1;
409 t.hook = track__genericResample;
410 } else {
411 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
412 t.hook = track__16BitsMono;
413 all16BitsStereoNoResample = 0;
414 }
415 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
416 t.hook = track__16BitsStereo;
417 }
418 }
419 }
420 }
421
422 // select the processing hooks
423 state->hook = process__nop;
424 if (countActiveTracks) {
425 if (resampling) {
426 if (!state->outputTemp) {
427 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
428 }
429 if (!state->resampleTemp) {
430 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
431 }
432 state->hook = process__genericResampling;
433 } else {
434 if (state->outputTemp) {
435 delete [] state->outputTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800436 state->outputTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700437 }
438 if (state->resampleTemp) {
439 delete [] state->resampleTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800440 state->resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700441 }
442 state->hook = process__genericNoResampling;
443 if (all16BitsStereoNoResample && !volumeRamp) {
444 if (countActiveTracks == 1) {
445 state->hook = process__OneTrack16BitsStereoNoResampling;
446 }
447 }
448 }
449 }
450
Steve Block3856b092011-10-20 11:56:00 +0100451 ALOGV("mixer configuration change: %d activeTracks (%08x) "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700452 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
453 countActiveTracks, state->enabledTracks,
454 all16BitsStereoNoResample, resampling, volumeRamp);
455
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800456 state->hook(state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700457
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800458 // Now that the volume ramp has been done, set optimal state and
459 // track hooks for subsequent mixer process
460 if (countActiveTracks) {
461 int allMuted = 1;
462 uint32_t en = state->enabledTracks;
463 while (en) {
464 const int i = 31 - __builtin_clz(en);
465 en &= ~(1<<i);
466 track_t& t = state->tracks[i];
467 if (!t.doesResample() && t.volumeRL == 0)
468 {
469 t.needs |= NEEDS_MUTE_ENABLED;
470 t.hook = track__nop;
471 } else {
472 allMuted = 0;
473 }
474 }
475 if (allMuted) {
476 state->hook = process__nop;
477 } else if (all16BitsStereoNoResample) {
478 if (countActiveTracks == 1) {
479 state->hook = process__OneTrack16BitsStereoNoResampling;
480 }
481 }
482 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700483}
484
485static inline
486int32_t mulAdd(int16_t in, int16_t v, int32_t a)
487{
488#if defined(__arm__) && !defined(__thumb__)
489 int32_t out;
490 asm( "smlabb %[out], %[in], %[v], %[a] \n"
491 : [out]"=r"(out)
492 : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
493 : );
494 return out;
495#else
496 return a + in * int32_t(v);
497#endif
498}
499
500static inline
501int32_t mul(int16_t in, int16_t v)
502{
503#if defined(__arm__) && !defined(__thumb__)
504 int32_t out;
505 asm( "smulbb %[out], %[in], %[v] \n"
506 : [out]"=r"(out)
507 : [in]"%r"(in), [v]"r"(v)
508 : );
509 return out;
510#else
511 return in * int32_t(v);
512#endif
513}
514
515static inline
516int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
517{
518#if defined(__arm__) && !defined(__thumb__)
519 int32_t out;
520 if (left) {
521 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
522 : [out]"=r"(out)
523 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
524 : );
525 } else {
526 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
527 : [out]"=r"(out)
528 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
529 : );
530 }
531 return out;
532#else
533 if (left) {
534 return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
535 } else {
536 return a + int16_t(inRL>>16) * int16_t(vRL>>16);
537 }
538#endif
539}
540
541static inline
542int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
543{
544#if defined(__arm__) && !defined(__thumb__)
545 int32_t out;
546 if (left) {
547 asm( "smulbb %[out], %[inRL], %[vRL] \n"
548 : [out]"=r"(out)
549 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
550 : );
551 } else {
552 asm( "smultt %[out], %[inRL], %[vRL] \n"
553 : [out]"=r"(out)
554 : [inRL]"%r"(inRL), [vRL]"r"(vRL)
555 : );
556 }
557 return out;
558#else
559 if (left) {
560 return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
561 } else {
562 return int16_t(inRL>>16) * int16_t(vRL>>16);
563 }
564#endif
565}
566
567
568void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
569{
570 t->resampler->setSampleRate(t->sampleRate);
571
572 // ramp gain - resample to temp buffer and scale/mix in 2nd step
573 if (aux != NULL) {
574 // always resample with unity gain when sending to auxiliary buffer to be able
575 // to apply send level after resampling
576 // TODO: modify each resampler to support aux channel?
577 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
578 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
579 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
580 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
581 volumeRampStereo(t, out, outFrameCount, temp, aux);
582 } else {
583 volumeStereo(t, out, outFrameCount, temp, aux);
584 }
585 } else {
586 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
587 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
588 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
589 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
590 volumeRampStereo(t, out, outFrameCount, temp, aux);
591 }
592
593 // constant gain
594 else {
595 t->resampler->setVolume(t->volume[0], t->volume[1]);
596 t->resampler->resample(out, outFrameCount, t->bufferProvider);
597 }
598 }
599}
600
601void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
602{
603}
604
605void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
606{
607 int32_t vl = t->prevVolume[0];
608 int32_t vr = t->prevVolume[1];
609 const int32_t vlInc = t->volumeInc[0];
610 const int32_t vrInc = t->volumeInc[1];
611
612 //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
613 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
614 // (vl + vlInc*frameCount)/65536.0f, frameCount);
615
616 // ramp volume
617 if UNLIKELY(aux != NULL) {
618 int32_t va = t->prevAuxLevel;
619 const int32_t vaInc = t->auxInc;
620 int32_t l;
621 int32_t r;
622
623 do {
624 l = (*temp++ >> 12);
625 r = (*temp++ >> 12);
626 *out++ += (vl >> 16) * l;
627 *out++ += (vr >> 16) * r;
628 *aux++ += (va >> 17) * (l + r);
629 vl += vlInc;
630 vr += vrInc;
631 va += vaInc;
632 } while (--frameCount);
633 t->prevAuxLevel = va;
634 } else {
635 do {
636 *out++ += (vl >> 16) * (*temp++ >> 12);
637 *out++ += (vr >> 16) * (*temp++ >> 12);
638 vl += vlInc;
639 vr += vrInc;
640 } while (--frameCount);
641 }
642 t->prevVolume[0] = vl;
643 t->prevVolume[1] = vr;
644 t->adjustVolumeRamp((aux != NULL));
645}
646
647void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
648{
649 const int16_t vl = t->volume[0];
650 const int16_t vr = t->volume[1];
651
652 if UNLIKELY(aux != NULL) {
653 const int16_t va = (int16_t)t->auxLevel;
654 do {
655 int16_t l = (int16_t)(*temp++ >> 12);
656 int16_t r = (int16_t)(*temp++ >> 12);
657 out[0] = mulAdd(l, vl, out[0]);
658 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
659 out[1] = mulAdd(r, vr, out[1]);
660 out += 2;
661 aux[0] = mulAdd(a, va, aux[0]);
662 aux++;
663 } while (--frameCount);
664 } else {
665 do {
666 int16_t l = (int16_t)(*temp++ >> 12);
667 int16_t r = (int16_t)(*temp++ >> 12);
668 out[0] = mulAdd(l, vl, out[0]);
669 out[1] = mulAdd(r, vr, out[1]);
670 out += 2;
671 } while (--frameCount);
672 }
673}
674
675void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
676{
677 int16_t const *in = static_cast<int16_t const *>(t->in);
678
679 if UNLIKELY(aux != NULL) {
680 int32_t l;
681 int32_t r;
682 // ramp gain
683 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
684 int32_t vl = t->prevVolume[0];
685 int32_t vr = t->prevVolume[1];
686 int32_t va = t->prevAuxLevel;
687 const int32_t vlInc = t->volumeInc[0];
688 const int32_t vrInc = t->volumeInc[1];
689 const int32_t vaInc = t->auxInc;
690 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
691 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
692 // (vl + vlInc*frameCount)/65536.0f, frameCount);
693
694 do {
695 l = (int32_t)*in++;
696 r = (int32_t)*in++;
697 *out++ += (vl >> 16) * l;
698 *out++ += (vr >> 16) * r;
699 *aux++ += (va >> 17) * (l + r);
700 vl += vlInc;
701 vr += vrInc;
702 va += vaInc;
703 } while (--frameCount);
704
705 t->prevVolume[0] = vl;
706 t->prevVolume[1] = vr;
707 t->prevAuxLevel = va;
708 t->adjustVolumeRamp(true);
709 }
710
711 // constant gain
712 else {
713 const uint32_t vrl = t->volumeRL;
714 const int16_t va = (int16_t)t->auxLevel;
715 do {
716 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
717 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
718 in += 2;
719 out[0] = mulAddRL(1, rl, vrl, out[0]);
720 out[1] = mulAddRL(0, rl, vrl, out[1]);
721 out += 2;
722 aux[0] = mulAdd(a, va, aux[0]);
723 aux++;
724 } while (--frameCount);
725 }
726 } else {
727 // ramp gain
728 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
729 int32_t vl = t->prevVolume[0];
730 int32_t vr = t->prevVolume[1];
731 const int32_t vlInc = t->volumeInc[0];
732 const int32_t vrInc = t->volumeInc[1];
733
734 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
735 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
736 // (vl + vlInc*frameCount)/65536.0f, frameCount);
737
738 do {
739 *out++ += (vl >> 16) * (int32_t) *in++;
740 *out++ += (vr >> 16) * (int32_t) *in++;
741 vl += vlInc;
742 vr += vrInc;
743 } while (--frameCount);
744
745 t->prevVolume[0] = vl;
746 t->prevVolume[1] = vr;
747 t->adjustVolumeRamp(false);
748 }
749
750 // constant gain
751 else {
752 const uint32_t vrl = t->volumeRL;
753 do {
754 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
755 in += 2;
756 out[0] = mulAddRL(1, rl, vrl, out[0]);
757 out[1] = mulAddRL(0, rl, vrl, out[1]);
758 out += 2;
759 } while (--frameCount);
760 }
761 }
762 t->in = in;
763}
764
765void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
766{
767 int16_t const *in = static_cast<int16_t const *>(t->in);
768
769 if UNLIKELY(aux != NULL) {
770 // ramp gain
771 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
772 int32_t vl = t->prevVolume[0];
773 int32_t vr = t->prevVolume[1];
774 int32_t va = t->prevAuxLevel;
775 const int32_t vlInc = t->volumeInc[0];
776 const int32_t vrInc = t->volumeInc[1];
777 const int32_t vaInc = t->auxInc;
778
779 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
780 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
781 // (vl + vlInc*frameCount)/65536.0f, frameCount);
782
783 do {
784 int32_t l = *in++;
785 *out++ += (vl >> 16) * l;
786 *out++ += (vr >> 16) * l;
787 *aux++ += (va >> 16) * l;
788 vl += vlInc;
789 vr += vrInc;
790 va += vaInc;
791 } while (--frameCount);
792
793 t->prevVolume[0] = vl;
794 t->prevVolume[1] = vr;
795 t->prevAuxLevel = va;
796 t->adjustVolumeRamp(true);
797 }
798 // constant gain
799 else {
800 const int16_t vl = t->volume[0];
801 const int16_t vr = t->volume[1];
802 const int16_t va = (int16_t)t->auxLevel;
803 do {
804 int16_t l = *in++;
805 out[0] = mulAdd(l, vl, out[0]);
806 out[1] = mulAdd(l, vr, out[1]);
807 out += 2;
808 aux[0] = mulAdd(l, va, aux[0]);
809 aux++;
810 } while (--frameCount);
811 }
812 } else {
813 // ramp gain
814 if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
815 int32_t vl = t->prevVolume[0];
816 int32_t vr = t->prevVolume[1];
817 const int32_t vlInc = t->volumeInc[0];
818 const int32_t vrInc = t->volumeInc[1];
819
820 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
821 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
822 // (vl + vlInc*frameCount)/65536.0f, frameCount);
823
824 do {
825 int32_t l = *in++;
826 *out++ += (vl >> 16) * l;
827 *out++ += (vr >> 16) * l;
828 vl += vlInc;
829 vr += vrInc;
830 } while (--frameCount);
831
832 t->prevVolume[0] = vl;
833 t->prevVolume[1] = vr;
834 t->adjustVolumeRamp(false);
835 }
836 // constant gain
837 else {
838 const int16_t vl = t->volume[0];
839 const int16_t vr = t->volume[1];
840 do {
841 int16_t l = *in++;
842 out[0] = mulAdd(l, vl, out[0]);
843 out[1] = mulAdd(l, vr, out[1]);
844 out += 2;
845 } while (--frameCount);
846 }
847 }
848 t->in = in;
849}
850
851void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
852{
853 for (size_t i=0 ; i<c ; i++) {
854 int32_t l = *sums++;
855 int32_t r = *sums++;
856 int32_t nl = l >> 12;
857 int32_t nr = r >> 12;
858 l = clamp16(nl);
859 r = clamp16(nr);
860 *out++ = (r<<16) | (l & 0xFFFF);
861 }
862}
863
864// no-op case
865void AudioMixer::process__nop(state_t* state)
866{
867 uint32_t e0 = state->enabledTracks;
868 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
869 while (e0) {
870 // process by group of tracks with same output buffer to
871 // avoid multiple memset() on same buffer
872 uint32_t e1 = e0, e2 = e0;
873 int i = 31 - __builtin_clz(e1);
874 track_t& t1 = state->tracks[i];
875 e2 &= ~(1<<i);
876 while (e2) {
877 i = 31 - __builtin_clz(e2);
878 e2 &= ~(1<<i);
879 track_t& t2 = state->tracks[i];
880 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
881 e1 &= ~(1<<i);
882 }
883 }
884 e0 &= ~(e1);
885
886 memset(t1.mainBuffer, 0, bufSize);
887
888 while (e1) {
889 i = 31 - __builtin_clz(e1);
890 e1 &= ~(1<<i);
891 t1 = state->tracks[i];
892 size_t outFrames = state->frameCount;
893 while (outFrames) {
894 t1.buffer.frameCount = outFrames;
895 t1.bufferProvider->getNextBuffer(&t1.buffer);
896 if (!t1.buffer.raw) break;
897 outFrames -= t1.buffer.frameCount;
898 t1.bufferProvider->releaseBuffer(&t1.buffer);
899 }
900 }
901 }
902}
903
904// generic code without resampling
905void AudioMixer::process__genericNoResampling(state_t* state)
906{
907 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
908
909 // acquire each track's buffer
910 uint32_t enabledTracks = state->enabledTracks;
911 uint32_t e0 = enabledTracks;
912 while (e0) {
913 const int i = 31 - __builtin_clz(e0);
914 e0 &= ~(1<<i);
915 track_t& t = state->tracks[i];
916 t.buffer.frameCount = state->frameCount;
917 t.bufferProvider->getNextBuffer(&t.buffer);
918 t.frameCount = t.buffer.frameCount;
919 t.in = t.buffer.raw;
920 // t.in == NULL can happen if the track was flushed just after having
921 // been enabled for mixing.
922 if (t.in == NULL)
923 enabledTracks &= ~(1<<i);
924 }
925
926 e0 = enabledTracks;
927 while (e0) {
928 // process by group of tracks with same output buffer to
929 // optimize cache use
930 uint32_t e1 = e0, e2 = e0;
931 int j = 31 - __builtin_clz(e1);
932 track_t& t1 = state->tracks[j];
933 e2 &= ~(1<<j);
934 while (e2) {
935 j = 31 - __builtin_clz(e2);
936 e2 &= ~(1<<j);
937 track_t& t2 = state->tracks[j];
938 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
939 e1 &= ~(1<<j);
940 }
941 }
942 e0 &= ~(e1);
943 // this assumes output 16 bits stereo, no resampling
944 int32_t *out = t1.mainBuffer;
945 size_t numFrames = 0;
946 do {
947 memset(outTemp, 0, sizeof(outTemp));
948 e2 = e1;
949 while (e2) {
950 const int i = 31 - __builtin_clz(e2);
951 e2 &= ~(1<<i);
952 track_t& t = state->tracks[i];
953 size_t outFrames = BLOCKSIZE;
954 int32_t *aux = NULL;
955 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
956 aux = t.auxBuffer + numFrames;
957 }
958 while (outFrames) {
959 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
960 if (inFrames) {
961 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
962 t.frameCount -= inFrames;
963 outFrames -= inFrames;
964 if UNLIKELY(aux != NULL) {
965 aux += inFrames;
966 }
967 }
968 if (t.frameCount == 0 && outFrames) {
969 t.bufferProvider->releaseBuffer(&t.buffer);
970 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
971 t.bufferProvider->getNextBuffer(&t.buffer);
972 t.in = t.buffer.raw;
973 if (t.in == NULL) {
974 enabledTracks &= ~(1<<i);
975 e1 &= ~(1<<i);
976 break;
977 }
978 t.frameCount = t.buffer.frameCount;
979 }
980 }
981 }
982 ditherAndClamp(out, outTemp, BLOCKSIZE);
983 out += BLOCKSIZE;
984 numFrames += BLOCKSIZE;
985 } while (numFrames < state->frameCount);
986 }
987
988 // release each track's buffer
989 e0 = enabledTracks;
990 while (e0) {
991 const int i = 31 - __builtin_clz(e0);
992 e0 &= ~(1<<i);
993 track_t& t = state->tracks[i];
994 t.bufferProvider->releaseBuffer(&t.buffer);
995 }
996}
997
998
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800999// generic code with resampling
Mathias Agopian65ab4712010-07-14 17:59:35 -07001000void AudioMixer::process__genericResampling(state_t* state)
1001{
1002 int32_t* const outTemp = state->outputTemp;
1003 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001004
1005 size_t numFrames = state->frameCount;
1006
1007 uint32_t e0 = state->enabledTracks;
1008 while (e0) {
1009 // process by group of tracks with same output buffer
1010 // to optimize cache use
1011 uint32_t e1 = e0, e2 = e0;
1012 int j = 31 - __builtin_clz(e1);
1013 track_t& t1 = state->tracks[j];
1014 e2 &= ~(1<<j);
1015 while (e2) {
1016 j = 31 - __builtin_clz(e2);
1017 e2 &= ~(1<<j);
1018 track_t& t2 = state->tracks[j];
1019 if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
1020 e1 &= ~(1<<j);
1021 }
1022 }
1023 e0 &= ~(e1);
1024 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi2151d7b2011-02-04 15:24:34 +01001025 memset(outTemp, 0, size);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001026 while (e1) {
1027 const int i = 31 - __builtin_clz(e1);
1028 e1 &= ~(1<<i);
1029 track_t& t = state->tracks[i];
1030 int32_t *aux = NULL;
1031 if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
1032 aux = t.auxBuffer;
1033 }
1034
1035 // this is a little goofy, on the resampling case we don't
1036 // acquire/release the buffers because it's done by
1037 // the resampler.
1038 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
1039 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
1040 } else {
1041
1042 size_t outFrames = 0;
1043
1044 while (outFrames < numFrames) {
1045 t.buffer.frameCount = numFrames - outFrames;
1046 t.bufferProvider->getNextBuffer(&t.buffer);
1047 t.in = t.buffer.raw;
1048 // t.in == NULL can happen if the track was flushed just after having
1049 // been enabled for mixing.
1050 if (t.in == NULL) break;
1051
1052 if UNLIKELY(aux != NULL) {
1053 aux += outFrames;
1054 }
1055 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
1056 outFrames += t.buffer.frameCount;
1057 t.bufferProvider->releaseBuffer(&t.buffer);
1058 }
1059 }
1060 }
1061 ditherAndClamp(out, outTemp, numFrames);
1062 }
1063}
1064
1065// one track, 16 bits stereo without resampling is the most common case
1066void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
1067{
1068 const int i = 31 - __builtin_clz(state->enabledTracks);
1069 const track_t& t = state->tracks[i];
1070
1071 AudioBufferProvider::Buffer& b(t.buffer);
1072
1073 int32_t* out = t.mainBuffer;
1074 size_t numFrames = state->frameCount;
1075
1076 const int16_t vl = t.volume[0];
1077 const int16_t vr = t.volume[1];
1078 const uint32_t vrl = t.volumeRL;
1079 while (numFrames) {
1080 b.frameCount = numFrames;
1081 t.bufferProvider->getNextBuffer(&b);
1082 int16_t const *in = b.i16;
1083
1084 // in == NULL can happen if the track was flushed just after having
1085 // been enabled for mixing.
1086 if (in == NULL || ((unsigned long)in & 3)) {
1087 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
1088 LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
1089 in, i, t.channelCount, t.needs);
1090 return;
1091 }
1092 size_t outFrames = b.frameCount;
1093
1094 if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
1095 // volume is boosted, so we might need to clamp even though
1096 // we process only one track.
1097 do {
1098 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1099 in += 2;
1100 int32_t l = mulRL(1, rl, vrl) >> 12;
1101 int32_t r = mulRL(0, rl, vrl) >> 12;
1102 // clamping...
1103 l = clamp16(l);
1104 r = clamp16(r);
1105 *out++ = (r<<16) | (l & 0xFFFF);
1106 } while (--outFrames);
1107 } else {
1108 do {
1109 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1110 in += 2;
1111 int32_t l = mulRL(1, rl, vrl) >> 12;
1112 int32_t r = mulRL(0, rl, vrl) >> 12;
1113 *out++ = (r<<16) | (l & 0xFFFF);
1114 } while (--outFrames);
1115 }
1116 numFrames -= b.frameCount;
1117 t.bufferProvider->releaseBuffer(&b);
1118 }
1119}
1120
1121// 2 tracks is also a common case
1122// NEVER used in current implementation of process__validate()
1123// only use if the 2 tracks have the same output buffer
1124void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
1125{
1126 int i;
1127 uint32_t en = state->enabledTracks;
1128
1129 i = 31 - __builtin_clz(en);
1130 const track_t& t0 = state->tracks[i];
1131 AudioBufferProvider::Buffer& b0(t0.buffer);
1132
1133 en &= ~(1<<i);
1134 i = 31 - __builtin_clz(en);
1135 const track_t& t1 = state->tracks[i];
1136 AudioBufferProvider::Buffer& b1(t1.buffer);
1137
1138 int16_t const *in0;
1139 const int16_t vl0 = t0.volume[0];
1140 const int16_t vr0 = t0.volume[1];
1141 size_t frameCount0 = 0;
1142
1143 int16_t const *in1;
1144 const int16_t vl1 = t1.volume[0];
1145 const int16_t vr1 = t1.volume[1];
1146 size_t frameCount1 = 0;
1147
1148 //FIXME: only works if two tracks use same buffer
1149 int32_t* out = t0.mainBuffer;
1150 size_t numFrames = state->frameCount;
1151 int16_t const *buff = NULL;
1152
1153
1154 while (numFrames) {
1155
1156 if (frameCount0 == 0) {
1157 b0.frameCount = numFrames;
1158 t0.bufferProvider->getNextBuffer(&b0);
1159 if (b0.i16 == NULL) {
1160 if (buff == NULL) {
1161 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1162 }
1163 in0 = buff;
1164 b0.frameCount = numFrames;
1165 } else {
1166 in0 = b0.i16;
1167 }
1168 frameCount0 = b0.frameCount;
1169 }
1170 if (frameCount1 == 0) {
1171 b1.frameCount = numFrames;
1172 t1.bufferProvider->getNextBuffer(&b1);
1173 if (b1.i16 == NULL) {
1174 if (buff == NULL) {
1175 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1176 }
1177 in1 = buff;
1178 b1.frameCount = numFrames;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001179 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001180 in1 = b1.i16;
1181 }
1182 frameCount1 = b1.frameCount;
1183 }
1184
1185 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1186
1187 numFrames -= outFrames;
1188 frameCount0 -= outFrames;
1189 frameCount1 -= outFrames;
1190
1191 do {
1192 int32_t l0 = *in0++;
1193 int32_t r0 = *in0++;
1194 l0 = mul(l0, vl0);
1195 r0 = mul(r0, vr0);
1196 int32_t l = *in1++;
1197 int32_t r = *in1++;
1198 l = mulAdd(l, vl1, l0) >> 12;
1199 r = mulAdd(r, vr1, r0) >> 12;
1200 // clamping...
1201 l = clamp16(l);
1202 r = clamp16(r);
1203 *out++ = (r<<16) | (l & 0xFFFF);
1204 } while (--outFrames);
1205
1206 if (frameCount0 == 0) {
1207 t0.bufferProvider->releaseBuffer(&b0);
1208 }
1209 if (frameCount1 == 0) {
1210 t1.bufferProvider->releaseBuffer(&b1);
1211 }
1212 }
1213
1214 if (buff != NULL) {
1215 delete [] buff;
1216 }
1217}
1218
1219// ----------------------------------------------------------------------------
1220}; // namespace android