summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/AudioResampler.h
blob: a8e3e6f91a156d25df11b14f3dccf1c3aa557364 (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 * Copyright (C) 2007 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.
 */

#ifndef ANDROID_AUDIO_RESAMPLER_H
#define ANDROID_AUDIO_RESAMPLER_H

#include <stdint.h>
#include <sys/types.h>

#include <cutils/compiler.h>
#include <utils/Compat.h>

#include <media/AudioBufferProvider.h>
#include <system/audio.h>

namespace android {
// ----------------------------------------------------------------------------

class ANDROID_API AudioResampler {
public:
    // Determines quality of SRC.
    //  LOW_QUALITY: linear interpolator (1st order)
    //  MED_QUALITY: cubic interpolator (3rd order)
    //  HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz)
    // NOTE: high quality SRC will only be supported for
    // certain fixed rate conversions. Sample rate cannot be
    // changed dynamically.
    enum src_quality {
        DEFAULT_QUALITY=0,
        LOW_QUALITY=1,
        MED_QUALITY=2,
        HIGH_QUALITY=3,
        VERY_HIGH_QUALITY=4,
        DYN_LOW_QUALITY=5,
        DYN_MED_QUALITY=6,
        DYN_HIGH_QUALITY=7,
    };

    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;

    static AudioResampler* create(audio_format_t format, int inChannelCount,
            int32_t sampleRate, src_quality quality=DEFAULT_QUALITY);

    virtual ~AudioResampler();

    virtual void init() = 0;
    virtual void setSampleRate(int32_t inSampleRate);
    virtual void setVolume(float left, float right);
    virtual void setLocalTimeFreq(uint64_t freq);

    // set the PTS of the next buffer output by the resampler
    virtual void setPTS(int64_t pts);

    // Resample int16_t samples from provider and accumulate into 'out'.
    // A mono provider delivers a sequence of samples.
    // A stereo provider delivers a sequence of interleaved pairs of samples.
    //
    // In either case, 'out' holds interleaved pairs of fixed-point Q4.27.
    // That is, for a mono provider, there is an implicit up-channeling.
    // Since this method accumulates, the caller is responsible for clearing 'out' initially.
    //
    // For a float resampler, 'out' holds interleaved pairs of float samples.
    //
    // Multichannel interleaved frames for n > 2 is supported for quality DYN_LOW_QUALITY,
    // DYN_MED_QUALITY, and DYN_HIGH_QUALITY.
    //
    // Returns the number of frames resampled into the out buffer.
    virtual size_t resample(int32_t* out, size_t outFrameCount,
            AudioBufferProvider* provider) = 0;

    virtual void reset();
    virtual size_t getUnreleasedFrames() const { return mInputIndex; }

    // called from destructor, so must not be virtual
    src_quality getQuality() const { return mQuality; }

protected:
    // number of bits for phase fraction - 30 bits allows nearly 2x downsampling
    static const int kNumPhaseBits = 30;

    // phase mask for fraction
    static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1;

    // multiplier to calculate fixed point phase increment
    static const double kPhaseMultiplier;

    AudioResampler(int inChannelCount, int32_t sampleRate, src_quality quality);

    // prevent copying
    AudioResampler(const AudioResampler&);
    AudioResampler& operator=(const AudioResampler&);

    int64_t calculateOutputPTS(int outputFrameIndex);

    const int32_t mChannelCount;
    const int32_t mSampleRate;
    int32_t mInSampleRate;
    AudioBufferProvider::Buffer mBuffer;
    union {
        int16_t mVolume[2];
        uint32_t mVolumeRL;
    };
    int16_t mTargetVolume[2];
    size_t mInputIndex;
    int32_t mPhaseIncrement;
    uint32_t mPhaseFraction;
    uint64_t mLocalTimeFreq;
    int64_t mPTS;

    // returns the inFrameCount required to generate outFrameCount frames.
    //
    // Placed here to be a consistent for all resamplers.
    //
    // Right now, we use the upper bound without regards to the current state of the
    // input buffer using integer arithmetic, as follows:
    //
    // (static_cast<uint64_t>(outFrameCount)*mInSampleRate + (mSampleRate - 1))/mSampleRate;
    //
    // The double precision equivalent (float may not be precise enough):
    // ceil(static_cast<double>(outFrameCount) * mInSampleRate / mSampleRate);
    //
    // this relies on the fact that the mPhaseIncrement is rounded down from
    // #phases * mInSampleRate/mSampleRate and the fact that Sum(Floor(x)) <= Floor(Sum(x)).
    // http://www.proofwiki.org/wiki/Sum_of_Floors_Not_Greater_Than_Floor_of_Sums
    //
    // (so long as double precision is computed accurately enough to be considered
    // greater than or equal to the Floor(x) value in int32_t arithmetic; thus this
    // will not necessarily hold for floats).
    //
    // TODO:
    // Greater accuracy and a tight bound is obtained by:
    // 1) subtract and adjust for the current state of the AudioBufferProvider buffer.
    // 2) using the exact integer formula where (ignoring 64b casting)
    //  inFrameCount = (mPhaseIncrement * (outFrameCount - 1) + mPhaseFraction) / phaseWrapLimit;
    //  phaseWrapLimit is the wraparound (1 << kNumPhaseBits), if not specified explicitly.
    //
    inline size_t getInFrameCountRequired(size_t outFrameCount) {
        return (static_cast<uint64_t>(outFrameCount)*mInSampleRate
                + (mSampleRate - 1))/mSampleRate;
    }

    inline float clampFloatVol(float volume) {
        if (volume > UNITY_GAIN_FLOAT) {
            return UNITY_GAIN_FLOAT;
        } else if (volume >= 0.) {
            return volume;
        }
        return 0.;  // NaN or negative volume maps to 0.
    }

private:
    const src_quality mQuality;

    // Return 'true' if the quality level is supported without explicit request
    static bool qualityIsSupported(src_quality quality);

    // For pthread_once()
    static void init_routine();

    // Return the estimated CPU load for specific resampler in MHz.
    // The absolute number is irrelevant, it's the relative values that matter.
    static uint32_t qualityMHz(src_quality quality);
};

// ----------------------------------------------------------------------------
} // namespace android

#endif // ANDROID_AUDIO_RESAMPLER_H