blob: fb1ca8766eb3724c0262cbd9167ec0f26e3f5bf7 [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>
Glenn Kastenf6b16782011-12-15 09:51:17 -080031#include <cutils/compiler.h>
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070032
33#include <system/audio.h>
34
Glenn Kasten3b21c502011-12-15 09:52:39 -080035#include <audio_utils/primitives.h>
36
Mathias Agopian65ab4712010-07-14 17:59:35 -070037#include "AudioMixer.h"
38
39namespace android {
Mathias Agopian65ab4712010-07-14 17:59:35 -070040
41// ----------------------------------------------------------------------------
42
43AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
44 : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
45{
Glenn Kasten788040c2011-05-05 08:19:00 -070046 // AudioMixer is not yet capable of multi-channel beyond stereo
47 assert(2 == MAX_NUM_CHANNELS);
Mathias Agopian65ab4712010-07-14 17:59:35 -070048 mState.enabledTracks= 0;
49 mState.needsChanged = 0;
50 mState.frameCount = frameCount;
Glenn Kastene0feee32011-12-13 11:53:26 -080051 mState.outputTemp = NULL;
52 mState.resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070053 mState.hook = process__nop;
54 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -080055 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -070056 t->needs = 0;
57 t->volume[0] = UNITY_GAIN;
58 t->volume[1] = UNITY_GAIN;
Glenn Kasten0cfd8232011-12-13 11:58:23 -080059 // no initialization needed
60 // t->prevVolume[0]
61 // t->prevVolume[1]
Mathias Agopian65ab4712010-07-14 17:59:35 -070062 t->volumeInc[0] = 0;
63 t->volumeInc[1] = 0;
64 t->auxLevel = 0;
65 t->auxInc = 0;
Glenn Kasten0cfd8232011-12-13 11:58:23 -080066 // no initialization needed
67 // t->prevAuxLevel
68 // t->frameCount
Mathias Agopian65ab4712010-07-14 17:59:35 -070069 t->channelCount = 2;
70 t->enabled = 0;
71 t->format = 16;
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -070072 t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
Mathias Agopian65ab4712010-07-14 17:59:35 -070073 t->buffer.raw = 0;
Glenn Kastene0feee32011-12-13 11:53:26 -080074 t->bufferProvider = NULL;
75 t->hook = NULL;
76 t->resampler = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070077 t->sampleRate = mSampleRate;
Glenn Kastene0feee32011-12-13 11:53:26 -080078 t->in = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -070079 t->mainBuffer = NULL;
80 t->auxBuffer = NULL;
81 t++;
82 }
83}
84
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080085AudioMixer::~AudioMixer()
86{
87 track_t* t = mState.tracks;
Glenn Kastenbf71f1e2011-12-13 11:52:35 -080088 for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080089 delete t->resampler;
90 t++;
91 }
92 delete [] mState.outputTemp;
93 delete [] mState.resampleTemp;
94}
Mathias Agopian65ab4712010-07-14 17:59:35 -070095
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -080096int AudioMixer::getTrackName()
97{
Glenn Kasten98dd5422011-12-15 14:38:29 -080098 uint32_t names = ~mTrackNames;
99 if (names != 0) {
100 int n = __builtin_ctz(names);
Steve Block3856b092011-10-20 11:56:00 +0100101 ALOGV("add track (%d)", n);
Glenn Kasten98dd5422011-12-15 14:38:29 -0800102 mTrackNames |= 1 << n;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700103 return TRACK0 + n;
104 }
105 return -1;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800106}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700107
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800108void AudioMixer::invalidateState(uint32_t mask)
109{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700110 if (mask) {
111 mState.needsChanged |= mask;
112 mState.hook = process__validate;
113 }
114 }
115
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800116void AudioMixer::deleteTrackName(int name)
117{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700118 name -= TRACK0;
Glenn Kasten237a6242011-12-15 15:32:27 -0800119 assert(uint32_t(name) < MAX_NUM_TRACKS);
120 ALOGV("deleteTrackName(%d)", name);
121 track_t& track(mState.tracks[ name ]);
122 if (track.enabled != 0) {
123 track.enabled = 0;
124 invalidateState(1<<name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700125 }
Glenn Kasten237a6242011-12-15 15:32:27 -0800126 if (track.resampler) {
127 // delete the resampler
128 delete track.resampler;
129 track.resampler = NULL;
130 track.sampleRate = mSampleRate;
131 invalidateState(1<<name);
132 }
133 track.volumeInc[0] = 0;
134 track.volumeInc[1] = 0;
135 mTrackNames &= ~(1<<name);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800136}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700137
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800138void AudioMixer::enable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700139{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800140 if (mState.tracks[ mActiveTrack ].enabled != 1) {
141 mState.tracks[ mActiveTrack ].enabled = 1;
142 ALOGV("enable(%d)", mActiveTrack);
143 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700144 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700145}
146
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800147void AudioMixer::disable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700148{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800149 if (mState.tracks[ mActiveTrack ].enabled != 0) {
150 mState.tracks[ mActiveTrack ].enabled = 0;
151 ALOGV("disable(%d)", mActiveTrack);
152 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700153 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700154}
155
Glenn Kastenfba380a2011-12-15 15:46:46 -0800156void AudioMixer::setActiveTrack(int track)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700157{
Glenn Kastenfba380a2011-12-15 15:46:46 -0800158 // this also catches track < TRACK0
159 track -= TRACK0;
160 assert(uint32_t(track) < MAX_NUM_TRACKS);
161 mActiveTrack = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700162}
163
Glenn Kasten788040c2011-05-05 08:19:00 -0700164void AudioMixer::setParameter(int target, int name, void *value)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700165{
166 int valueInt = (int)value;
167 int32_t *valueBuf = (int32_t *)value;
168
169 switch (target) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700170
Mathias Agopian65ab4712010-07-14 17:59:35 -0700171 case TRACK:
Glenn Kasten788040c2011-05-05 08:19:00 -0700172 switch (name) {
173 case CHANNEL_MASK: {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700174 uint32_t mask = (uint32_t)value;
175 if (mState.tracks[ mActiveTrack ].channelMask != mask) {
176 uint8_t channelCount = popcount(mask);
Glenn Kasten788040c2011-05-05 08:19:00 -0700177 assert((channelCount <= MAX_NUM_CHANNELS) && (channelCount));
178 mState.tracks[ mActiveTrack ].channelMask = mask;
179 mState.tracks[ mActiveTrack ].channelCount = channelCount;
180 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
181 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700182 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700183 } break;
184 case MAIN_BUFFER:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700185 if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
186 mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100187 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700188 invalidateState(1<<mActiveTrack);
189 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700190 break;
191 case AUX_BUFFER:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700192 if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
193 mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100194 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700195 invalidateState(1<<mActiveTrack);
196 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700197 break;
198 default:
199 // bad name
200 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700201 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700202 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700203
Mathias Agopian65ab4712010-07-14 17:59:35 -0700204 case RESAMPLE:
Glenn Kasten788040c2011-05-05 08:19:00 -0700205 switch (name) {
206 case SAMPLE_RATE: {
207 assert(valueInt > 0);
208 track_t& track = mState.tracks[ mActiveTrack ];
209 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
210 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
211 uint32_t(valueInt));
212 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700213 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700214 } break;
215 case RESET: {
Eric Laurent243f5f92011-02-28 16:52:51 -0800216 track_t& track = mState.tracks[ mActiveTrack ];
217 track.resetResampler();
218 invalidateState(1<<mActiveTrack);
Glenn Kasten788040c2011-05-05 08:19:00 -0700219 } break;
220 default:
221 // bad name
222 assert(false);
Eric Laurent243f5f92011-02-28 16:52:51 -0800223 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700224 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700225
Mathias Agopian65ab4712010-07-14 17:59:35 -0700226 case RAMP_VOLUME:
227 case VOLUME:
Glenn Kasten788040c2011-05-05 08:19:00 -0700228 switch (name) {
229 case VOLUME0:
230 case VOLUME1: {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700231 track_t& track = mState.tracks[ mActiveTrack ];
232 if (track.volume[name-VOLUME0] != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100233 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700234 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
235 track.volume[name-VOLUME0] = valueInt;
236 if (target == VOLUME) {
237 track.prevVolume[name-VOLUME0] = valueInt << 16;
238 track.volumeInc[name-VOLUME0] = 0;
239 } else {
240 int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
241 int32_t volInc = d / int32_t(mState.frameCount);
242 track.volumeInc[name-VOLUME0] = volInc;
243 if (volInc == 0) {
244 track.prevVolume[name-VOLUME0] = valueInt << 16;
245 }
246 }
247 invalidateState(1<<mActiveTrack);
248 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700249 } break;
250 case AUXLEVEL: {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700251 track_t& track = mState.tracks[ mActiveTrack ];
252 if (track.auxLevel != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100253 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700254 track.prevAuxLevel = track.auxLevel << 16;
255 track.auxLevel = valueInt;
256 if (target == VOLUME) {
257 track.prevAuxLevel = valueInt << 16;
258 track.auxInc = 0;
259 } else {
260 int32_t d = (valueInt<<16) - track.prevAuxLevel;
261 int32_t volInc = d / int32_t(mState.frameCount);
262 track.auxInc = volInc;
263 if (volInc == 0) {
264 track.prevAuxLevel = valueInt << 16;
265 }
266 }
267 invalidateState(1<<mActiveTrack);
268 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700269 } break;
270 default:
271 // bad name
272 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700273 }
274 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700275
276 default:
277 // bad target
278 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700279 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700280}
281
282bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
283{
284 if (value!=devSampleRate || resampler) {
285 if (sampleRate != value) {
286 sampleRate = value;
Glenn Kastene0feee32011-12-13 11:53:26 -0800287 if (resampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700288 resampler = AudioResampler::create(
289 format, channelCount, devSampleRate);
290 }
291 return true;
292 }
293 }
294 return false;
295}
296
297bool AudioMixer::track_t::doesResample() const
298{
Glenn Kastene0feee32011-12-13 11:53:26 -0800299 return resampler != NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700300}
301
Eric Laurent243f5f92011-02-28 16:52:51 -0800302void AudioMixer::track_t::resetResampler()
303{
Glenn Kastene0feee32011-12-13 11:53:26 -0800304 if (resampler != NULL) {
Eric Laurent243f5f92011-02-28 16:52:51 -0800305 resampler->reset();
306 }
307}
308
Mathias Agopian65ab4712010-07-14 17:59:35 -0700309inline
310void AudioMixer::track_t::adjustVolumeRamp(bool aux)
311{
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800312 for (int i=0 ; i<MAX_NUM_CHANNELS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700313 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
314 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
315 volumeInc[i] = 0;
316 prevVolume[i] = volume[i]<<16;
317 }
318 }
319 if (aux) {
320 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
321 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
322 auxInc = 0;
323 prevAuxLevel = auxLevel<<16;
324 }
325 }
326}
327
Eric Laurent071ccd52011-12-22 16:08:41 -0800328size_t AudioMixer::track_t::getUnreleasedFrames()
329{
330 if (resampler != NULL) {
331 return resampler->getUnreleasedFrames();
332 }
333 return 0;
334}
335
336size_t AudioMixer::getUnreleasedFrames(int name)
337{
338 name -= TRACK0;
339 if (uint32_t(name) < MAX_NUM_TRACKS) {
340 track_t& track(mState.tracks[name]);
341 return track.getUnreleasedFrames();
342 }
343 return 0;
344}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700345
Glenn Kastenfba380a2011-12-15 15:46:46 -0800346void AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700347{
348 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700349}
350
351
352
353void AudioMixer::process()
354{
355 mState.hook(&mState);
356}
357
358
359void AudioMixer::process__validate(state_t* state)
360{
361 LOGW_IF(!state->needsChanged,
362 "in process__validate() but nothing's invalid");
363
364 uint32_t changed = state->needsChanged;
365 state->needsChanged = 0; // clear the validation flag
366
367 // recompute which tracks are enabled / disabled
368 uint32_t enabled = 0;
369 uint32_t disabled = 0;
370 while (changed) {
371 const int i = 31 - __builtin_clz(changed);
372 const uint32_t mask = 1<<i;
373 changed &= ~mask;
374 track_t& t = state->tracks[i];
375 (t.enabled ? enabled : disabled) |= mask;
376 }
377 state->enabledTracks &= ~disabled;
378 state->enabledTracks |= enabled;
379
380 // compute everything we need...
381 int countActiveTracks = 0;
382 int all16BitsStereoNoResample = 1;
383 int resampling = 0;
384 int volumeRamp = 0;
385 uint32_t en = state->enabledTracks;
386 while (en) {
387 const int i = 31 - __builtin_clz(en);
388 en &= ~(1<<i);
389
390 countActiveTracks++;
391 track_t& t = state->tracks[i];
392 uint32_t n = 0;
393 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
394 n |= NEEDS_FORMAT_16;
395 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
396 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
397 n |= NEEDS_AUX_ENABLED;
398 }
399
400 if (t.volumeInc[0]|t.volumeInc[1]) {
401 volumeRamp = 1;
402 } else if (!t.doesResample() && t.volumeRL == 0) {
403 n |= NEEDS_MUTE_ENABLED;
404 }
405 t.needs = n;
406
407 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
408 t.hook = track__nop;
409 } else {
410 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
411 all16BitsStereoNoResample = 0;
412 }
413 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
414 all16BitsStereoNoResample = 0;
415 resampling = 1;
416 t.hook = track__genericResample;
417 } else {
418 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
419 t.hook = track__16BitsMono;
420 all16BitsStereoNoResample = 0;
421 }
422 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
423 t.hook = track__16BitsStereo;
424 }
425 }
426 }
427 }
428
429 // select the processing hooks
430 state->hook = process__nop;
431 if (countActiveTracks) {
432 if (resampling) {
433 if (!state->outputTemp) {
434 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
435 }
436 if (!state->resampleTemp) {
437 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
438 }
439 state->hook = process__genericResampling;
440 } else {
441 if (state->outputTemp) {
442 delete [] state->outputTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800443 state->outputTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700444 }
445 if (state->resampleTemp) {
446 delete [] state->resampleTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800447 state->resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700448 }
449 state->hook = process__genericNoResampling;
450 if (all16BitsStereoNoResample && !volumeRamp) {
451 if (countActiveTracks == 1) {
452 state->hook = process__OneTrack16BitsStereoNoResampling;
453 }
454 }
455 }
456 }
457
Steve Block3856b092011-10-20 11:56:00 +0100458 ALOGV("mixer configuration change: %d activeTracks (%08x) "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700459 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
460 countActiveTracks, state->enabledTracks,
461 all16BitsStereoNoResample, resampling, volumeRamp);
462
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800463 state->hook(state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700464
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800465 // Now that the volume ramp has been done, set optimal state and
466 // track hooks for subsequent mixer process
467 if (countActiveTracks) {
468 int allMuted = 1;
469 uint32_t en = state->enabledTracks;
470 while (en) {
471 const int i = 31 - __builtin_clz(en);
472 en &= ~(1<<i);
473 track_t& t = state->tracks[i];
474 if (!t.doesResample() && t.volumeRL == 0)
475 {
476 t.needs |= NEEDS_MUTE_ENABLED;
477 t.hook = track__nop;
478 } else {
479 allMuted = 0;
480 }
481 }
482 if (allMuted) {
483 state->hook = process__nop;
484 } else if (all16BitsStereoNoResample) {
485 if (countActiveTracks == 1) {
486 state->hook = process__OneTrack16BitsStereoNoResampling;
487 }
488 }
489 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700490}
491
Mathias Agopian65ab4712010-07-14 17:59:35 -0700492
493void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
494{
495 t->resampler->setSampleRate(t->sampleRate);
496
497 // ramp gain - resample to temp buffer and scale/mix in 2nd step
498 if (aux != NULL) {
499 // always resample with unity gain when sending to auxiliary buffer to be able
500 // to apply send level after resampling
501 // TODO: modify each resampler to support aux channel?
502 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
503 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
504 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Glenn Kastenf6b16782011-12-15 09:51:17 -0800505 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700506 volumeRampStereo(t, out, outFrameCount, temp, aux);
507 } else {
508 volumeStereo(t, out, outFrameCount, temp, aux);
509 }
510 } else {
Glenn Kastenf6b16782011-12-15 09:51:17 -0800511 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700512 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
513 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
514 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
515 volumeRampStereo(t, out, outFrameCount, temp, aux);
516 }
517
518 // constant gain
519 else {
520 t->resampler->setVolume(t->volume[0], t->volume[1]);
521 t->resampler->resample(out, outFrameCount, t->bufferProvider);
522 }
523 }
524}
525
526void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
527{
528}
529
530void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
531{
532 int32_t vl = t->prevVolume[0];
533 int32_t vr = t->prevVolume[1];
534 const int32_t vlInc = t->volumeInc[0];
535 const int32_t vrInc = t->volumeInc[1];
536
Steve Blockb8a80522011-12-20 16:23:08 +0000537 //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700538 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
539 // (vl + vlInc*frameCount)/65536.0f, frameCount);
540
541 // ramp volume
Glenn Kastenf6b16782011-12-15 09:51:17 -0800542 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700543 int32_t va = t->prevAuxLevel;
544 const int32_t vaInc = t->auxInc;
545 int32_t l;
546 int32_t r;
547
548 do {
549 l = (*temp++ >> 12);
550 r = (*temp++ >> 12);
551 *out++ += (vl >> 16) * l;
552 *out++ += (vr >> 16) * r;
553 *aux++ += (va >> 17) * (l + r);
554 vl += vlInc;
555 vr += vrInc;
556 va += vaInc;
557 } while (--frameCount);
558 t->prevAuxLevel = va;
559 } else {
560 do {
561 *out++ += (vl >> 16) * (*temp++ >> 12);
562 *out++ += (vr >> 16) * (*temp++ >> 12);
563 vl += vlInc;
564 vr += vrInc;
565 } while (--frameCount);
566 }
567 t->prevVolume[0] = vl;
568 t->prevVolume[1] = vr;
569 t->adjustVolumeRamp((aux != NULL));
570}
571
572void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
573{
574 const int16_t vl = t->volume[0];
575 const int16_t vr = t->volume[1];
576
Glenn Kastenf6b16782011-12-15 09:51:17 -0800577 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700578 const int16_t va = (int16_t)t->auxLevel;
579 do {
580 int16_t l = (int16_t)(*temp++ >> 12);
581 int16_t r = (int16_t)(*temp++ >> 12);
582 out[0] = mulAdd(l, vl, out[0]);
583 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
584 out[1] = mulAdd(r, vr, out[1]);
585 out += 2;
586 aux[0] = mulAdd(a, va, aux[0]);
587 aux++;
588 } while (--frameCount);
589 } else {
590 do {
591 int16_t l = (int16_t)(*temp++ >> 12);
592 int16_t r = (int16_t)(*temp++ >> 12);
593 out[0] = mulAdd(l, vl, out[0]);
594 out[1] = mulAdd(r, vr, out[1]);
595 out += 2;
596 } while (--frameCount);
597 }
598}
599
600void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
601{
602 int16_t const *in = static_cast<int16_t const *>(t->in);
603
Glenn Kastenf6b16782011-12-15 09:51:17 -0800604 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700605 int32_t l;
606 int32_t r;
607 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800608 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700609 int32_t vl = t->prevVolume[0];
610 int32_t vr = t->prevVolume[1];
611 int32_t va = t->prevAuxLevel;
612 const int32_t vlInc = t->volumeInc[0];
613 const int32_t vrInc = t->volumeInc[1];
614 const int32_t vaInc = t->auxInc;
Steve Blockb8a80522011-12-20 16:23:08 +0000615 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700616 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
617 // (vl + vlInc*frameCount)/65536.0f, frameCount);
618
619 do {
620 l = (int32_t)*in++;
621 r = (int32_t)*in++;
622 *out++ += (vl >> 16) * l;
623 *out++ += (vr >> 16) * r;
624 *aux++ += (va >> 17) * (l + r);
625 vl += vlInc;
626 vr += vrInc;
627 va += vaInc;
628 } while (--frameCount);
629
630 t->prevVolume[0] = vl;
631 t->prevVolume[1] = vr;
632 t->prevAuxLevel = va;
633 t->adjustVolumeRamp(true);
634 }
635
636 // constant gain
637 else {
638 const uint32_t vrl = t->volumeRL;
639 const int16_t va = (int16_t)t->auxLevel;
640 do {
641 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
642 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
643 in += 2;
644 out[0] = mulAddRL(1, rl, vrl, out[0]);
645 out[1] = mulAddRL(0, rl, vrl, out[1]);
646 out += 2;
647 aux[0] = mulAdd(a, va, aux[0]);
648 aux++;
649 } while (--frameCount);
650 }
651 } else {
652 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800653 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700654 int32_t vl = t->prevVolume[0];
655 int32_t vr = t->prevVolume[1];
656 const int32_t vlInc = t->volumeInc[0];
657 const int32_t vrInc = t->volumeInc[1];
658
Steve Blockb8a80522011-12-20 16:23:08 +0000659 // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700660 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
661 // (vl + vlInc*frameCount)/65536.0f, frameCount);
662
663 do {
664 *out++ += (vl >> 16) * (int32_t) *in++;
665 *out++ += (vr >> 16) * (int32_t) *in++;
666 vl += vlInc;
667 vr += vrInc;
668 } while (--frameCount);
669
670 t->prevVolume[0] = vl;
671 t->prevVolume[1] = vr;
672 t->adjustVolumeRamp(false);
673 }
674
675 // constant gain
676 else {
677 const uint32_t vrl = t->volumeRL;
678 do {
679 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
680 in += 2;
681 out[0] = mulAddRL(1, rl, vrl, out[0]);
682 out[1] = mulAddRL(0, rl, vrl, out[1]);
683 out += 2;
684 } while (--frameCount);
685 }
686 }
687 t->in = in;
688}
689
690void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
691{
692 int16_t const *in = static_cast<int16_t const *>(t->in);
693
Glenn Kastenf6b16782011-12-15 09:51:17 -0800694 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700695 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800696 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700697 int32_t vl = t->prevVolume[0];
698 int32_t vr = t->prevVolume[1];
699 int32_t va = t->prevAuxLevel;
700 const int32_t vlInc = t->volumeInc[0];
701 const int32_t vrInc = t->volumeInc[1];
702 const int32_t vaInc = t->auxInc;
703
Steve Blockb8a80522011-12-20 16:23:08 +0000704 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700705 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
706 // (vl + vlInc*frameCount)/65536.0f, frameCount);
707
708 do {
709 int32_t l = *in++;
710 *out++ += (vl >> 16) * l;
711 *out++ += (vr >> 16) * l;
712 *aux++ += (va >> 16) * l;
713 vl += vlInc;
714 vr += vrInc;
715 va += vaInc;
716 } while (--frameCount);
717
718 t->prevVolume[0] = vl;
719 t->prevVolume[1] = vr;
720 t->prevAuxLevel = va;
721 t->adjustVolumeRamp(true);
722 }
723 // constant gain
724 else {
725 const int16_t vl = t->volume[0];
726 const int16_t vr = t->volume[1];
727 const int16_t va = (int16_t)t->auxLevel;
728 do {
729 int16_t l = *in++;
730 out[0] = mulAdd(l, vl, out[0]);
731 out[1] = mulAdd(l, vr, out[1]);
732 out += 2;
733 aux[0] = mulAdd(l, va, aux[0]);
734 aux++;
735 } while (--frameCount);
736 }
737 } else {
738 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800739 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700740 int32_t vl = t->prevVolume[0];
741 int32_t vr = t->prevVolume[1];
742 const int32_t vlInc = t->volumeInc[0];
743 const int32_t vrInc = t->volumeInc[1];
744
Steve Blockb8a80522011-12-20 16:23:08 +0000745 // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700746 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
747 // (vl + vlInc*frameCount)/65536.0f, frameCount);
748
749 do {
750 int32_t l = *in++;
751 *out++ += (vl >> 16) * l;
752 *out++ += (vr >> 16) * l;
753 vl += vlInc;
754 vr += vrInc;
755 } while (--frameCount);
756
757 t->prevVolume[0] = vl;
758 t->prevVolume[1] = vr;
759 t->adjustVolumeRamp(false);
760 }
761 // constant gain
762 else {
763 const int16_t vl = t->volume[0];
764 const int16_t vr = t->volume[1];
765 do {
766 int16_t l = *in++;
767 out[0] = mulAdd(l, vl, out[0]);
768 out[1] = mulAdd(l, vr, out[1]);
769 out += 2;
770 } while (--frameCount);
771 }
772 }
773 t->in = in;
774}
775
Mathias Agopian65ab4712010-07-14 17:59:35 -0700776// no-op case
777void AudioMixer::process__nop(state_t* state)
778{
779 uint32_t e0 = state->enabledTracks;
780 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
781 while (e0) {
782 // process by group of tracks with same output buffer to
783 // avoid multiple memset() on same buffer
784 uint32_t e1 = e0, e2 = e0;
785 int i = 31 - __builtin_clz(e1);
786 track_t& t1 = state->tracks[i];
787 e2 &= ~(1<<i);
788 while (e2) {
789 i = 31 - __builtin_clz(e2);
790 e2 &= ~(1<<i);
791 track_t& t2 = state->tracks[i];
Glenn Kastenf6b16782011-12-15 09:51:17 -0800792 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700793 e1 &= ~(1<<i);
794 }
795 }
796 e0 &= ~(e1);
797
798 memset(t1.mainBuffer, 0, bufSize);
799
800 while (e1) {
801 i = 31 - __builtin_clz(e1);
802 e1 &= ~(1<<i);
803 t1 = state->tracks[i];
804 size_t outFrames = state->frameCount;
805 while (outFrames) {
806 t1.buffer.frameCount = outFrames;
807 t1.bufferProvider->getNextBuffer(&t1.buffer);
808 if (!t1.buffer.raw) break;
809 outFrames -= t1.buffer.frameCount;
810 t1.bufferProvider->releaseBuffer(&t1.buffer);
811 }
812 }
813 }
814}
815
816// generic code without resampling
817void AudioMixer::process__genericNoResampling(state_t* state)
818{
819 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
820
821 // acquire each track's buffer
822 uint32_t enabledTracks = state->enabledTracks;
823 uint32_t e0 = enabledTracks;
824 while (e0) {
825 const int i = 31 - __builtin_clz(e0);
826 e0 &= ~(1<<i);
827 track_t& t = state->tracks[i];
828 t.buffer.frameCount = state->frameCount;
829 t.bufferProvider->getNextBuffer(&t.buffer);
830 t.frameCount = t.buffer.frameCount;
831 t.in = t.buffer.raw;
832 // t.in == NULL can happen if the track was flushed just after having
833 // been enabled for mixing.
834 if (t.in == NULL)
835 enabledTracks &= ~(1<<i);
836 }
837
838 e0 = enabledTracks;
839 while (e0) {
840 // process by group of tracks with same output buffer to
841 // optimize cache use
842 uint32_t e1 = e0, e2 = e0;
843 int j = 31 - __builtin_clz(e1);
844 track_t& t1 = state->tracks[j];
845 e2 &= ~(1<<j);
846 while (e2) {
847 j = 31 - __builtin_clz(e2);
848 e2 &= ~(1<<j);
849 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -0800850 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700851 e1 &= ~(1<<j);
852 }
853 }
854 e0 &= ~(e1);
855 // this assumes output 16 bits stereo, no resampling
856 int32_t *out = t1.mainBuffer;
857 size_t numFrames = 0;
858 do {
859 memset(outTemp, 0, sizeof(outTemp));
860 e2 = e1;
861 while (e2) {
862 const int i = 31 - __builtin_clz(e2);
863 e2 &= ~(1<<i);
864 track_t& t = state->tracks[i];
865 size_t outFrames = BLOCKSIZE;
866 int32_t *aux = NULL;
Glenn Kastenf6b16782011-12-15 09:51:17 -0800867 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700868 aux = t.auxBuffer + numFrames;
869 }
870 while (outFrames) {
871 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
872 if (inFrames) {
873 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
874 t.frameCount -= inFrames;
875 outFrames -= inFrames;
Glenn Kastenf6b16782011-12-15 09:51:17 -0800876 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700877 aux += inFrames;
878 }
879 }
880 if (t.frameCount == 0 && outFrames) {
881 t.bufferProvider->releaseBuffer(&t.buffer);
882 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
883 t.bufferProvider->getNextBuffer(&t.buffer);
884 t.in = t.buffer.raw;
885 if (t.in == NULL) {
886 enabledTracks &= ~(1<<i);
887 e1 &= ~(1<<i);
888 break;
889 }
890 t.frameCount = t.buffer.frameCount;
891 }
892 }
893 }
894 ditherAndClamp(out, outTemp, BLOCKSIZE);
895 out += BLOCKSIZE;
896 numFrames += BLOCKSIZE;
897 } while (numFrames < state->frameCount);
898 }
899
900 // release each track's buffer
901 e0 = enabledTracks;
902 while (e0) {
903 const int i = 31 - __builtin_clz(e0);
904 e0 &= ~(1<<i);
905 track_t& t = state->tracks[i];
906 t.bufferProvider->releaseBuffer(&t.buffer);
907 }
908}
909
910
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800911// generic code with resampling
Mathias Agopian65ab4712010-07-14 17:59:35 -0700912void AudioMixer::process__genericResampling(state_t* state)
913{
914 int32_t* const outTemp = state->outputTemp;
915 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700916
917 size_t numFrames = state->frameCount;
918
919 uint32_t e0 = state->enabledTracks;
920 while (e0) {
921 // process by group of tracks with same output buffer
922 // to optimize cache use
923 uint32_t e1 = e0, e2 = e0;
924 int j = 31 - __builtin_clz(e1);
925 track_t& t1 = state->tracks[j];
926 e2 &= ~(1<<j);
927 while (e2) {
928 j = 31 - __builtin_clz(e2);
929 e2 &= ~(1<<j);
930 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -0800931 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700932 e1 &= ~(1<<j);
933 }
934 }
935 e0 &= ~(e1);
936 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi2151d7b2011-02-04 15:24:34 +0100937 memset(outTemp, 0, size);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700938 while (e1) {
939 const int i = 31 - __builtin_clz(e1);
940 e1 &= ~(1<<i);
941 track_t& t = state->tracks[i];
942 int32_t *aux = NULL;
Glenn Kastenf6b16782011-12-15 09:51:17 -0800943 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700944 aux = t.auxBuffer;
945 }
946
947 // this is a little goofy, on the resampling case we don't
948 // acquire/release the buffers because it's done by
949 // the resampler.
950 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
951 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
952 } else {
953
954 size_t outFrames = 0;
955
956 while (outFrames < numFrames) {
957 t.buffer.frameCount = numFrames - outFrames;
958 t.bufferProvider->getNextBuffer(&t.buffer);
959 t.in = t.buffer.raw;
960 // t.in == NULL can happen if the track was flushed just after having
961 // been enabled for mixing.
962 if (t.in == NULL) break;
963
Glenn Kastenf6b16782011-12-15 09:51:17 -0800964 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700965 aux += outFrames;
966 }
967 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
968 outFrames += t.buffer.frameCount;
969 t.bufferProvider->releaseBuffer(&t.buffer);
970 }
971 }
972 }
973 ditherAndClamp(out, outTemp, numFrames);
974 }
975}
976
977// one track, 16 bits stereo without resampling is the most common case
978void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
979{
980 const int i = 31 - __builtin_clz(state->enabledTracks);
981 const track_t& t = state->tracks[i];
982
983 AudioBufferProvider::Buffer& b(t.buffer);
984
985 int32_t* out = t.mainBuffer;
986 size_t numFrames = state->frameCount;
987
988 const int16_t vl = t.volume[0];
989 const int16_t vr = t.volume[1];
990 const uint32_t vrl = t.volumeRL;
991 while (numFrames) {
992 b.frameCount = numFrames;
993 t.bufferProvider->getNextBuffer(&b);
994 int16_t const *in = b.i16;
995
996 // in == NULL can happen if the track was flushed just after having
997 // been enabled for mixing.
998 if (in == NULL || ((unsigned long)in & 3)) {
999 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
1000 LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
1001 in, i, t.channelCount, t.needs);
1002 return;
1003 }
1004 size_t outFrames = b.frameCount;
1005
Glenn Kastenf6b16782011-12-15 09:51:17 -08001006 if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001007 // volume is boosted, so we might need to clamp even though
1008 // we process only one track.
1009 do {
1010 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1011 in += 2;
1012 int32_t l = mulRL(1, rl, vrl) >> 12;
1013 int32_t r = mulRL(0, rl, vrl) >> 12;
1014 // clamping...
1015 l = clamp16(l);
1016 r = clamp16(r);
1017 *out++ = (r<<16) | (l & 0xFFFF);
1018 } while (--outFrames);
1019 } else {
1020 do {
1021 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1022 in += 2;
1023 int32_t l = mulRL(1, rl, vrl) >> 12;
1024 int32_t r = mulRL(0, rl, vrl) >> 12;
1025 *out++ = (r<<16) | (l & 0xFFFF);
1026 } while (--outFrames);
1027 }
1028 numFrames -= b.frameCount;
1029 t.bufferProvider->releaseBuffer(&b);
1030 }
1031}
1032
Glenn Kasten81a028f2011-12-15 09:53:12 -08001033#if 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07001034// 2 tracks is also a common case
1035// NEVER used in current implementation of process__validate()
1036// only use if the 2 tracks have the same output buffer
1037void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
1038{
1039 int i;
1040 uint32_t en = state->enabledTracks;
1041
1042 i = 31 - __builtin_clz(en);
1043 const track_t& t0 = state->tracks[i];
1044 AudioBufferProvider::Buffer& b0(t0.buffer);
1045
1046 en &= ~(1<<i);
1047 i = 31 - __builtin_clz(en);
1048 const track_t& t1 = state->tracks[i];
1049 AudioBufferProvider::Buffer& b1(t1.buffer);
1050
1051 int16_t const *in0;
1052 const int16_t vl0 = t0.volume[0];
1053 const int16_t vr0 = t0.volume[1];
1054 size_t frameCount0 = 0;
1055
1056 int16_t const *in1;
1057 const int16_t vl1 = t1.volume[0];
1058 const int16_t vr1 = t1.volume[1];
1059 size_t frameCount1 = 0;
1060
1061 //FIXME: only works if two tracks use same buffer
1062 int32_t* out = t0.mainBuffer;
1063 size_t numFrames = state->frameCount;
1064 int16_t const *buff = NULL;
1065
1066
1067 while (numFrames) {
1068
1069 if (frameCount0 == 0) {
1070 b0.frameCount = numFrames;
1071 t0.bufferProvider->getNextBuffer(&b0);
1072 if (b0.i16 == NULL) {
1073 if (buff == NULL) {
1074 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1075 }
1076 in0 = buff;
1077 b0.frameCount = numFrames;
1078 } else {
1079 in0 = b0.i16;
1080 }
1081 frameCount0 = b0.frameCount;
1082 }
1083 if (frameCount1 == 0) {
1084 b1.frameCount = numFrames;
1085 t1.bufferProvider->getNextBuffer(&b1);
1086 if (b1.i16 == NULL) {
1087 if (buff == NULL) {
1088 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1089 }
1090 in1 = buff;
1091 b1.frameCount = numFrames;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001092 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001093 in1 = b1.i16;
1094 }
1095 frameCount1 = b1.frameCount;
1096 }
1097
1098 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1099
1100 numFrames -= outFrames;
1101 frameCount0 -= outFrames;
1102 frameCount1 -= outFrames;
1103
1104 do {
1105 int32_t l0 = *in0++;
1106 int32_t r0 = *in0++;
1107 l0 = mul(l0, vl0);
1108 r0 = mul(r0, vr0);
1109 int32_t l = *in1++;
1110 int32_t r = *in1++;
1111 l = mulAdd(l, vl1, l0) >> 12;
1112 r = mulAdd(r, vr1, r0) >> 12;
1113 // clamping...
1114 l = clamp16(l);
1115 r = clamp16(r);
1116 *out++ = (r<<16) | (l & 0xFFFF);
1117 } while (--outFrames);
1118
1119 if (frameCount0 == 0) {
1120 t0.bufferProvider->releaseBuffer(&b0);
1121 }
1122 if (frameCount1 == 0) {
1123 t1.bufferProvider->releaseBuffer(&b1);
1124 }
1125 }
1126
1127 if (buff != NULL) {
1128 delete [] buff;
1129 }
1130}
Glenn Kasten81a028f2011-12-15 09:53:12 -08001131#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001132
1133// ----------------------------------------------------------------------------
1134}; // namespace android