19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* //device/include/server/AudioFlinger/AudioMixer.cpp 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2007, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "AudioMixer" 19105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project//#define LOG_NDEBUG 0 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdint.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Errors.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "AudioMixer.h" 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline int16_t clamp16(int32_t sample) 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((sample>>15) ^ (sample>>31)) 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sample = 0x7FFF ^ (sample>>31); 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sample; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate) 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate) 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.enabledTracks= 0; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.needsChanged = 0; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.frameCount = frameCount; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.outputTemp = 0; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.resampleTemp = 0; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.hook = process__nop; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t* t = mState.tracks; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0 ; i<32 ; i++) { 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->needs = 0; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->volume[0] = UNITY_GAIN; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->volume[1] = UNITY_GAIN; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->volumeInc[0] = 0; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->volumeInc[1] = 0; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->channelCount = 2; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->enabled = 0; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->format = 16; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->buffer.raw = 0; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->bufferProvider = 0; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->hook = 0; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->resampler = 0; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->sampleRate = mSampleRate; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->in = 0; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t++; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioMixer::~AudioMixer() 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t* t = mState.tracks; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0 ; i<32 ; i++) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete t->resampler; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t++; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete [] mState.outputTemp; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete [] mState.resampleTemp; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int AudioMixer::getTrackName() 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t names = mTrackNames; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t mask = 1; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = 0; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (names & mask) { 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mask <<= 1; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n++; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mask) { 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("add track (%d)", n); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTrackNames |= mask; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return TRACK0 + n; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void AudioMixer::invalidateState(uint32_t mask) 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mask) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.needsChanged |= mask; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.hook = process__validate; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void AudioMixer::deleteTrackName(int name) 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name -= TRACK0; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uint32_t(name) < MAX_NUM_TRACKS) { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("deleteTrackName(%d)", name); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& track(mState.tracks[ name ]); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (track.enabled != 0) { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.enabled = 0; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateState(1<<name); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (track.resampler) { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // delete the resampler 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete track.resampler; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.resampler = 0; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.sampleRate = mSampleRate; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateState(1<<name); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.volumeInc[0] = 0; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.volumeInc[1] = 0; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTrackNames &= ~(1<<name); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioMixer::enable(int name) 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (name) { 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MIXING: { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState.tracks[ mActiveTrack ].enabled != 1) { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.tracks[ mActiveTrack ].enabled = 1; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("enable(%d)", mActiveTrack); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateState(1<<mActiveTrack); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } break; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NAME_NOT_FOUND; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioMixer::disable(int name) 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (name) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MIXING: { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState.tracks[ mActiveTrack ].enabled != 0) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.tracks[ mActiveTrack ].enabled = 0; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("disable(%d)", mActiveTrack); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateState(1<<mActiveTrack); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } break; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NAME_NOT_FOUND; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioMixer::setActiveTrack(int track) 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BAD_VALUE; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mActiveTrack = track - TRACK0; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioMixer::setParameter(int target, int name, int value) 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (target) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case TRACK: 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == CHANNEL_COUNT) { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((uint32_t(value) <= MAX_NUM_CHANNELS) && (value)) { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState.tracks[ mActiveTrack ].channelCount != value) { 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.tracks[ mActiveTrack ].channelCount = value; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("setParameter(TRACK, CHANNEL_COUNT, %d)", value); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateState(1<<mActiveTrack); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case RESAMPLE: 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == SAMPLE_RATE) { 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value > 0) { 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& track = mState.tracks[ mActiveTrack ]; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (track.setResampler(uint32_t(value), mSampleRate)) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)", 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t(value)); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateState(1<<mActiveTrack); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case RAMP_VOLUME: 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case VOLUME: 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& track = mState.tracks[ mActiveTrack ]; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (track.volume[name-VOLUME0] != value) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.volume[name-VOLUME0] = value; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (target == VOLUME) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.prevVolume[name-VOLUME0] = value << 16; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.volumeInc[name-VOLUME0] = 0; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t d = (value<<16) - track.prevVolume[name-VOLUME0]; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t volInc = d / int32_t(mState.frameCount); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.volumeInc[name-VOLUME0] = volInc; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (volInc == 0) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track.prevVolume[name-VOLUME0] = value << 16; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateState(1<<mActiveTrack); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BAD_VALUE; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate) 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value!=devSampleRate || resampler) { 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sampleRate != value) { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sampleRate = value; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (resampler == 0) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resampler = AudioResampler::create( 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project format, channelCount, devSampleRate); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AudioMixer::track_t::doesResample() const 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return resampler != 0; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectinline 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::track_t::adjustVolumeRamp() 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0 ; i<2 ; i++) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) || 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) { 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project volumeInc[i] = 0; 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prevVolume[i] = volume[i]<<16; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer) 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.tracks[ mActiveTrack ].bufferProvider = buffer; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::process(void* output) 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState.hook(&mState, output); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::process__validate(state_t* state, void* output) 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW_IF(!state->needsChanged, 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "in process__validate() but nothing's invalid"); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t changed = state->needsChanged; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->needsChanged = 0; // clear the validation flag 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // recompute which tracks are enabled / disabled 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t enabled = 0; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t disabled = 0; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (changed) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(changed); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const uint32_t mask = 1<<i; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project changed &= ~mask; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& t = state->tracks[i]; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (t.enabled ? enabled : disabled) |= mask; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->enabledTracks &= ~disabled; 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->enabledTracks |= enabled; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // compute everything we need... 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int countActiveTracks = 0; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int all16BitsStereoNoResample = 1; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int resampling = 0; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int volumeRamp = 0; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t en = state->enabledTracks; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (en) { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(en); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en &= ~(1<<i); 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project countActiveTracks++; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& t = state->tracks[i]; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t n = 0; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n |= NEEDS_CHANNEL_1 + t.channelCount - 1; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n |= NEEDS_FORMAT_16; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t.volumeInc[0]|t.volumeInc[1]) { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project volumeRamp = 1; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!t.doesResample() && t.volumeRL == 0) { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n |= NEEDS_MUTE_ENABLED; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.needs = n; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) { 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.hook = track__nop; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project all16BitsStereoNoResample = 0; 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resampling = 1; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.hook = track__genericResample; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){ 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.hook = track__16BitsMono; 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project all16BitsStereoNoResample = 0; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){ 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.hook = track__16BitsStereo; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // select the processing hooks 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->hook = process__nop; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (countActiveTracks) { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (resampling) { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!state->outputTemp) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!state->resampleTemp) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->hook = process__genericResampling; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state->outputTemp) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete [] state->outputTemp; 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->outputTemp = 0; 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state->resampleTemp) { 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete [] state->resampleTemp; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->resampleTemp = 0; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->hook = process__genericNoResampling; 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (all16BitsStereoNoResample && !volumeRamp) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (countActiveTracks == 1) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->hook = process__OneTrack16BitsStereoNoResampling; 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("mixer configuration change: %d activeTracks (%08x) " 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d", 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project countActiveTracks, state->enabledTracks, 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project all16BitsStereoNoResample, resampling, volumeRamp); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->hook(state, output); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now that the volume ramp has been done, set optimal state and 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // track hooks for subsequent mixer process 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (countActiveTracks) { 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int allMuted = 1; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t en = state->enabledTracks; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (en) { 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(en); 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en &= ~(1<<i); 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& t = state->tracks[i]; 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!t.doesResample() && t.volumeRL == 0) 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.needs |= NEEDS_MUTE_ENABLED; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.hook = track__nop; 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project allMuted = 0; 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (allMuted) { 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->hook = process__nop; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!resampling && all16BitsStereoNoResample) { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (countActiveTracks == 1) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project state->hook = process__OneTrack16BitsStereoNoResampling; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t mulAdd(int16_t in, int16_t v, int32_t a) 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(__arm__) && !defined(__thumb__) 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t out; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asm( "smlabb %[out], %[in], %[v], %[a] \n" 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [out]"=r"(out) 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : ); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return out; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return a + in * int32_t(v); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t mul(int16_t in, int16_t v) 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(__arm__) && !defined(__thumb__) 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t out; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asm( "smulbb %[out], %[in], %[v] \n" 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [out]"=r"(out) 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [in]"%r"(in), [v]"r"(v) 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : ); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return out; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return in * int32_t(v); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(__arm__) && !defined(__thumb__) 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t out; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (left) { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [out]"=r"(out) 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : ); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [out]"=r"(out) 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : ); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return out; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (left) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return a + int16_t(inRL>>16) * int16_t(vRL>>16); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint32_t mulRL(int left, uint32_t inRL, uint32_t vRL) 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(__arm__) && !defined(__thumb__) 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t out; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (left) { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asm( "smulbb %[out], %[inRL], %[vRL] \n" 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [out]"=r"(out) 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [inRL]"%r"(inRL), [vRL]"r"(vRL) 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : ); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asm( "smultt %[out], %[inRL], %[vRL] \n" 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [out]"=r"(out) 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : [inRL]"%r"(inRL), [vRL]"r"(vRL) 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : ); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return out; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (left) { 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return int16_t(inRL>>16) * int16_t(vRL>>16); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp) 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->resampler->setSampleRate(t->sampleRate); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ramp gain - resample to temp buffer and scale/mix in 2nd step 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t)); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->resampler->resample(temp, outFrameCount, t->bufferProvider); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project volumeRampStereo(t, out, outFrameCount, temp); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // constant gain 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->resampler->setVolume(t->volume[0], t->volume[1]); 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->resampler->resample(out, outFrameCount, t->bufferProvider); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp) 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t vl = t->prevVolume[0]; 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t vr = t->prevVolume[1]; 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int32_t vlInc = t->volumeInc[0]; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int32_t vrInc = t->volumeInc[1]; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (vl + vlInc*frameCount)/65536.0f, frameCount); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ramp volume 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ += (vl >> 16) * (*temp++ >> 12); 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ += (vr >> 16) * (*temp++ >> 12); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vl += vlInc; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vr += vrInc; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (--frameCount); 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->prevVolume[0] = vl; 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->prevVolume[1] = vr; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->adjustVolumeRamp(); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int16_t const *in = static_cast<int16_t const *>(t->in); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ramp gain 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t vl = t->prevVolume[0]; 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t vr = t->prevVolume[1]; 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int32_t vlInc = t->volumeInc[0]; 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int32_t vrInc = t->volumeInc[1]; 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (vl + vlInc*frameCount)/65536.0f, frameCount); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ += (vl >> 16) * (int32_t) *in++; 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ += (vr >> 16) * (int32_t) *in++; 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vl += vlInc; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vr += vrInc; 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (--frameCount); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->prevVolume[0] = vl; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->prevVolume[1] = vr; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->adjustVolumeRamp(); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // constant gain 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const uint32_t vrl = t->volumeRL; 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t rl = *reinterpret_cast<uint32_t const *>(in); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in += 2; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out[0] = mulAddRL(1, rl, vrl, out[0]); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out[1] = mulAddRL(0, rl, vrl, out[1]); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out += 2; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (--frameCount); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->in = in; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int16_t const *in = static_cast<int16_t const *>(t->in); 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ramp gain 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t vl = t->prevVolume[0]; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t vr = t->prevVolume[1]; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int32_t vlInc = t->volumeInc[0]; 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int32_t vrInc = t->volumeInc[1]; 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (vl + vlInc*frameCount)/65536.0f, frameCount); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t l = *in++; 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ += (vl >> 16) * l; 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ += (vr >> 16) * l; 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vl += vlInc; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vr += vrInc; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (--frameCount); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->prevVolume[0] = vl; 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->prevVolume[1] = vr; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->adjustVolumeRamp(); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // constant gain 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int16_t vl = t->volume[0]; 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int16_t vr = t->volume[1]; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int16_t l = *in++; 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out[0] = mulAdd(l, vl, out[0]); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out[1] = mulAdd(l, vr, out[1]); 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out += 2; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (--frameCount); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->in = in; 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c) 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i=0 ; i<c ; i++) { 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t l = *sums++; 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t r = *sums++; 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t nl = l >> 12; 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t nr = r >> 12; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project l = clamp16(nl); 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r = clamp16(nr); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ = (r<<16) | (l & 0xFFFF); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// no-op case 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::process__nop(state_t* state, void* output) 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this assumes output 16 bits stereo, no resampling 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(output, 0, state->frameCount*4); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t en = state->enabledTracks; 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (en) { 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(en); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en &= ~(1<<i); 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& t = state->tracks[i]; 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t outFrames = state->frameCount; 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (outFrames) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.buffer.frameCount = outFrames; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->getNextBuffer(&t.buffer); 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!t.buffer.raw) break; 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project outFrames -= t.buffer.frameCount; 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->releaseBuffer(&t.buffer); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// generic code without resampling 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::process__genericNoResampling(state_t* state, void* output) 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32))); 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // acquire each track's buffer 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t enabledTracks = state->enabledTracks; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t en = enabledTracks; 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (en) { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(en); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en &= ~(1<<i); 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& t = state->tracks[i]; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.buffer.frameCount = state->frameCount; 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->getNextBuffer(&t.buffer); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.frameCount = t.buffer.frameCount; 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.in = t.buffer.raw; 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // t.in == NULL can happen if the track was flushed just after having 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // been enabled for mixing. 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t.in == NULL) 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enabledTracks &= ~(1<<i); 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this assumes output 16 bits stereo, no resampling 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t* out = static_cast<int32_t*>(output); 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t numFrames = state->frameCount; 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(outTemp, 0, sizeof(outTemp)); 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = enabledTracks; 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (en) { 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(en); 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en &= ~(1<<i); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& t = state->tracks[i]; 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t outFrames = BLOCKSIZE; 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (outFrames) { 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount; 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (inFrames) { 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp); 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.frameCount -= inFrames; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project outFrames -= inFrames; 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t.frameCount == 0 && outFrames) { 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->releaseBuffer(&t.buffer); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.buffer.frameCount = numFrames - (BLOCKSIZE - outFrames); 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->getNextBuffer(&t.buffer); 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.in = t.buffer.raw; 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t.in == NULL) { 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enabledTracks &= ~(1<<i); 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.frameCount = t.buffer.frameCount; 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ditherAndClamp(out, outTemp, BLOCKSIZE); 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out += BLOCKSIZE; 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numFrames -= BLOCKSIZE; 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (numFrames); 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // release each track's buffer 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = enabledTracks; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (en) { 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(en); 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en &= ~(1<<i); 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& t = state->tracks[i]; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->releaseBuffer(&t.buffer); 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// generic code with resampling 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::process__genericResampling(state_t* state, void* output) 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t* const outTemp = state->outputTemp; 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount; 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(outTemp, 0, size); 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t* out = static_cast<int32_t*>(output); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t numFrames = state->frameCount; 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t en = state->enabledTracks; 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (en) { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(en); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en &= ~(1<<i); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project track_t& t = state->tracks[i]; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this is a little goofy, on the resampling case we don't 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // acquire/release the buffers because it's done by 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the resampler. 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (t.hook)(&t, outTemp, numFrames, state->resampleTemp); 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t outFrames = numFrames; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (outFrames) { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.buffer.frameCount = outFrames; 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->getNextBuffer(&t.buffer); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.in = t.buffer.raw; 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // t.in == NULL can happen if the track was flushed just after having 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // been enabled for mixing. 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t.in == NULL) break; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (t.hook)(&t, outTemp + (numFrames-outFrames)*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project outFrames -= t.buffer.frameCount; 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->releaseBuffer(&t.buffer); 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ditherAndClamp(out, outTemp, numFrames); 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// one track, 16 bits stereo without resampling is the most common case 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, void* output) 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int i = 31 - __builtin_clz(state->enabledTracks); 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const track_t& t = state->tracks[i]; 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioBufferProvider::Buffer& b(t.buffer); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t* out = static_cast<int32_t*>(output); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t numFrames = state->frameCount; 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int16_t vl = t.volume[0]; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int16_t vr = t.volume[1]; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const uint32_t vrl = t.volumeRL; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (numFrames) { 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.frameCount = numFrames; 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->getNextBuffer(&b); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int16_t const *in = b.i16; 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // in == NULL can happen if the track was flushed just after having 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // been enabled for mixing. 783105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (in == NULL || ((unsigned long)in & 3)) { 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t)); 785105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x", 786105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project in, i, t.channelCount, t.needs); 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t outFrames = b.frameCount; 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) { 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // volume is boosted, so we might need to clamp even though 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we process only one track. 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t rl = *reinterpret_cast<uint32_t const *>(in); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in += 2; 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t l = mulRL(1, rl, vrl) >> 12; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t r = mulRL(0, rl, vrl) >> 12; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // clamping... 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project l = clamp16(l); 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r = clamp16(r); 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ = (r<<16) | (l & 0xFFFF); 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (--outFrames); 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t rl = *reinterpret_cast<uint32_t const *>(in); 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in += 2; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t l = mulRL(1, rl, vrl) >> 12; 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t r = mulRL(0, rl, vrl) >> 12; 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ = (r<<16) | (l & 0xFFFF); 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (--outFrames); 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numFrames -= b.frameCount; 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.bufferProvider->releaseBuffer(&b); 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// 2 tracks is also a common case 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state, void* output) 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i; 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t en = state->enabledTracks; 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i = 31 - __builtin_clz(en); 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const track_t& t0 = state->tracks[i]; 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioBufferProvider::Buffer& b0(t0.buffer); 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en &= ~(1<<i); 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i = 31 - __builtin_clz(en); 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const track_t& t1 = state->tracks[i]; 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioBufferProvider::Buffer& b1(t1.buffer); 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int16_t const *in0; 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int16_t vl0 = t0.volume[0]; 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int16_t vr0 = t0.volume[1]; 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t frameCount0 = 0; 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int16_t const *in1; 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int16_t vl1 = t1.volume[0]; 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int16_t vr1 = t1.volume[1]; 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t frameCount1 = 0; 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t* out = static_cast<int32_t*>(output); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t numFrames = state->frameCount; 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int16_t const *buff = NULL; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (numFrames) { 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frameCount0 == 0) { 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b0.frameCount = numFrames; 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t0.bufferProvider->getNextBuffer(&b0); 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (b0.i16 == NULL) { 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buff == NULL) { 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in0 = buff; 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b0.frameCount = numFrames; 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in0 = b0.i16; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project frameCount0 = b0.frameCount; 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frameCount1 == 0) { 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b1.frameCount = numFrames; 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t1.bufferProvider->getNextBuffer(&b1); 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (b1.i16 == NULL) { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buff == NULL) { 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in1 = buff; 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b1.frameCount = numFrames; 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in1 = b1.i16; 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project frameCount1 = b1.frameCount; 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1; 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numFrames -= outFrames; 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project frameCount0 -= outFrames; 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project frameCount1 -= outFrames; 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t l0 = *in0++; 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t r0 = *in0++; 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project l0 = mul(l0, vl0); 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r0 = mul(r0, vr0); 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t l = *in1++; 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int32_t r = *in1++; 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project l = mulAdd(l, vl1, l0) >> 12; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r = mulAdd(r, vr1, r0) >> 12; 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // clamping... 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project l = clamp16(l); 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project r = clamp16(r); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *out++ = (r<<16) | (l & 0xFFFF); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (--outFrames); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frameCount0 == 0) { 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t0.bufferProvider->releaseBuffer(&b0); 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frameCount1 == 0) { 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t1.bufferProvider->releaseBuffer(&b1); 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buff != NULL) { 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete [] buff; 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 916