blob: 9da18be59ee9492f01b68856e1bd7f349938d2b1 [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{
Mathias Agopian65ab4712010-07-14 17:59:35 -070098 uint32_t names = mTrackNames;
99 uint32_t mask = 1;
100 int n = 0;
101 while (names & mask) {
102 mask <<= 1;
103 n++;
104 }
105 if (mask) {
Steve Block3856b092011-10-20 11:56:00 +0100106 ALOGV("add track (%d)", n);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700107 mTrackNames |= mask;
108 return TRACK0 + n;
109 }
110 return -1;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800111}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700112
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800113void AudioMixer::invalidateState(uint32_t mask)
114{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700115 if (mask) {
116 mState.needsChanged |= mask;
117 mState.hook = process__validate;
118 }
119 }
120
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800121void AudioMixer::deleteTrackName(int name)
122{
Mathias Agopian65ab4712010-07-14 17:59:35 -0700123 name -= TRACK0;
Glenn Kasten237a6242011-12-15 15:32:27 -0800124 assert(uint32_t(name) < MAX_NUM_TRACKS);
125 ALOGV("deleteTrackName(%d)", name);
126 track_t& track(mState.tracks[ name ]);
127 if (track.enabled != 0) {
128 track.enabled = 0;
129 invalidateState(1<<name);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700130 }
Glenn Kasten237a6242011-12-15 15:32:27 -0800131 if (track.resampler) {
132 // delete the resampler
133 delete track.resampler;
134 track.resampler = NULL;
135 track.sampleRate = mSampleRate;
136 invalidateState(1<<name);
137 }
138 track.volumeInc[0] = 0;
139 track.volumeInc[1] = 0;
140 mTrackNames &= ~(1<<name);
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800141}
Mathias Agopian65ab4712010-07-14 17:59:35 -0700142
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800143void AudioMixer::enable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700144{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800145 if (mState.tracks[ mActiveTrack ].enabled != 1) {
146 mState.tracks[ mActiveTrack ].enabled = 1;
147 ALOGV("enable(%d)", mActiveTrack);
148 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700149 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700150}
151
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800152void AudioMixer::disable()
Mathias Agopian65ab4712010-07-14 17:59:35 -0700153{
Glenn Kasten1c48c3c2011-12-15 14:54:01 -0800154 if (mState.tracks[ mActiveTrack ].enabled != 0) {
155 mState.tracks[ mActiveTrack ].enabled = 0;
156 ALOGV("disable(%d)", mActiveTrack);
157 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700158 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700159}
160
Glenn Kastenfba380a2011-12-15 15:46:46 -0800161void AudioMixer::setActiveTrack(int track)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700162{
Glenn Kastenfba380a2011-12-15 15:46:46 -0800163 // this also catches track < TRACK0
164 track -= TRACK0;
165 assert(uint32_t(track) < MAX_NUM_TRACKS);
166 mActiveTrack = track;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700167}
168
Glenn Kasten788040c2011-05-05 08:19:00 -0700169void AudioMixer::setParameter(int target, int name, void *value)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700170{
171 int valueInt = (int)value;
172 int32_t *valueBuf = (int32_t *)value;
173
174 switch (target) {
Glenn Kasten788040c2011-05-05 08:19:00 -0700175
Mathias Agopian65ab4712010-07-14 17:59:35 -0700176 case TRACK:
Glenn Kasten788040c2011-05-05 08:19:00 -0700177 switch (name) {
178 case CHANNEL_MASK: {
Jean-Michel Trivi0d255b22011-05-24 15:53:33 -0700179 uint32_t mask = (uint32_t)value;
180 if (mState.tracks[ mActiveTrack ].channelMask != mask) {
181 uint8_t channelCount = popcount(mask);
Glenn Kasten788040c2011-05-05 08:19:00 -0700182 assert((channelCount <= MAX_NUM_CHANNELS) && (channelCount));
183 mState.tracks[ mActiveTrack ].channelMask = mask;
184 mState.tracks[ mActiveTrack ].channelCount = channelCount;
185 ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
186 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700187 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700188 } break;
189 case MAIN_BUFFER:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700190 if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
191 mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100192 ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700193 invalidateState(1<<mActiveTrack);
194 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700195 break;
196 case AUX_BUFFER:
Mathias Agopian65ab4712010-07-14 17:59:35 -0700197 if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
198 mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
Steve Block3856b092011-10-20 11:56:00 +0100199 ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700200 invalidateState(1<<mActiveTrack);
201 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700202 break;
203 default:
204 // bad name
205 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700206 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700207 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700208
Mathias Agopian65ab4712010-07-14 17:59:35 -0700209 case RESAMPLE:
Glenn Kasten788040c2011-05-05 08:19:00 -0700210 switch (name) {
211 case SAMPLE_RATE: {
212 assert(valueInt > 0);
213 track_t& track = mState.tracks[ mActiveTrack ];
214 if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
215 ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
216 uint32_t(valueInt));
217 invalidateState(1<<mActiveTrack);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700218 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700219 } break;
220 case RESET: {
Eric Laurent243f5f92011-02-28 16:52:51 -0800221 track_t& track = mState.tracks[ mActiveTrack ];
222 track.resetResampler();
223 invalidateState(1<<mActiveTrack);
Glenn Kasten788040c2011-05-05 08:19:00 -0700224 } break;
225 default:
226 // bad name
227 assert(false);
Eric Laurent243f5f92011-02-28 16:52:51 -0800228 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700229 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700230
Mathias Agopian65ab4712010-07-14 17:59:35 -0700231 case RAMP_VOLUME:
232 case VOLUME:
Glenn Kasten788040c2011-05-05 08:19:00 -0700233 switch (name) {
234 case VOLUME0:
235 case VOLUME1: {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700236 track_t& track = mState.tracks[ mActiveTrack ];
237 if (track.volume[name-VOLUME0] != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100238 ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700239 track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
240 track.volume[name-VOLUME0] = valueInt;
241 if (target == VOLUME) {
242 track.prevVolume[name-VOLUME0] = valueInt << 16;
243 track.volumeInc[name-VOLUME0] = 0;
244 } else {
245 int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
246 int32_t volInc = d / int32_t(mState.frameCount);
247 track.volumeInc[name-VOLUME0] = volInc;
248 if (volInc == 0) {
249 track.prevVolume[name-VOLUME0] = valueInt << 16;
250 }
251 }
252 invalidateState(1<<mActiveTrack);
253 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700254 } break;
255 case AUXLEVEL: {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700256 track_t& track = mState.tracks[ mActiveTrack ];
257 if (track.auxLevel != valueInt) {
Steve Block3856b092011-10-20 11:56:00 +0100258 ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700259 track.prevAuxLevel = track.auxLevel << 16;
260 track.auxLevel = valueInt;
261 if (target == VOLUME) {
262 track.prevAuxLevel = valueInt << 16;
263 track.auxInc = 0;
264 } else {
265 int32_t d = (valueInt<<16) - track.prevAuxLevel;
266 int32_t volInc = d / int32_t(mState.frameCount);
267 track.auxInc = volInc;
268 if (volInc == 0) {
269 track.prevAuxLevel = valueInt << 16;
270 }
271 }
272 invalidateState(1<<mActiveTrack);
273 }
Glenn Kasten788040c2011-05-05 08:19:00 -0700274 } break;
275 default:
276 // bad name
277 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700278 }
279 break;
Glenn Kasten788040c2011-05-05 08:19:00 -0700280
281 default:
282 // bad target
283 assert(false);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700284 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700285}
286
287bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
288{
289 if (value!=devSampleRate || resampler) {
290 if (sampleRate != value) {
291 sampleRate = value;
Glenn Kastene0feee32011-12-13 11:53:26 -0800292 if (resampler == NULL) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700293 resampler = AudioResampler::create(
294 format, channelCount, devSampleRate);
295 }
296 return true;
297 }
298 }
299 return false;
300}
301
302bool AudioMixer::track_t::doesResample() const
303{
Glenn Kastene0feee32011-12-13 11:53:26 -0800304 return resampler != NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700305}
306
Eric Laurent243f5f92011-02-28 16:52:51 -0800307void AudioMixer::track_t::resetResampler()
308{
Glenn Kastene0feee32011-12-13 11:53:26 -0800309 if (resampler != NULL) {
Eric Laurent243f5f92011-02-28 16:52:51 -0800310 resampler->reset();
311 }
312}
313
Mathias Agopian65ab4712010-07-14 17:59:35 -0700314inline
315void AudioMixer::track_t::adjustVolumeRamp(bool aux)
316{
Glenn Kastenbf71f1e2011-12-13 11:52:35 -0800317 for (int i=0 ; i<MAX_NUM_CHANNELS ; i++) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700318 if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
319 ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
320 volumeInc[i] = 0;
321 prevVolume[i] = volume[i]<<16;
322 }
323 }
324 if (aux) {
325 if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
326 ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
327 auxInc = 0;
328 prevAuxLevel = auxLevel<<16;
329 }
330 }
331}
332
333
Glenn Kastenfba380a2011-12-15 15:46:46 -0800334void AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
Mathias Agopian65ab4712010-07-14 17:59:35 -0700335{
336 mState.tracks[ mActiveTrack ].bufferProvider = buffer;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700337}
338
339
340
341void AudioMixer::process()
342{
343 mState.hook(&mState);
344}
345
346
347void AudioMixer::process__validate(state_t* state)
348{
349 LOGW_IF(!state->needsChanged,
350 "in process__validate() but nothing's invalid");
351
352 uint32_t changed = state->needsChanged;
353 state->needsChanged = 0; // clear the validation flag
354
355 // recompute which tracks are enabled / disabled
356 uint32_t enabled = 0;
357 uint32_t disabled = 0;
358 while (changed) {
359 const int i = 31 - __builtin_clz(changed);
360 const uint32_t mask = 1<<i;
361 changed &= ~mask;
362 track_t& t = state->tracks[i];
363 (t.enabled ? enabled : disabled) |= mask;
364 }
365 state->enabledTracks &= ~disabled;
366 state->enabledTracks |= enabled;
367
368 // compute everything we need...
369 int countActiveTracks = 0;
370 int all16BitsStereoNoResample = 1;
371 int resampling = 0;
372 int volumeRamp = 0;
373 uint32_t en = state->enabledTracks;
374 while (en) {
375 const int i = 31 - __builtin_clz(en);
376 en &= ~(1<<i);
377
378 countActiveTracks++;
379 track_t& t = state->tracks[i];
380 uint32_t n = 0;
381 n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
382 n |= NEEDS_FORMAT_16;
383 n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
384 if (t.auxLevel != 0 && t.auxBuffer != NULL) {
385 n |= NEEDS_AUX_ENABLED;
386 }
387
388 if (t.volumeInc[0]|t.volumeInc[1]) {
389 volumeRamp = 1;
390 } else if (!t.doesResample() && t.volumeRL == 0) {
391 n |= NEEDS_MUTE_ENABLED;
392 }
393 t.needs = n;
394
395 if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
396 t.hook = track__nop;
397 } else {
398 if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
399 all16BitsStereoNoResample = 0;
400 }
401 if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
402 all16BitsStereoNoResample = 0;
403 resampling = 1;
404 t.hook = track__genericResample;
405 } else {
406 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
407 t.hook = track__16BitsMono;
408 all16BitsStereoNoResample = 0;
409 }
410 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
411 t.hook = track__16BitsStereo;
412 }
413 }
414 }
415 }
416
417 // select the processing hooks
418 state->hook = process__nop;
419 if (countActiveTracks) {
420 if (resampling) {
421 if (!state->outputTemp) {
422 state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
423 }
424 if (!state->resampleTemp) {
425 state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
426 }
427 state->hook = process__genericResampling;
428 } else {
429 if (state->outputTemp) {
430 delete [] state->outputTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800431 state->outputTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700432 }
433 if (state->resampleTemp) {
434 delete [] state->resampleTemp;
Glenn Kastene0feee32011-12-13 11:53:26 -0800435 state->resampleTemp = NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700436 }
437 state->hook = process__genericNoResampling;
438 if (all16BitsStereoNoResample && !volumeRamp) {
439 if (countActiveTracks == 1) {
440 state->hook = process__OneTrack16BitsStereoNoResampling;
441 }
442 }
443 }
444 }
445
Steve Block3856b092011-10-20 11:56:00 +0100446 ALOGV("mixer configuration change: %d activeTracks (%08x) "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700447 "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
448 countActiveTracks, state->enabledTracks,
449 all16BitsStereoNoResample, resampling, volumeRamp);
450
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800451 state->hook(state);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700452
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800453 // Now that the volume ramp has been done, set optimal state and
454 // track hooks for subsequent mixer process
455 if (countActiveTracks) {
456 int allMuted = 1;
457 uint32_t en = state->enabledTracks;
458 while (en) {
459 const int i = 31 - __builtin_clz(en);
460 en &= ~(1<<i);
461 track_t& t = state->tracks[i];
462 if (!t.doesResample() && t.volumeRL == 0)
463 {
464 t.needs |= NEEDS_MUTE_ENABLED;
465 t.hook = track__nop;
466 } else {
467 allMuted = 0;
468 }
469 }
470 if (allMuted) {
471 state->hook = process__nop;
472 } else if (all16BitsStereoNoResample) {
473 if (countActiveTracks == 1) {
474 state->hook = process__OneTrack16BitsStereoNoResampling;
475 }
476 }
477 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700478}
479
Mathias Agopian65ab4712010-07-14 17:59:35 -0700480
481void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
482{
483 t->resampler->setSampleRate(t->sampleRate);
484
485 // ramp gain - resample to temp buffer and scale/mix in 2nd step
486 if (aux != NULL) {
487 // always resample with unity gain when sending to auxiliary buffer to be able
488 // to apply send level after resampling
489 // TODO: modify each resampler to support aux channel?
490 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
491 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
492 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
Glenn Kastenf6b16782011-12-15 09:51:17 -0800493 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700494 volumeRampStereo(t, out, outFrameCount, temp, aux);
495 } else {
496 volumeStereo(t, out, outFrameCount, temp, aux);
497 }
498 } else {
Glenn Kastenf6b16782011-12-15 09:51:17 -0800499 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700500 t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
501 memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
502 t->resampler->resample(temp, outFrameCount, t->bufferProvider);
503 volumeRampStereo(t, out, outFrameCount, temp, aux);
504 }
505
506 // constant gain
507 else {
508 t->resampler->setVolume(t->volume[0], t->volume[1]);
509 t->resampler->resample(out, outFrameCount, t->bufferProvider);
510 }
511 }
512}
513
514void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
515{
516}
517
518void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
519{
520 int32_t vl = t->prevVolume[0];
521 int32_t vr = t->prevVolume[1];
522 const int32_t vlInc = t->volumeInc[0];
523 const int32_t vrInc = t->volumeInc[1];
524
525 //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
526 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
527 // (vl + vlInc*frameCount)/65536.0f, frameCount);
528
529 // ramp volume
Glenn Kastenf6b16782011-12-15 09:51:17 -0800530 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700531 int32_t va = t->prevAuxLevel;
532 const int32_t vaInc = t->auxInc;
533 int32_t l;
534 int32_t r;
535
536 do {
537 l = (*temp++ >> 12);
538 r = (*temp++ >> 12);
539 *out++ += (vl >> 16) * l;
540 *out++ += (vr >> 16) * r;
541 *aux++ += (va >> 17) * (l + r);
542 vl += vlInc;
543 vr += vrInc;
544 va += vaInc;
545 } while (--frameCount);
546 t->prevAuxLevel = va;
547 } else {
548 do {
549 *out++ += (vl >> 16) * (*temp++ >> 12);
550 *out++ += (vr >> 16) * (*temp++ >> 12);
551 vl += vlInc;
552 vr += vrInc;
553 } while (--frameCount);
554 }
555 t->prevVolume[0] = vl;
556 t->prevVolume[1] = vr;
557 t->adjustVolumeRamp((aux != NULL));
558}
559
560void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
561{
562 const int16_t vl = t->volume[0];
563 const int16_t vr = t->volume[1];
564
Glenn Kastenf6b16782011-12-15 09:51:17 -0800565 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700566 const int16_t va = (int16_t)t->auxLevel;
567 do {
568 int16_t l = (int16_t)(*temp++ >> 12);
569 int16_t r = (int16_t)(*temp++ >> 12);
570 out[0] = mulAdd(l, vl, out[0]);
571 int16_t a = (int16_t)(((int32_t)l + r) >> 1);
572 out[1] = mulAdd(r, vr, out[1]);
573 out += 2;
574 aux[0] = mulAdd(a, va, aux[0]);
575 aux++;
576 } while (--frameCount);
577 } else {
578 do {
579 int16_t l = (int16_t)(*temp++ >> 12);
580 int16_t r = (int16_t)(*temp++ >> 12);
581 out[0] = mulAdd(l, vl, out[0]);
582 out[1] = mulAdd(r, vr, out[1]);
583 out += 2;
584 } while (--frameCount);
585 }
586}
587
588void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
589{
590 int16_t const *in = static_cast<int16_t const *>(t->in);
591
Glenn Kastenf6b16782011-12-15 09:51:17 -0800592 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700593 int32_t l;
594 int32_t r;
595 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800596 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700597 int32_t vl = t->prevVolume[0];
598 int32_t vr = t->prevVolume[1];
599 int32_t va = t->prevAuxLevel;
600 const int32_t vlInc = t->volumeInc[0];
601 const int32_t vrInc = t->volumeInc[1];
602 const int32_t vaInc = t->auxInc;
603 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
604 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
605 // (vl + vlInc*frameCount)/65536.0f, frameCount);
606
607 do {
608 l = (int32_t)*in++;
609 r = (int32_t)*in++;
610 *out++ += (vl >> 16) * l;
611 *out++ += (vr >> 16) * r;
612 *aux++ += (va >> 17) * (l + r);
613 vl += vlInc;
614 vr += vrInc;
615 va += vaInc;
616 } while (--frameCount);
617
618 t->prevVolume[0] = vl;
619 t->prevVolume[1] = vr;
620 t->prevAuxLevel = va;
621 t->adjustVolumeRamp(true);
622 }
623
624 // constant gain
625 else {
626 const uint32_t vrl = t->volumeRL;
627 const int16_t va = (int16_t)t->auxLevel;
628 do {
629 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
630 int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
631 in += 2;
632 out[0] = mulAddRL(1, rl, vrl, out[0]);
633 out[1] = mulAddRL(0, rl, vrl, out[1]);
634 out += 2;
635 aux[0] = mulAdd(a, va, aux[0]);
636 aux++;
637 } while (--frameCount);
638 }
639 } else {
640 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800641 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700642 int32_t vl = t->prevVolume[0];
643 int32_t vr = t->prevVolume[1];
644 const int32_t vlInc = t->volumeInc[0];
645 const int32_t vrInc = t->volumeInc[1];
646
647 // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
648 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
649 // (vl + vlInc*frameCount)/65536.0f, frameCount);
650
651 do {
652 *out++ += (vl >> 16) * (int32_t) *in++;
653 *out++ += (vr >> 16) * (int32_t) *in++;
654 vl += vlInc;
655 vr += vrInc;
656 } while (--frameCount);
657
658 t->prevVolume[0] = vl;
659 t->prevVolume[1] = vr;
660 t->adjustVolumeRamp(false);
661 }
662
663 // constant gain
664 else {
665 const uint32_t vrl = t->volumeRL;
666 do {
667 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
668 in += 2;
669 out[0] = mulAddRL(1, rl, vrl, out[0]);
670 out[1] = mulAddRL(0, rl, vrl, out[1]);
671 out += 2;
672 } while (--frameCount);
673 }
674 }
675 t->in = in;
676}
677
678void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
679{
680 int16_t const *in = static_cast<int16_t const *>(t->in);
681
Glenn Kastenf6b16782011-12-15 09:51:17 -0800682 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700683 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800684 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700685 int32_t vl = t->prevVolume[0];
686 int32_t vr = t->prevVolume[1];
687 int32_t va = t->prevAuxLevel;
688 const int32_t vlInc = t->volumeInc[0];
689 const int32_t vrInc = t->volumeInc[1];
690 const int32_t vaInc = t->auxInc;
691
692 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
693 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
694 // (vl + vlInc*frameCount)/65536.0f, frameCount);
695
696 do {
697 int32_t l = *in++;
698 *out++ += (vl >> 16) * l;
699 *out++ += (vr >> 16) * l;
700 *aux++ += (va >> 16) * l;
701 vl += vlInc;
702 vr += vrInc;
703 va += vaInc;
704 } while (--frameCount);
705
706 t->prevVolume[0] = vl;
707 t->prevVolume[1] = vr;
708 t->prevAuxLevel = va;
709 t->adjustVolumeRamp(true);
710 }
711 // constant gain
712 else {
713 const int16_t vl = t->volume[0];
714 const int16_t vr = t->volume[1];
715 const int16_t va = (int16_t)t->auxLevel;
716 do {
717 int16_t l = *in++;
718 out[0] = mulAdd(l, vl, out[0]);
719 out[1] = mulAdd(l, vr, out[1]);
720 out += 2;
721 aux[0] = mulAdd(l, va, aux[0]);
722 aux++;
723 } while (--frameCount);
724 }
725 } else {
726 // ramp gain
Glenn Kastenf6b16782011-12-15 09:51:17 -0800727 if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700728 int32_t vl = t->prevVolume[0];
729 int32_t vr = t->prevVolume[1];
730 const int32_t vlInc = t->volumeInc[0];
731 const int32_t vrInc = t->volumeInc[1];
732
733 // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
734 // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
735 // (vl + vlInc*frameCount)/65536.0f, frameCount);
736
737 do {
738 int32_t l = *in++;
739 *out++ += (vl >> 16) * l;
740 *out++ += (vr >> 16) * l;
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 // constant gain
750 else {
751 const int16_t vl = t->volume[0];
752 const int16_t vr = t->volume[1];
753 do {
754 int16_t l = *in++;
755 out[0] = mulAdd(l, vl, out[0]);
756 out[1] = mulAdd(l, vr, out[1]);
757 out += 2;
758 } while (--frameCount);
759 }
760 }
761 t->in = in;
762}
763
Mathias Agopian65ab4712010-07-14 17:59:35 -0700764// no-op case
765void AudioMixer::process__nop(state_t* state)
766{
767 uint32_t e0 = state->enabledTracks;
768 size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
769 while (e0) {
770 // process by group of tracks with same output buffer to
771 // avoid multiple memset() on same buffer
772 uint32_t e1 = e0, e2 = e0;
773 int i = 31 - __builtin_clz(e1);
774 track_t& t1 = state->tracks[i];
775 e2 &= ~(1<<i);
776 while (e2) {
777 i = 31 - __builtin_clz(e2);
778 e2 &= ~(1<<i);
779 track_t& t2 = state->tracks[i];
Glenn Kastenf6b16782011-12-15 09:51:17 -0800780 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700781 e1 &= ~(1<<i);
782 }
783 }
784 e0 &= ~(e1);
785
786 memset(t1.mainBuffer, 0, bufSize);
787
788 while (e1) {
789 i = 31 - __builtin_clz(e1);
790 e1 &= ~(1<<i);
791 t1 = state->tracks[i];
792 size_t outFrames = state->frameCount;
793 while (outFrames) {
794 t1.buffer.frameCount = outFrames;
795 t1.bufferProvider->getNextBuffer(&t1.buffer);
796 if (!t1.buffer.raw) break;
797 outFrames -= t1.buffer.frameCount;
798 t1.bufferProvider->releaseBuffer(&t1.buffer);
799 }
800 }
801 }
802}
803
804// generic code without resampling
805void AudioMixer::process__genericNoResampling(state_t* state)
806{
807 int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
808
809 // acquire each track's buffer
810 uint32_t enabledTracks = state->enabledTracks;
811 uint32_t e0 = enabledTracks;
812 while (e0) {
813 const int i = 31 - __builtin_clz(e0);
814 e0 &= ~(1<<i);
815 track_t& t = state->tracks[i];
816 t.buffer.frameCount = state->frameCount;
817 t.bufferProvider->getNextBuffer(&t.buffer);
818 t.frameCount = t.buffer.frameCount;
819 t.in = t.buffer.raw;
820 // t.in == NULL can happen if the track was flushed just after having
821 // been enabled for mixing.
822 if (t.in == NULL)
823 enabledTracks &= ~(1<<i);
824 }
825
826 e0 = enabledTracks;
827 while (e0) {
828 // process by group of tracks with same output buffer to
829 // optimize cache use
830 uint32_t e1 = e0, e2 = e0;
831 int j = 31 - __builtin_clz(e1);
832 track_t& t1 = state->tracks[j];
833 e2 &= ~(1<<j);
834 while (e2) {
835 j = 31 - __builtin_clz(e2);
836 e2 &= ~(1<<j);
837 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -0800838 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700839 e1 &= ~(1<<j);
840 }
841 }
842 e0 &= ~(e1);
843 // this assumes output 16 bits stereo, no resampling
844 int32_t *out = t1.mainBuffer;
845 size_t numFrames = 0;
846 do {
847 memset(outTemp, 0, sizeof(outTemp));
848 e2 = e1;
849 while (e2) {
850 const int i = 31 - __builtin_clz(e2);
851 e2 &= ~(1<<i);
852 track_t& t = state->tracks[i];
853 size_t outFrames = BLOCKSIZE;
854 int32_t *aux = NULL;
Glenn Kastenf6b16782011-12-15 09:51:17 -0800855 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700856 aux = t.auxBuffer + numFrames;
857 }
858 while (outFrames) {
859 size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
860 if (inFrames) {
861 (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
862 t.frameCount -= inFrames;
863 outFrames -= inFrames;
Glenn Kastenf6b16782011-12-15 09:51:17 -0800864 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700865 aux += inFrames;
866 }
867 }
868 if (t.frameCount == 0 && outFrames) {
869 t.bufferProvider->releaseBuffer(&t.buffer);
870 t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
871 t.bufferProvider->getNextBuffer(&t.buffer);
872 t.in = t.buffer.raw;
873 if (t.in == NULL) {
874 enabledTracks &= ~(1<<i);
875 e1 &= ~(1<<i);
876 break;
877 }
878 t.frameCount = t.buffer.frameCount;
879 }
880 }
881 }
882 ditherAndClamp(out, outTemp, BLOCKSIZE);
883 out += BLOCKSIZE;
884 numFrames += BLOCKSIZE;
885 } while (numFrames < state->frameCount);
886 }
887
888 // release each track's buffer
889 e0 = enabledTracks;
890 while (e0) {
891 const int i = 31 - __builtin_clz(e0);
892 e0 &= ~(1<<i);
893 track_t& t = state->tracks[i];
894 t.bufferProvider->releaseBuffer(&t.buffer);
895 }
896}
897
898
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -0800899// generic code with resampling
Mathias Agopian65ab4712010-07-14 17:59:35 -0700900void AudioMixer::process__genericResampling(state_t* state)
901{
902 int32_t* const outTemp = state->outputTemp;
903 const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700904
905 size_t numFrames = state->frameCount;
906
907 uint32_t e0 = state->enabledTracks;
908 while (e0) {
909 // process by group of tracks with same output buffer
910 // to optimize cache use
911 uint32_t e1 = e0, e2 = e0;
912 int j = 31 - __builtin_clz(e1);
913 track_t& t1 = state->tracks[j];
914 e2 &= ~(1<<j);
915 while (e2) {
916 j = 31 - __builtin_clz(e2);
917 e2 &= ~(1<<j);
918 track_t& t2 = state->tracks[j];
Glenn Kastenf6b16782011-12-15 09:51:17 -0800919 if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700920 e1 &= ~(1<<j);
921 }
922 }
923 e0 &= ~(e1);
924 int32_t *out = t1.mainBuffer;
Yuuhi Yamaguchi2151d7b2011-02-04 15:24:34 +0100925 memset(outTemp, 0, size);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700926 while (e1) {
927 const int i = 31 - __builtin_clz(e1);
928 e1 &= ~(1<<i);
929 track_t& t = state->tracks[i];
930 int32_t *aux = NULL;
Glenn Kastenf6b16782011-12-15 09:51:17 -0800931 if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700932 aux = t.auxBuffer;
933 }
934
935 // this is a little goofy, on the resampling case we don't
936 // acquire/release the buffers because it's done by
937 // the resampler.
938 if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
939 (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
940 } else {
941
942 size_t outFrames = 0;
943
944 while (outFrames < numFrames) {
945 t.buffer.frameCount = numFrames - outFrames;
946 t.bufferProvider->getNextBuffer(&t.buffer);
947 t.in = t.buffer.raw;
948 // t.in == NULL can happen if the track was flushed just after having
949 // been enabled for mixing.
950 if (t.in == NULL) break;
951
Glenn Kastenf6b16782011-12-15 09:51:17 -0800952 if (CC_UNLIKELY(aux != NULL)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700953 aux += outFrames;
954 }
955 (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
956 outFrames += t.buffer.frameCount;
957 t.bufferProvider->releaseBuffer(&t.buffer);
958 }
959 }
960 }
961 ditherAndClamp(out, outTemp, numFrames);
962 }
963}
964
965// one track, 16 bits stereo without resampling is the most common case
966void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
967{
968 const int i = 31 - __builtin_clz(state->enabledTracks);
969 const track_t& t = state->tracks[i];
970
971 AudioBufferProvider::Buffer& b(t.buffer);
972
973 int32_t* out = t.mainBuffer;
974 size_t numFrames = state->frameCount;
975
976 const int16_t vl = t.volume[0];
977 const int16_t vr = t.volume[1];
978 const uint32_t vrl = t.volumeRL;
979 while (numFrames) {
980 b.frameCount = numFrames;
981 t.bufferProvider->getNextBuffer(&b);
982 int16_t const *in = b.i16;
983
984 // in == NULL can happen if the track was flushed just after having
985 // been enabled for mixing.
986 if (in == NULL || ((unsigned long)in & 3)) {
987 memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
988 LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
989 in, i, t.channelCount, t.needs);
990 return;
991 }
992 size_t outFrames = b.frameCount;
993
Glenn Kastenf6b16782011-12-15 09:51:17 -0800994 if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700995 // volume is boosted, so we might need to clamp even though
996 // we process only one track.
997 do {
998 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
999 in += 2;
1000 int32_t l = mulRL(1, rl, vrl) >> 12;
1001 int32_t r = mulRL(0, rl, vrl) >> 12;
1002 // clamping...
1003 l = clamp16(l);
1004 r = clamp16(r);
1005 *out++ = (r<<16) | (l & 0xFFFF);
1006 } while (--outFrames);
1007 } else {
1008 do {
1009 uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
1010 in += 2;
1011 int32_t l = mulRL(1, rl, vrl) >> 12;
1012 int32_t r = mulRL(0, rl, vrl) >> 12;
1013 *out++ = (r<<16) | (l & 0xFFFF);
1014 } while (--outFrames);
1015 }
1016 numFrames -= b.frameCount;
1017 t.bufferProvider->releaseBuffer(&b);
1018 }
1019}
1020
Glenn Kasten81a028f2011-12-15 09:53:12 -08001021#if 0
Mathias Agopian65ab4712010-07-14 17:59:35 -07001022// 2 tracks is also a common case
1023// NEVER used in current implementation of process__validate()
1024// only use if the 2 tracks have the same output buffer
1025void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
1026{
1027 int i;
1028 uint32_t en = state->enabledTracks;
1029
1030 i = 31 - __builtin_clz(en);
1031 const track_t& t0 = state->tracks[i];
1032 AudioBufferProvider::Buffer& b0(t0.buffer);
1033
1034 en &= ~(1<<i);
1035 i = 31 - __builtin_clz(en);
1036 const track_t& t1 = state->tracks[i];
1037 AudioBufferProvider::Buffer& b1(t1.buffer);
1038
1039 int16_t const *in0;
1040 const int16_t vl0 = t0.volume[0];
1041 const int16_t vr0 = t0.volume[1];
1042 size_t frameCount0 = 0;
1043
1044 int16_t const *in1;
1045 const int16_t vl1 = t1.volume[0];
1046 const int16_t vr1 = t1.volume[1];
1047 size_t frameCount1 = 0;
1048
1049 //FIXME: only works if two tracks use same buffer
1050 int32_t* out = t0.mainBuffer;
1051 size_t numFrames = state->frameCount;
1052 int16_t const *buff = NULL;
1053
1054
1055 while (numFrames) {
1056
1057 if (frameCount0 == 0) {
1058 b0.frameCount = numFrames;
1059 t0.bufferProvider->getNextBuffer(&b0);
1060 if (b0.i16 == NULL) {
1061 if (buff == NULL) {
1062 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1063 }
1064 in0 = buff;
1065 b0.frameCount = numFrames;
1066 } else {
1067 in0 = b0.i16;
1068 }
1069 frameCount0 = b0.frameCount;
1070 }
1071 if (frameCount1 == 0) {
1072 b1.frameCount = numFrames;
1073 t1.bufferProvider->getNextBuffer(&b1);
1074 if (b1.i16 == NULL) {
1075 if (buff == NULL) {
1076 buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1077 }
1078 in1 = buff;
1079 b1.frameCount = numFrames;
Glenn Kastenc5ac4cb2011-12-12 09:05:55 -08001080 } else {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001081 in1 = b1.i16;
1082 }
1083 frameCount1 = b1.frameCount;
1084 }
1085
1086 size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1087
1088 numFrames -= outFrames;
1089 frameCount0 -= outFrames;
1090 frameCount1 -= outFrames;
1091
1092 do {
1093 int32_t l0 = *in0++;
1094 int32_t r0 = *in0++;
1095 l0 = mul(l0, vl0);
1096 r0 = mul(r0, vr0);
1097 int32_t l = *in1++;
1098 int32_t r = *in1++;
1099 l = mulAdd(l, vl1, l0) >> 12;
1100 r = mulAdd(r, vr1, r0) >> 12;
1101 // clamping...
1102 l = clamp16(l);
1103 r = clamp16(r);
1104 *out++ = (r<<16) | (l & 0xFFFF);
1105 } while (--outFrames);
1106
1107 if (frameCount0 == 0) {
1108 t0.bufferProvider->releaseBuffer(&b0);
1109 }
1110 if (frameCount1 == 0) {
1111 t1.bufferProvider->releaseBuffer(&b1);
1112 }
1113 }
1114
1115 if (buff != NULL) {
1116 delete [] buff;
1117 }
1118}
Glenn Kasten81a028f2011-12-15 09:53:12 -08001119#endif
Mathias Agopian65ab4712010-07-14 17:59:35 -07001120
1121// ----------------------------------------------------------------------------
1122}; // namespace android