blob: 6b569221d8d9c5168e321e5ca9abebe41137aebe [file] [log] [blame]
Eric Laurent5fe37c62010-05-21 06:05:13 -07001/* //device/servers/AudioFlinger/AudioCoefInterpolator.cpp
2 **
3 ** Copyright 2008, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18#include <string.h>
Eric Laurent5fe37c62010-05-21 06:05:13 -070019
Glenn Kastene80a4cc2011-12-15 09:51:17 -080020#include <cutils/compiler.h>
21
22#include "AudioCoefInterpolator.h"
Eric Laurent5fe37c62010-05-21 06:05:13 -070023
24namespace android {
25
26AudioCoefInterpolator::AudioCoefInterpolator(size_t nInDims,
27 const size_t inDims[],
28 size_t nOutDims,
29 const audio_coef_t * table) {
30 mNumInDims = nInDims;
31 memcpy(mInDims, inDims, nInDims * sizeof(size_t));
32 mNumOutDims = nOutDims;
33 mTable = table;
34 // Initialize offsets array
35 size_t dim = nInDims - 1;
36 mInDimOffsets[nInDims - 1] = nOutDims;
37 while (dim-- > 0) {
38 mInDimOffsets[dim] = mInDimOffsets[dim + 1] * mInDims[dim + 1];
39 }
40}
41
42void AudioCoefInterpolator::getCoef(const int intCoord[], uint32_t fracCoord[],
43 audio_coef_t out[]) {
44 size_t index = 0;
45 size_t dim = mNumInDims;
46 while (dim-- > 0) {
Glenn Kastene80a4cc2011-12-15 09:51:17 -080047 if (CC_UNLIKELY(intCoord[dim] < 0)) {
Eric Laurent5fe37c62010-05-21 06:05:13 -070048 fracCoord[dim] = 0;
Glenn Kastene80a4cc2011-12-15 09:51:17 -080049 } else if (CC_UNLIKELY(intCoord[dim] >= (int)mInDims[dim] - 1)) {
Eric Laurent5fe37c62010-05-21 06:05:13 -070050 fracCoord[dim] = 0;
51 index += mInDimOffsets[dim] * (mInDims[dim] - 1);
52 } else {
53 index += mInDimOffsets[dim] * intCoord[dim];
54 }
55 }
56 getCoefRecurse(index, fracCoord, out, 0);
57}
58
59void AudioCoefInterpolator::getCoefRecurse(size_t index,
60 const uint32_t fracCoord[],
61 audio_coef_t out[], size_t dim) {
62 if (dim == mNumInDims) {
63 memcpy(out, mTable + index, mNumOutDims * sizeof(audio_coef_t));
64 } else {
65 getCoefRecurse(index, fracCoord, out, dim + 1);
Glenn Kastene80a4cc2011-12-15 09:51:17 -080066 if (CC_LIKELY(fracCoord != 0)) {
Eric Laurent5fe37c62010-05-21 06:05:13 -070067 audio_coef_t tempCoef[MAX_OUT_DIMS];
68 getCoefRecurse(index + mInDimOffsets[dim], fracCoord, tempCoef,
69 dim + 1);
70 size_t d = mNumOutDims;
71 while (d-- > 0) {
72 out[d] = interp(out[d], tempCoef[d], fracCoord[dim]);
73 }
74 }
75 }
76}
77
78audio_coef_t AudioCoefInterpolator::interp(audio_coef_t lo, audio_coef_t hi,
79 uint32_t frac) {
80 int64_t delta = static_cast<int64_t>(hi-lo) * frac;
81 return lo + static_cast<audio_coef_t> (delta >> 32);
82}
83
84}