summaryrefslogtreecommitdiffstats
path: root/media/libeffects/testlibs/AudioCoefInterpolator.cpp
blob: 6b569221d8d9c5168e321e5ca9abebe41137aebe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* //device/servers/AudioFlinger/AudioCoefInterpolator.cpp
 **
 ** Copyright 2008, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */

#include <string.h>

#include <cutils/compiler.h>

#include "AudioCoefInterpolator.h"

namespace android {

AudioCoefInterpolator::AudioCoefInterpolator(size_t nInDims,
                                             const size_t inDims[],
                                             size_t nOutDims,
                                             const audio_coef_t * table) {
    mNumInDims = nInDims;
    memcpy(mInDims, inDims, nInDims * sizeof(size_t));
    mNumOutDims = nOutDims;
    mTable = table;
    // Initialize offsets array
    size_t dim = nInDims - 1;
    mInDimOffsets[nInDims - 1] = nOutDims;
    while (dim-- > 0) {
        mInDimOffsets[dim] = mInDimOffsets[dim + 1] * mInDims[dim + 1];
    }
}

void AudioCoefInterpolator::getCoef(const int intCoord[], uint32_t fracCoord[],
                                    audio_coef_t out[]) {
    size_t index = 0;
    size_t dim = mNumInDims;
    while (dim-- > 0) {
        if (CC_UNLIKELY(intCoord[dim] < 0)) {
            fracCoord[dim] = 0;
        } else if (CC_UNLIKELY(intCoord[dim] >= (int)mInDims[dim] - 1)) {
            fracCoord[dim] = 0;
            index += mInDimOffsets[dim] * (mInDims[dim] - 1);
        } else {
            index += mInDimOffsets[dim] * intCoord[dim];
        }
    }
    getCoefRecurse(index, fracCoord, out, 0);
}

void AudioCoefInterpolator::getCoefRecurse(size_t index,
                                           const uint32_t fracCoord[],
                                           audio_coef_t out[], size_t dim) {
    if (dim == mNumInDims) {
        memcpy(out, mTable + index, mNumOutDims * sizeof(audio_coef_t));
    } else {
        getCoefRecurse(index, fracCoord, out, dim + 1);
        if (CC_LIKELY(fracCoord != 0)) {
           audio_coef_t tempCoef[MAX_OUT_DIMS];
           getCoefRecurse(index + mInDimOffsets[dim], fracCoord, tempCoef,
                           dim + 1);
            size_t d = mNumOutDims;
            while (d-- > 0) {
                out[d] = interp(out[d], tempCoef[d], fracCoord[dim]);
            }
        }
    }
}

audio_coef_t AudioCoefInterpolator::interp(audio_coef_t lo, audio_coef_t hi,
                                           uint32_t frac) {
    int64_t delta = static_cast<int64_t>(hi-lo) * frac;
    return lo + static_cast<audio_coef_t> (delta >> 32);
}

}