1135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent/* //device/servers/AudioFlinger/AudioCoefInterpolator.cpp 2135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** 3135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** Copyright 2008, The Android Open Source Project 4135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** 5135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** Licensed under the Apache License, Version 2.0 (the "License"); 6135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** you may not use this file except in compliance with the License. 7135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** You may obtain a copy of the License at 8135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** 9135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** http://www.apache.org/licenses/LICENSE-2.0 10135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** 11135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** Unless required by applicable law or agreed to in writing, software 12135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** distributed under the License is distributed on an "AS IS" BASIS, 13135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** See the License for the specific language governing permissions and 15135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ** limitations under the License. 16135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent */ 17135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 18135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include <string.h> 19135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 20f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten#include <cutils/compiler.h> 21f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten 22f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten#include "AudioCoefInterpolator.h" 23135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 24135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentnamespace android { 25135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 26135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric LaurentAudioCoefInterpolator::AudioCoefInterpolator(size_t nInDims, 27135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const size_t inDims[], 28135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t nOutDims, 29135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t * table) { 30135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mNumInDims = nInDims; 31135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mInDims, inDims, nInDims * sizeof(size_t)); 32135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mNumOutDims = nOutDims; 33135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mTable = table; 34135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // Initialize offsets array 35135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t dim = nInDims - 1; 36135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mInDimOffsets[nInDims - 1] = nOutDims; 37135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (dim-- > 0) { 38135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mInDimOffsets[dim] = mInDimOffsets[dim + 1] * mInDims[dim + 1]; 39135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 40135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 41135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 42135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioCoefInterpolator::getCoef(const int intCoord[], uint32_t fracCoord[], 43135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_t out[]) { 44135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t index = 0; 45135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t dim = mNumInDims; 46135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (dim-- > 0) { 47f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_UNLIKELY(intCoord[dim] < 0)) { 48135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent fracCoord[dim] = 0; 49f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten } else if (CC_UNLIKELY(intCoord[dim] >= (int)mInDims[dim] - 1)) { 50135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent fracCoord[dim] = 0; 51135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent index += mInDimOffsets[dim] * (mInDims[dim] - 1); 52135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 53135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent index += mInDimOffsets[dim] * intCoord[dim]; 54135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 55135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 56135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent getCoefRecurse(index, fracCoord, out, 0); 57135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 58135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 59135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioCoefInterpolator::getCoefRecurse(size_t index, 60135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const uint32_t fracCoord[], 61135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_t out[], size_t dim) { 62135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (dim == mNumInDims) { 63135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(out, mTable + index, mNumOutDims * sizeof(audio_coef_t)); 64135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 65135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent getCoefRecurse(index, fracCoord, out, dim + 1); 66f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_LIKELY(fracCoord != 0)) { 67135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_t tempCoef[MAX_OUT_DIMS]; 68135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent getCoefRecurse(index + mInDimOffsets[dim], fracCoord, tempCoef, 69135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent dim + 1); 70135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t d = mNumOutDims; 71135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (d-- > 0) { 72135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent out[d] = interp(out[d], tempCoef[d], fracCoord[dim]); 73135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 74135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 75135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 76135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 77135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 78135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentaudio_coef_t AudioCoefInterpolator::interp(audio_coef_t lo, audio_coef_t hi, 79135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent uint32_t frac) { 80135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int64_t delta = static_cast<int64_t>(hi-lo) * frac; 81135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent return lo + static_cast<audio_coef_t> (delta >> 32); 82135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 83135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 84135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 85