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