1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2007 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AudioResampler"
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker
20*ec779b8eSAndroid Build Coastguard Worker #include <pthread.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <stdint.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <stdlib.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h>
24*ec779b8eSAndroid Build Coastguard Worker
25*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <log/log.h>
27*ec779b8eSAndroid Build Coastguard Worker
28*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/primitives.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioResampler.h>
30*ec779b8eSAndroid Build Coastguard Worker #include "AudioResamplerSinc.h"
31*ec779b8eSAndroid Build Coastguard Worker #include "AudioResamplerCubic.h"
32*ec779b8eSAndroid Build Coastguard Worker #include "AudioResamplerDyn.h"
33*ec779b8eSAndroid Build Coastguard Worker
34*ec779b8eSAndroid Build Coastguard Worker #ifdef __arm__
35*ec779b8eSAndroid Build Coastguard Worker // bug 13102576
36*ec779b8eSAndroid Build Coastguard Worker //#define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
37*ec779b8eSAndroid Build Coastguard Worker #endif
38*ec779b8eSAndroid Build Coastguard Worker
39*ec779b8eSAndroid Build Coastguard Worker namespace android {
40*ec779b8eSAndroid Build Coastguard Worker
41*ec779b8eSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
42*ec779b8eSAndroid Build Coastguard Worker
43*ec779b8eSAndroid Build Coastguard Worker class AudioResamplerOrder1 : public AudioResampler {
44*ec779b8eSAndroid Build Coastguard Worker public:
AudioResamplerOrder1(int inChannelCount,int32_t sampleRate)45*ec779b8eSAndroid Build Coastguard Worker AudioResamplerOrder1(int inChannelCount, int32_t sampleRate) :
46*ec779b8eSAndroid Build Coastguard Worker AudioResampler(inChannelCount, sampleRate, LOW_QUALITY), mX0L(0), mX0R(0) {
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker virtual size_t resample(int32_t* out, size_t outFrameCount,
49*ec779b8eSAndroid Build Coastguard Worker AudioBufferProvider* provider);
50*ec779b8eSAndroid Build Coastguard Worker private:
51*ec779b8eSAndroid Build Coastguard Worker // number of bits used in interpolation multiply - 15 bits avoids overflow
52*ec779b8eSAndroid Build Coastguard Worker static const int kNumInterpBits = 15;
53*ec779b8eSAndroid Build Coastguard Worker
54*ec779b8eSAndroid Build Coastguard Worker // bits to shift the phase fraction down to avoid overflow
55*ec779b8eSAndroid Build Coastguard Worker static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
56*ec779b8eSAndroid Build Coastguard Worker
init()57*ec779b8eSAndroid Build Coastguard Worker void init() {}
58*ec779b8eSAndroid Build Coastguard Worker size_t resampleMono16(int32_t* out, size_t outFrameCount,
59*ec779b8eSAndroid Build Coastguard Worker AudioBufferProvider* provider);
60*ec779b8eSAndroid Build Coastguard Worker size_t resampleStereo16(int32_t* out, size_t outFrameCount,
61*ec779b8eSAndroid Build Coastguard Worker AudioBufferProvider* provider);
62*ec779b8eSAndroid Build Coastguard Worker #ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
63*ec779b8eSAndroid Build Coastguard Worker void AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
64*ec779b8eSAndroid Build Coastguard Worker size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
65*ec779b8eSAndroid Build Coastguard Worker uint32_t &phaseFraction, uint32_t phaseIncrement);
66*ec779b8eSAndroid Build Coastguard Worker void AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
67*ec779b8eSAndroid Build Coastguard Worker size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
68*ec779b8eSAndroid Build Coastguard Worker uint32_t &phaseFraction, uint32_t phaseIncrement);
69*ec779b8eSAndroid Build Coastguard Worker #endif // ASM_ARM_RESAMP1
70*ec779b8eSAndroid Build Coastguard Worker
Interp(int32_t x0,int32_t x1,uint32_t f)71*ec779b8eSAndroid Build Coastguard Worker static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) {
72*ec779b8eSAndroid Build Coastguard Worker return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits);
73*ec779b8eSAndroid Build Coastguard Worker }
Advance(size_t * index,uint32_t * frac,uint32_t inc)74*ec779b8eSAndroid Build Coastguard Worker static inline void Advance(size_t* index, uint32_t* frac, uint32_t inc) {
75*ec779b8eSAndroid Build Coastguard Worker *frac += inc;
76*ec779b8eSAndroid Build Coastguard Worker *index += (size_t)(*frac >> kNumPhaseBits);
77*ec779b8eSAndroid Build Coastguard Worker *frac &= kPhaseMask;
78*ec779b8eSAndroid Build Coastguard Worker }
79*ec779b8eSAndroid Build Coastguard Worker int mX0L;
80*ec779b8eSAndroid Build Coastguard Worker int mX0R;
81*ec779b8eSAndroid Build Coastguard Worker };
82*ec779b8eSAndroid Build Coastguard Worker
83*ec779b8eSAndroid Build Coastguard Worker /*static*/
84*ec779b8eSAndroid Build Coastguard Worker const double AudioResampler::kPhaseMultiplier = 1L << AudioResampler::kNumPhaseBits;
85*ec779b8eSAndroid Build Coastguard Worker
qualityIsSupported(src_quality quality)86*ec779b8eSAndroid Build Coastguard Worker bool AudioResampler::qualityIsSupported(src_quality quality)
87*ec779b8eSAndroid Build Coastguard Worker {
88*ec779b8eSAndroid Build Coastguard Worker switch (quality) {
89*ec779b8eSAndroid Build Coastguard Worker case DEFAULT_QUALITY:
90*ec779b8eSAndroid Build Coastguard Worker case LOW_QUALITY:
91*ec779b8eSAndroid Build Coastguard Worker case MED_QUALITY:
92*ec779b8eSAndroid Build Coastguard Worker case HIGH_QUALITY:
93*ec779b8eSAndroid Build Coastguard Worker case VERY_HIGH_QUALITY:
94*ec779b8eSAndroid Build Coastguard Worker case DYN_LOW_QUALITY:
95*ec779b8eSAndroid Build Coastguard Worker case DYN_MED_QUALITY:
96*ec779b8eSAndroid Build Coastguard Worker case DYN_HIGH_QUALITY:
97*ec779b8eSAndroid Build Coastguard Worker return true;
98*ec779b8eSAndroid Build Coastguard Worker default:
99*ec779b8eSAndroid Build Coastguard Worker return false;
100*ec779b8eSAndroid Build Coastguard Worker }
101*ec779b8eSAndroid Build Coastguard Worker }
102*ec779b8eSAndroid Build Coastguard Worker
103*ec779b8eSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
104*ec779b8eSAndroid Build Coastguard Worker
105*ec779b8eSAndroid Build Coastguard Worker static pthread_once_t once_control = PTHREAD_ONCE_INIT;
106*ec779b8eSAndroid Build Coastguard Worker static AudioResampler::src_quality defaultQuality = AudioResampler::DEFAULT_QUALITY;
107*ec779b8eSAndroid Build Coastguard Worker
init_routine()108*ec779b8eSAndroid Build Coastguard Worker void AudioResampler::init_routine()
109*ec779b8eSAndroid Build Coastguard Worker {
110*ec779b8eSAndroid Build Coastguard Worker char value[PROPERTY_VALUE_MAX];
111*ec779b8eSAndroid Build Coastguard Worker if (property_get("af.resampler.quality", value, NULL) > 0) {
112*ec779b8eSAndroid Build Coastguard Worker char *endptr;
113*ec779b8eSAndroid Build Coastguard Worker unsigned long l = strtoul(value, &endptr, 0);
114*ec779b8eSAndroid Build Coastguard Worker if (*endptr == '\0') {
115*ec779b8eSAndroid Build Coastguard Worker defaultQuality = (src_quality) l;
116*ec779b8eSAndroid Build Coastguard Worker ALOGD("forcing AudioResampler quality to %d", defaultQuality);
117*ec779b8eSAndroid Build Coastguard Worker if (defaultQuality < DEFAULT_QUALITY || defaultQuality > DYN_HIGH_QUALITY) {
118*ec779b8eSAndroid Build Coastguard Worker defaultQuality = DEFAULT_QUALITY;
119*ec779b8eSAndroid Build Coastguard Worker }
120*ec779b8eSAndroid Build Coastguard Worker }
121*ec779b8eSAndroid Build Coastguard Worker }
122*ec779b8eSAndroid Build Coastguard Worker }
123*ec779b8eSAndroid Build Coastguard Worker
qualityMHz(src_quality quality)124*ec779b8eSAndroid Build Coastguard Worker uint32_t AudioResampler::qualityMHz(src_quality quality)
125*ec779b8eSAndroid Build Coastguard Worker {
126*ec779b8eSAndroid Build Coastguard Worker switch (quality) {
127*ec779b8eSAndroid Build Coastguard Worker default:
128*ec779b8eSAndroid Build Coastguard Worker case DEFAULT_QUALITY:
129*ec779b8eSAndroid Build Coastguard Worker case LOW_QUALITY:
130*ec779b8eSAndroid Build Coastguard Worker return 3;
131*ec779b8eSAndroid Build Coastguard Worker case MED_QUALITY:
132*ec779b8eSAndroid Build Coastguard Worker return 6;
133*ec779b8eSAndroid Build Coastguard Worker case HIGH_QUALITY:
134*ec779b8eSAndroid Build Coastguard Worker return 20;
135*ec779b8eSAndroid Build Coastguard Worker case VERY_HIGH_QUALITY:
136*ec779b8eSAndroid Build Coastguard Worker return 34;
137*ec779b8eSAndroid Build Coastguard Worker case DYN_LOW_QUALITY:
138*ec779b8eSAndroid Build Coastguard Worker return 4;
139*ec779b8eSAndroid Build Coastguard Worker case DYN_MED_QUALITY:
140*ec779b8eSAndroid Build Coastguard Worker return 6;
141*ec779b8eSAndroid Build Coastguard Worker case DYN_HIGH_QUALITY:
142*ec779b8eSAndroid Build Coastguard Worker return 12;
143*ec779b8eSAndroid Build Coastguard Worker }
144*ec779b8eSAndroid Build Coastguard Worker }
145*ec779b8eSAndroid Build Coastguard Worker
146*ec779b8eSAndroid Build Coastguard Worker static const uint32_t maxMHz = 130; // an arbitrary number that permits 3 VHQ, should be tunable
147*ec779b8eSAndroid Build Coastguard Worker static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
148*ec779b8eSAndroid Build Coastguard Worker static uint32_t currentMHz = 0;
149*ec779b8eSAndroid Build Coastguard Worker
create(audio_format_t format,int inChannelCount,int32_t sampleRate,src_quality quality)150*ec779b8eSAndroid Build Coastguard Worker AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount,
151*ec779b8eSAndroid Build Coastguard Worker int32_t sampleRate, src_quality quality) {
152*ec779b8eSAndroid Build Coastguard Worker
153*ec779b8eSAndroid Build Coastguard Worker bool atFinalQuality;
154*ec779b8eSAndroid Build Coastguard Worker if (quality == DEFAULT_QUALITY) {
155*ec779b8eSAndroid Build Coastguard Worker // read the resampler default quality property the first time it is needed
156*ec779b8eSAndroid Build Coastguard Worker int ok = pthread_once(&once_control, init_routine);
157*ec779b8eSAndroid Build Coastguard Worker if (ok != 0) {
158*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s pthread_once failed: %d", __func__, ok);
159*ec779b8eSAndroid Build Coastguard Worker }
160*ec779b8eSAndroid Build Coastguard Worker quality = defaultQuality;
161*ec779b8eSAndroid Build Coastguard Worker atFinalQuality = false;
162*ec779b8eSAndroid Build Coastguard Worker } else {
163*ec779b8eSAndroid Build Coastguard Worker atFinalQuality = true;
164*ec779b8eSAndroid Build Coastguard Worker }
165*ec779b8eSAndroid Build Coastguard Worker
166*ec779b8eSAndroid Build Coastguard Worker /* if the caller requests DEFAULT_QUALITY and af.resampler.property
167*ec779b8eSAndroid Build Coastguard Worker * has not been set, the target resampler quality is set to DYN_MED_QUALITY,
168*ec779b8eSAndroid Build Coastguard Worker * and allowed to "throttle" down to DYN_LOW_QUALITY if necessary
169*ec779b8eSAndroid Build Coastguard Worker * due to estimated CPU load of having too many active resamplers
170*ec779b8eSAndroid Build Coastguard Worker * (the code below the if).
171*ec779b8eSAndroid Build Coastguard Worker */
172*ec779b8eSAndroid Build Coastguard Worker if (quality == DEFAULT_QUALITY) {
173*ec779b8eSAndroid Build Coastguard Worker quality = DYN_MED_QUALITY;
174*ec779b8eSAndroid Build Coastguard Worker }
175*ec779b8eSAndroid Build Coastguard Worker
176*ec779b8eSAndroid Build Coastguard Worker // naive implementation of CPU load throttling doesn't account for whether resampler is active
177*ec779b8eSAndroid Build Coastguard Worker pthread_mutex_lock(&mutex);
178*ec779b8eSAndroid Build Coastguard Worker for (;;) {
179*ec779b8eSAndroid Build Coastguard Worker uint32_t deltaMHz = qualityMHz(quality);
180*ec779b8eSAndroid Build Coastguard Worker uint32_t newMHz = currentMHz + deltaMHz;
181*ec779b8eSAndroid Build Coastguard Worker if ((qualityIsSupported(quality) && newMHz <= maxMHz) || atFinalQuality) {
182*ec779b8eSAndroid Build Coastguard Worker ALOGV("resampler load %u -> %u MHz due to delta +%u MHz from quality %d",
183*ec779b8eSAndroid Build Coastguard Worker currentMHz, newMHz, deltaMHz, quality);
184*ec779b8eSAndroid Build Coastguard Worker currentMHz = newMHz;
185*ec779b8eSAndroid Build Coastguard Worker break;
186*ec779b8eSAndroid Build Coastguard Worker }
187*ec779b8eSAndroid Build Coastguard Worker // not enough CPU available for proposed quality level, so try next lowest level
188*ec779b8eSAndroid Build Coastguard Worker switch (quality) {
189*ec779b8eSAndroid Build Coastguard Worker default:
190*ec779b8eSAndroid Build Coastguard Worker case LOW_QUALITY:
191*ec779b8eSAndroid Build Coastguard Worker atFinalQuality = true;
192*ec779b8eSAndroid Build Coastguard Worker break;
193*ec779b8eSAndroid Build Coastguard Worker case MED_QUALITY:
194*ec779b8eSAndroid Build Coastguard Worker quality = LOW_QUALITY;
195*ec779b8eSAndroid Build Coastguard Worker break;
196*ec779b8eSAndroid Build Coastguard Worker case HIGH_QUALITY:
197*ec779b8eSAndroid Build Coastguard Worker quality = MED_QUALITY;
198*ec779b8eSAndroid Build Coastguard Worker break;
199*ec779b8eSAndroid Build Coastguard Worker case VERY_HIGH_QUALITY:
200*ec779b8eSAndroid Build Coastguard Worker quality = HIGH_QUALITY;
201*ec779b8eSAndroid Build Coastguard Worker break;
202*ec779b8eSAndroid Build Coastguard Worker case DYN_LOW_QUALITY:
203*ec779b8eSAndroid Build Coastguard Worker atFinalQuality = true;
204*ec779b8eSAndroid Build Coastguard Worker break;
205*ec779b8eSAndroid Build Coastguard Worker case DYN_MED_QUALITY:
206*ec779b8eSAndroid Build Coastguard Worker quality = DYN_LOW_QUALITY;
207*ec779b8eSAndroid Build Coastguard Worker break;
208*ec779b8eSAndroid Build Coastguard Worker case DYN_HIGH_QUALITY:
209*ec779b8eSAndroid Build Coastguard Worker quality = DYN_MED_QUALITY;
210*ec779b8eSAndroid Build Coastguard Worker break;
211*ec779b8eSAndroid Build Coastguard Worker }
212*ec779b8eSAndroid Build Coastguard Worker }
213*ec779b8eSAndroid Build Coastguard Worker pthread_mutex_unlock(&mutex);
214*ec779b8eSAndroid Build Coastguard Worker
215*ec779b8eSAndroid Build Coastguard Worker AudioResampler* resampler;
216*ec779b8eSAndroid Build Coastguard Worker
217*ec779b8eSAndroid Build Coastguard Worker switch (quality) {
218*ec779b8eSAndroid Build Coastguard Worker default:
219*ec779b8eSAndroid Build Coastguard Worker case LOW_QUALITY:
220*ec779b8eSAndroid Build Coastguard Worker ALOGV("Create linear Resampler");
221*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
222*ec779b8eSAndroid Build Coastguard Worker resampler = new AudioResamplerOrder1(inChannelCount, sampleRate);
223*ec779b8eSAndroid Build Coastguard Worker break;
224*ec779b8eSAndroid Build Coastguard Worker case MED_QUALITY:
225*ec779b8eSAndroid Build Coastguard Worker ALOGV("Create cubic Resampler");
226*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
227*ec779b8eSAndroid Build Coastguard Worker resampler = new AudioResamplerCubic(inChannelCount, sampleRate);
228*ec779b8eSAndroid Build Coastguard Worker break;
229*ec779b8eSAndroid Build Coastguard Worker case HIGH_QUALITY:
230*ec779b8eSAndroid Build Coastguard Worker ALOGV("Create HIGH_QUALITY sinc Resampler");
231*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
232*ec779b8eSAndroid Build Coastguard Worker resampler = new AudioResamplerSinc(inChannelCount, sampleRate);
233*ec779b8eSAndroid Build Coastguard Worker break;
234*ec779b8eSAndroid Build Coastguard Worker case VERY_HIGH_QUALITY:
235*ec779b8eSAndroid Build Coastguard Worker ALOGV("Create VERY_HIGH_QUALITY sinc Resampler = %d", quality);
236*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
237*ec779b8eSAndroid Build Coastguard Worker resampler = new AudioResamplerSinc(inChannelCount, sampleRate, quality);
238*ec779b8eSAndroid Build Coastguard Worker break;
239*ec779b8eSAndroid Build Coastguard Worker case DYN_LOW_QUALITY:
240*ec779b8eSAndroid Build Coastguard Worker case DYN_MED_QUALITY:
241*ec779b8eSAndroid Build Coastguard Worker case DYN_HIGH_QUALITY:
242*ec779b8eSAndroid Build Coastguard Worker ALOGV("Create dynamic Resampler = %d", quality);
243*ec779b8eSAndroid Build Coastguard Worker if (format == AUDIO_FORMAT_PCM_FLOAT) {
244*ec779b8eSAndroid Build Coastguard Worker resampler = new AudioResamplerDyn<float, float, float>(inChannelCount,
245*ec779b8eSAndroid Build Coastguard Worker sampleRate, quality);
246*ec779b8eSAndroid Build Coastguard Worker } else {
247*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
248*ec779b8eSAndroid Build Coastguard Worker if (quality == DYN_HIGH_QUALITY) {
249*ec779b8eSAndroid Build Coastguard Worker resampler = new AudioResamplerDyn<int32_t, int16_t, int32_t>(inChannelCount,
250*ec779b8eSAndroid Build Coastguard Worker sampleRate, quality);
251*ec779b8eSAndroid Build Coastguard Worker } else {
252*ec779b8eSAndroid Build Coastguard Worker resampler = new AudioResamplerDyn<int16_t, int16_t, int32_t>(inChannelCount,
253*ec779b8eSAndroid Build Coastguard Worker sampleRate, quality);
254*ec779b8eSAndroid Build Coastguard Worker }
255*ec779b8eSAndroid Build Coastguard Worker }
256*ec779b8eSAndroid Build Coastguard Worker break;
257*ec779b8eSAndroid Build Coastguard Worker }
258*ec779b8eSAndroid Build Coastguard Worker
259*ec779b8eSAndroid Build Coastguard Worker // initialize resampler
260*ec779b8eSAndroid Build Coastguard Worker resampler->init();
261*ec779b8eSAndroid Build Coastguard Worker return resampler;
262*ec779b8eSAndroid Build Coastguard Worker }
263*ec779b8eSAndroid Build Coastguard Worker
AudioResampler(int inChannelCount,int32_t sampleRate,src_quality quality)264*ec779b8eSAndroid Build Coastguard Worker AudioResampler::AudioResampler(int inChannelCount,
265*ec779b8eSAndroid Build Coastguard Worker int32_t sampleRate, src_quality quality) :
266*ec779b8eSAndroid Build Coastguard Worker mChannelCount(inChannelCount),
267*ec779b8eSAndroid Build Coastguard Worker mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0),
268*ec779b8eSAndroid Build Coastguard Worker mPhaseFraction(0),
269*ec779b8eSAndroid Build Coastguard Worker mQuality(quality) {
270*ec779b8eSAndroid Build Coastguard Worker
271*ec779b8eSAndroid Build Coastguard Worker const int maxChannels = quality < DYN_LOW_QUALITY ? FCC_2 : FCC_LIMIT;
272*ec779b8eSAndroid Build Coastguard Worker if (inChannelCount < 1
273*ec779b8eSAndroid Build Coastguard Worker || inChannelCount > maxChannels) {
274*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Unsupported sample format %d quality %d channels",
275*ec779b8eSAndroid Build Coastguard Worker quality, inChannelCount);
276*ec779b8eSAndroid Build Coastguard Worker }
277*ec779b8eSAndroid Build Coastguard Worker if (sampleRate <= 0) {
278*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Unsupported sample rate %d Hz", sampleRate);
279*ec779b8eSAndroid Build Coastguard Worker }
280*ec779b8eSAndroid Build Coastguard Worker
281*ec779b8eSAndroid Build Coastguard Worker // initialize common members
282*ec779b8eSAndroid Build Coastguard Worker mVolume[0] = mVolume[1] = 0;
283*ec779b8eSAndroid Build Coastguard Worker mBuffer.frameCount = 0;
284*ec779b8eSAndroid Build Coastguard Worker }
285*ec779b8eSAndroid Build Coastguard Worker
~AudioResampler()286*ec779b8eSAndroid Build Coastguard Worker AudioResampler::~AudioResampler() {
287*ec779b8eSAndroid Build Coastguard Worker pthread_mutex_lock(&mutex);
288*ec779b8eSAndroid Build Coastguard Worker src_quality quality = getQuality();
289*ec779b8eSAndroid Build Coastguard Worker uint32_t deltaMHz = qualityMHz(quality);
290*ec779b8eSAndroid Build Coastguard Worker int32_t newMHz = currentMHz - deltaMHz;
291*ec779b8eSAndroid Build Coastguard Worker ALOGV("resampler load %u -> %d MHz due to delta -%u MHz from quality %d",
292*ec779b8eSAndroid Build Coastguard Worker currentMHz, newMHz, deltaMHz, quality);
293*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(newMHz < 0, "negative resampler load %d MHz", newMHz);
294*ec779b8eSAndroid Build Coastguard Worker currentMHz = newMHz;
295*ec779b8eSAndroid Build Coastguard Worker pthread_mutex_unlock(&mutex);
296*ec779b8eSAndroid Build Coastguard Worker }
297*ec779b8eSAndroid Build Coastguard Worker
setSampleRate(int32_t inSampleRate)298*ec779b8eSAndroid Build Coastguard Worker void AudioResampler::setSampleRate(int32_t inSampleRate) {
299*ec779b8eSAndroid Build Coastguard Worker mInSampleRate = inSampleRate;
300*ec779b8eSAndroid Build Coastguard Worker mPhaseIncrement = (uint32_t)((kPhaseMultiplier * inSampleRate) / mSampleRate);
301*ec779b8eSAndroid Build Coastguard Worker }
302*ec779b8eSAndroid Build Coastguard Worker
setVolume(float left,float right)303*ec779b8eSAndroid Build Coastguard Worker void AudioResampler::setVolume(float left, float right) {
304*ec779b8eSAndroid Build Coastguard Worker // TODO: Implement anti-zipper filter
305*ec779b8eSAndroid Build Coastguard Worker // convert to U4.12 for internal integer use (round down)
306*ec779b8eSAndroid Build Coastguard Worker // integer volume values are clamped to 0 to UNITY_GAIN.
307*ec779b8eSAndroid Build Coastguard Worker mVolume[0] = u4_12_from_float(clampFloatVol(left));
308*ec779b8eSAndroid Build Coastguard Worker mVolume[1] = u4_12_from_float(clampFloatVol(right));
309*ec779b8eSAndroid Build Coastguard Worker }
310*ec779b8eSAndroid Build Coastguard Worker
reset()311*ec779b8eSAndroid Build Coastguard Worker void AudioResampler::reset() {
312*ec779b8eSAndroid Build Coastguard Worker mInputIndex = 0;
313*ec779b8eSAndroid Build Coastguard Worker mPhaseFraction = 0;
314*ec779b8eSAndroid Build Coastguard Worker mBuffer.frameCount = 0;
315*ec779b8eSAndroid Build Coastguard Worker }
316*ec779b8eSAndroid Build Coastguard Worker
317*ec779b8eSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
318*ec779b8eSAndroid Build Coastguard Worker
resample(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)319*ec779b8eSAndroid Build Coastguard Worker size_t AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount,
320*ec779b8eSAndroid Build Coastguard Worker AudioBufferProvider* provider) {
321*ec779b8eSAndroid Build Coastguard Worker
322*ec779b8eSAndroid Build Coastguard Worker // should never happen, but we overflow if it does
323*ec779b8eSAndroid Build Coastguard Worker // ALOG_ASSERT(outFrameCount < 32767);
324*ec779b8eSAndroid Build Coastguard Worker
325*ec779b8eSAndroid Build Coastguard Worker // select the appropriate resampler
326*ec779b8eSAndroid Build Coastguard Worker switch (mChannelCount) {
327*ec779b8eSAndroid Build Coastguard Worker case 1:
328*ec779b8eSAndroid Build Coastguard Worker return resampleMono16(out, outFrameCount, provider);
329*ec779b8eSAndroid Build Coastguard Worker case 2:
330*ec779b8eSAndroid Build Coastguard Worker return resampleStereo16(out, outFrameCount, provider);
331*ec779b8eSAndroid Build Coastguard Worker default:
332*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("invalid channel count: %d", mChannelCount);
333*ec779b8eSAndroid Build Coastguard Worker return 0;
334*ec779b8eSAndroid Build Coastguard Worker }
335*ec779b8eSAndroid Build Coastguard Worker }
336*ec779b8eSAndroid Build Coastguard Worker
resampleStereo16(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)337*ec779b8eSAndroid Build Coastguard Worker size_t AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,
338*ec779b8eSAndroid Build Coastguard Worker AudioBufferProvider* provider) {
339*ec779b8eSAndroid Build Coastguard Worker
340*ec779b8eSAndroid Build Coastguard Worker int32_t vl = mVolume[0];
341*ec779b8eSAndroid Build Coastguard Worker int32_t vr = mVolume[1];
342*ec779b8eSAndroid Build Coastguard Worker
343*ec779b8eSAndroid Build Coastguard Worker size_t inputIndex = mInputIndex;
344*ec779b8eSAndroid Build Coastguard Worker uint32_t phaseFraction = mPhaseFraction;
345*ec779b8eSAndroid Build Coastguard Worker uint32_t phaseIncrement = mPhaseIncrement;
346*ec779b8eSAndroid Build Coastguard Worker size_t outputIndex = 0;
347*ec779b8eSAndroid Build Coastguard Worker size_t outputSampleCount = outFrameCount * 2;
348*ec779b8eSAndroid Build Coastguard Worker size_t inFrameCount = getInFrameCountRequired(outFrameCount);
349*ec779b8eSAndroid Build Coastguard Worker
350*ec779b8eSAndroid Build Coastguard Worker // ALOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d",
351*ec779b8eSAndroid Build Coastguard Worker // outFrameCount, inputIndex, phaseFraction, phaseIncrement);
352*ec779b8eSAndroid Build Coastguard Worker
353*ec779b8eSAndroid Build Coastguard Worker while (outputIndex < outputSampleCount) {
354*ec779b8eSAndroid Build Coastguard Worker
355*ec779b8eSAndroid Build Coastguard Worker // buffer is empty, fetch a new one
356*ec779b8eSAndroid Build Coastguard Worker while (mBuffer.frameCount == 0) {
357*ec779b8eSAndroid Build Coastguard Worker mBuffer.frameCount = inFrameCount;
358*ec779b8eSAndroid Build Coastguard Worker provider->getNextBuffer(&mBuffer);
359*ec779b8eSAndroid Build Coastguard Worker if (mBuffer.raw == NULL) {
360*ec779b8eSAndroid Build Coastguard Worker goto resampleStereo16_exit;
361*ec779b8eSAndroid Build Coastguard Worker }
362*ec779b8eSAndroid Build Coastguard Worker
363*ec779b8eSAndroid Build Coastguard Worker // ALOGE("New buffer fetched: %d frames", mBuffer.frameCount);
364*ec779b8eSAndroid Build Coastguard Worker if (mBuffer.frameCount > inputIndex) break;
365*ec779b8eSAndroid Build Coastguard Worker
366*ec779b8eSAndroid Build Coastguard Worker inputIndex -= mBuffer.frameCount;
367*ec779b8eSAndroid Build Coastguard Worker mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
368*ec779b8eSAndroid Build Coastguard Worker mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
369*ec779b8eSAndroid Build Coastguard Worker provider->releaseBuffer(&mBuffer);
370*ec779b8eSAndroid Build Coastguard Worker // mBuffer.frameCount == 0 now so we reload a new buffer
371*ec779b8eSAndroid Build Coastguard Worker }
372*ec779b8eSAndroid Build Coastguard Worker
373*ec779b8eSAndroid Build Coastguard Worker int16_t *in = mBuffer.i16;
374*ec779b8eSAndroid Build Coastguard Worker
375*ec779b8eSAndroid Build Coastguard Worker // handle boundary case
376*ec779b8eSAndroid Build Coastguard Worker while (inputIndex == 0) {
377*ec779b8eSAndroid Build Coastguard Worker // ALOGE("boundary case");
378*ec779b8eSAndroid Build Coastguard Worker out[outputIndex++] += vl * Interp(mX0L, in[0], phaseFraction);
379*ec779b8eSAndroid Build Coastguard Worker out[outputIndex++] += vr * Interp(mX0R, in[1], phaseFraction);
380*ec779b8eSAndroid Build Coastguard Worker Advance(&inputIndex, &phaseFraction, phaseIncrement);
381*ec779b8eSAndroid Build Coastguard Worker if (outputIndex == outputSampleCount) {
382*ec779b8eSAndroid Build Coastguard Worker break;
383*ec779b8eSAndroid Build Coastguard Worker }
384*ec779b8eSAndroid Build Coastguard Worker }
385*ec779b8eSAndroid Build Coastguard Worker
386*ec779b8eSAndroid Build Coastguard Worker // process input samples
387*ec779b8eSAndroid Build Coastguard Worker // ALOGE("general case");
388*ec779b8eSAndroid Build Coastguard Worker
389*ec779b8eSAndroid Build Coastguard Worker #ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
390*ec779b8eSAndroid Build Coastguard Worker if (inputIndex + 2 < mBuffer.frameCount) {
391*ec779b8eSAndroid Build Coastguard Worker int32_t* maxOutPt;
392*ec779b8eSAndroid Build Coastguard Worker int32_t maxInIdx;
393*ec779b8eSAndroid Build Coastguard Worker
394*ec779b8eSAndroid Build Coastguard Worker maxOutPt = out + (outputSampleCount - 2); // 2 because 2 frames per loop
395*ec779b8eSAndroid Build Coastguard Worker maxInIdx = mBuffer.frameCount - 2;
396*ec779b8eSAndroid Build Coastguard Worker AsmStereo16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
397*ec779b8eSAndroid Build Coastguard Worker phaseFraction, phaseIncrement);
398*ec779b8eSAndroid Build Coastguard Worker }
399*ec779b8eSAndroid Build Coastguard Worker #endif // ASM_ARM_RESAMP1
400*ec779b8eSAndroid Build Coastguard Worker
401*ec779b8eSAndroid Build Coastguard Worker while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
402*ec779b8eSAndroid Build Coastguard Worker out[outputIndex++] += vl * Interp(in[inputIndex*2-2],
403*ec779b8eSAndroid Build Coastguard Worker in[inputIndex*2], phaseFraction);
404*ec779b8eSAndroid Build Coastguard Worker out[outputIndex++] += vr * Interp(in[inputIndex*2-1],
405*ec779b8eSAndroid Build Coastguard Worker in[inputIndex*2+1], phaseFraction);
406*ec779b8eSAndroid Build Coastguard Worker Advance(&inputIndex, &phaseFraction, phaseIncrement);
407*ec779b8eSAndroid Build Coastguard Worker }
408*ec779b8eSAndroid Build Coastguard Worker
409*ec779b8eSAndroid Build Coastguard Worker // ALOGE("loop done - outputIndex=%d, inputIndex=%d", outputIndex, inputIndex);
410*ec779b8eSAndroid Build Coastguard Worker
411*ec779b8eSAndroid Build Coastguard Worker // if done with buffer, save samples
412*ec779b8eSAndroid Build Coastguard Worker if (inputIndex >= mBuffer.frameCount) {
413*ec779b8eSAndroid Build Coastguard Worker inputIndex -= mBuffer.frameCount;
414*ec779b8eSAndroid Build Coastguard Worker
415*ec779b8eSAndroid Build Coastguard Worker // ALOGE("buffer done, new input index %d", inputIndex);
416*ec779b8eSAndroid Build Coastguard Worker
417*ec779b8eSAndroid Build Coastguard Worker mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
418*ec779b8eSAndroid Build Coastguard Worker mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
419*ec779b8eSAndroid Build Coastguard Worker provider->releaseBuffer(&mBuffer);
420*ec779b8eSAndroid Build Coastguard Worker
421*ec779b8eSAndroid Build Coastguard Worker // verify that the releaseBuffer resets the buffer frameCount
422*ec779b8eSAndroid Build Coastguard Worker // ALOG_ASSERT(mBuffer.frameCount == 0);
423*ec779b8eSAndroid Build Coastguard Worker }
424*ec779b8eSAndroid Build Coastguard Worker }
425*ec779b8eSAndroid Build Coastguard Worker
426*ec779b8eSAndroid Build Coastguard Worker // ALOGE("output buffer full - outputIndex=%d, inputIndex=%d", outputIndex, inputIndex);
427*ec779b8eSAndroid Build Coastguard Worker
428*ec779b8eSAndroid Build Coastguard Worker resampleStereo16_exit:
429*ec779b8eSAndroid Build Coastguard Worker // save state
430*ec779b8eSAndroid Build Coastguard Worker mInputIndex = inputIndex;
431*ec779b8eSAndroid Build Coastguard Worker mPhaseFraction = phaseFraction;
432*ec779b8eSAndroid Build Coastguard Worker return outputIndex / 2 /* channels for stereo */;
433*ec779b8eSAndroid Build Coastguard Worker }
434*ec779b8eSAndroid Build Coastguard Worker
resampleMono16(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)435*ec779b8eSAndroid Build Coastguard Worker size_t AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,
436*ec779b8eSAndroid Build Coastguard Worker AudioBufferProvider* provider) {
437*ec779b8eSAndroid Build Coastguard Worker
438*ec779b8eSAndroid Build Coastguard Worker int32_t vl = mVolume[0];
439*ec779b8eSAndroid Build Coastguard Worker int32_t vr = mVolume[1];
440*ec779b8eSAndroid Build Coastguard Worker
441*ec779b8eSAndroid Build Coastguard Worker size_t inputIndex = mInputIndex;
442*ec779b8eSAndroid Build Coastguard Worker uint32_t phaseFraction = mPhaseFraction;
443*ec779b8eSAndroid Build Coastguard Worker uint32_t phaseIncrement = mPhaseIncrement;
444*ec779b8eSAndroid Build Coastguard Worker size_t outputIndex = 0;
445*ec779b8eSAndroid Build Coastguard Worker size_t outputSampleCount = outFrameCount * 2;
446*ec779b8eSAndroid Build Coastguard Worker size_t inFrameCount = getInFrameCountRequired(outFrameCount);
447*ec779b8eSAndroid Build Coastguard Worker
448*ec779b8eSAndroid Build Coastguard Worker // ALOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d",
449*ec779b8eSAndroid Build Coastguard Worker // outFrameCount, inputIndex, phaseFraction, phaseIncrement);
450*ec779b8eSAndroid Build Coastguard Worker while (outputIndex < outputSampleCount) {
451*ec779b8eSAndroid Build Coastguard Worker // buffer is empty, fetch a new one
452*ec779b8eSAndroid Build Coastguard Worker while (mBuffer.frameCount == 0) {
453*ec779b8eSAndroid Build Coastguard Worker mBuffer.frameCount = inFrameCount;
454*ec779b8eSAndroid Build Coastguard Worker provider->getNextBuffer(&mBuffer);
455*ec779b8eSAndroid Build Coastguard Worker if (mBuffer.raw == NULL) {
456*ec779b8eSAndroid Build Coastguard Worker mInputIndex = inputIndex;
457*ec779b8eSAndroid Build Coastguard Worker mPhaseFraction = phaseFraction;
458*ec779b8eSAndroid Build Coastguard Worker goto resampleMono16_exit;
459*ec779b8eSAndroid Build Coastguard Worker }
460*ec779b8eSAndroid Build Coastguard Worker // ALOGE("New buffer fetched: %d frames", mBuffer.frameCount);
461*ec779b8eSAndroid Build Coastguard Worker if (mBuffer.frameCount > inputIndex) break;
462*ec779b8eSAndroid Build Coastguard Worker
463*ec779b8eSAndroid Build Coastguard Worker inputIndex -= mBuffer.frameCount;
464*ec779b8eSAndroid Build Coastguard Worker mX0L = mBuffer.i16[mBuffer.frameCount-1];
465*ec779b8eSAndroid Build Coastguard Worker provider->releaseBuffer(&mBuffer);
466*ec779b8eSAndroid Build Coastguard Worker // mBuffer.frameCount == 0 now so we reload a new buffer
467*ec779b8eSAndroid Build Coastguard Worker }
468*ec779b8eSAndroid Build Coastguard Worker int16_t *in = mBuffer.i16;
469*ec779b8eSAndroid Build Coastguard Worker
470*ec779b8eSAndroid Build Coastguard Worker // handle boundary case
471*ec779b8eSAndroid Build Coastguard Worker while (inputIndex == 0) {
472*ec779b8eSAndroid Build Coastguard Worker // ALOGE("boundary case");
473*ec779b8eSAndroid Build Coastguard Worker int32_t sample = Interp(mX0L, in[0], phaseFraction);
474*ec779b8eSAndroid Build Coastguard Worker out[outputIndex++] += vl * sample;
475*ec779b8eSAndroid Build Coastguard Worker out[outputIndex++] += vr * sample;
476*ec779b8eSAndroid Build Coastguard Worker Advance(&inputIndex, &phaseFraction, phaseIncrement);
477*ec779b8eSAndroid Build Coastguard Worker if (outputIndex == outputSampleCount) {
478*ec779b8eSAndroid Build Coastguard Worker break;
479*ec779b8eSAndroid Build Coastguard Worker }
480*ec779b8eSAndroid Build Coastguard Worker }
481*ec779b8eSAndroid Build Coastguard Worker
482*ec779b8eSAndroid Build Coastguard Worker // process input samples
483*ec779b8eSAndroid Build Coastguard Worker // ALOGE("general case");
484*ec779b8eSAndroid Build Coastguard Worker
485*ec779b8eSAndroid Build Coastguard Worker #ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
486*ec779b8eSAndroid Build Coastguard Worker if (inputIndex + 2 < mBuffer.frameCount) {
487*ec779b8eSAndroid Build Coastguard Worker int32_t* maxOutPt;
488*ec779b8eSAndroid Build Coastguard Worker int32_t maxInIdx;
489*ec779b8eSAndroid Build Coastguard Worker
490*ec779b8eSAndroid Build Coastguard Worker maxOutPt = out + (outputSampleCount - 2);
491*ec779b8eSAndroid Build Coastguard Worker maxInIdx = (int32_t)mBuffer.frameCount - 2;
492*ec779b8eSAndroid Build Coastguard Worker AsmMono16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
493*ec779b8eSAndroid Build Coastguard Worker phaseFraction, phaseIncrement);
494*ec779b8eSAndroid Build Coastguard Worker }
495*ec779b8eSAndroid Build Coastguard Worker #endif // ASM_ARM_RESAMP1
496*ec779b8eSAndroid Build Coastguard Worker
497*ec779b8eSAndroid Build Coastguard Worker while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
498*ec779b8eSAndroid Build Coastguard Worker int32_t sample = Interp(in[inputIndex-1], in[inputIndex],
499*ec779b8eSAndroid Build Coastguard Worker phaseFraction);
500*ec779b8eSAndroid Build Coastguard Worker out[outputIndex++] += vl * sample;
501*ec779b8eSAndroid Build Coastguard Worker out[outputIndex++] += vr * sample;
502*ec779b8eSAndroid Build Coastguard Worker Advance(&inputIndex, &phaseFraction, phaseIncrement);
503*ec779b8eSAndroid Build Coastguard Worker }
504*ec779b8eSAndroid Build Coastguard Worker
505*ec779b8eSAndroid Build Coastguard Worker
506*ec779b8eSAndroid Build Coastguard Worker // ALOGE("loop done - outputIndex=%d, inputIndex=%d", outputIndex, inputIndex);
507*ec779b8eSAndroid Build Coastguard Worker
508*ec779b8eSAndroid Build Coastguard Worker // if done with buffer, save samples
509*ec779b8eSAndroid Build Coastguard Worker if (inputIndex >= mBuffer.frameCount) {
510*ec779b8eSAndroid Build Coastguard Worker inputIndex -= mBuffer.frameCount;
511*ec779b8eSAndroid Build Coastguard Worker
512*ec779b8eSAndroid Build Coastguard Worker // ALOGE("buffer done, new input index %d", inputIndex);
513*ec779b8eSAndroid Build Coastguard Worker
514*ec779b8eSAndroid Build Coastguard Worker mX0L = mBuffer.i16[mBuffer.frameCount-1];
515*ec779b8eSAndroid Build Coastguard Worker provider->releaseBuffer(&mBuffer);
516*ec779b8eSAndroid Build Coastguard Worker
517*ec779b8eSAndroid Build Coastguard Worker // verify that the releaseBuffer resets the buffer frameCount
518*ec779b8eSAndroid Build Coastguard Worker // ALOG_ASSERT(mBuffer.frameCount == 0);
519*ec779b8eSAndroid Build Coastguard Worker }
520*ec779b8eSAndroid Build Coastguard Worker }
521*ec779b8eSAndroid Build Coastguard Worker
522*ec779b8eSAndroid Build Coastguard Worker // ALOGE("output buffer full - outputIndex=%d, inputIndex=%d", outputIndex, inputIndex);
523*ec779b8eSAndroid Build Coastguard Worker
524*ec779b8eSAndroid Build Coastguard Worker resampleMono16_exit:
525*ec779b8eSAndroid Build Coastguard Worker // save state
526*ec779b8eSAndroid Build Coastguard Worker mInputIndex = inputIndex;
527*ec779b8eSAndroid Build Coastguard Worker mPhaseFraction = phaseFraction;
528*ec779b8eSAndroid Build Coastguard Worker return outputIndex;
529*ec779b8eSAndroid Build Coastguard Worker }
530*ec779b8eSAndroid Build Coastguard Worker
531*ec779b8eSAndroid Build Coastguard Worker #ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
532*ec779b8eSAndroid Build Coastguard Worker
533*ec779b8eSAndroid Build Coastguard Worker /*******************************************************************
534*ec779b8eSAndroid Build Coastguard Worker *
535*ec779b8eSAndroid Build Coastguard Worker * AsmMono16Loop
536*ec779b8eSAndroid Build Coastguard Worker * asm optimized monotonic loop version; one loop is 2 frames
537*ec779b8eSAndroid Build Coastguard Worker * Input:
538*ec779b8eSAndroid Build Coastguard Worker * in : pointer on input samples
539*ec779b8eSAndroid Build Coastguard Worker * maxOutPt : pointer on first not filled
540*ec779b8eSAndroid Build Coastguard Worker * maxInIdx : index on first not used
541*ec779b8eSAndroid Build Coastguard Worker * outputIndex : pointer on current output index
542*ec779b8eSAndroid Build Coastguard Worker * out : pointer on output buffer
543*ec779b8eSAndroid Build Coastguard Worker * inputIndex : pointer on current input index
544*ec779b8eSAndroid Build Coastguard Worker * vl, vr : left and right gain
545*ec779b8eSAndroid Build Coastguard Worker * phaseFraction : pointer on current phase fraction
546*ec779b8eSAndroid Build Coastguard Worker * phaseIncrement
547*ec779b8eSAndroid Build Coastguard Worker * Ouput:
548*ec779b8eSAndroid Build Coastguard Worker * outputIndex :
549*ec779b8eSAndroid Build Coastguard Worker * out : updated buffer
550*ec779b8eSAndroid Build Coastguard Worker * inputIndex : index of next to use
551*ec779b8eSAndroid Build Coastguard Worker * phaseFraction : phase fraction for next interpolation
552*ec779b8eSAndroid Build Coastguard Worker *
553*ec779b8eSAndroid Build Coastguard Worker *******************************************************************/
554*ec779b8eSAndroid Build Coastguard Worker __attribute__((noinline))
AsmMono16Loop(int16_t * in,int32_t * maxOutPt,int32_t maxInIdx,size_t & outputIndex,int32_t * out,size_t & inputIndex,int32_t vl,int32_t vr,uint32_t & phaseFraction,uint32_t phaseIncrement)555*ec779b8eSAndroid Build Coastguard Worker void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
556*ec779b8eSAndroid Build Coastguard Worker size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
557*ec779b8eSAndroid Build Coastguard Worker uint32_t &phaseFraction, uint32_t phaseIncrement)
558*ec779b8eSAndroid Build Coastguard Worker {
559*ec779b8eSAndroid Build Coastguard Worker (void)maxOutPt; // remove unused parameter warnings
560*ec779b8eSAndroid Build Coastguard Worker (void)maxInIdx;
561*ec779b8eSAndroid Build Coastguard Worker (void)outputIndex;
562*ec779b8eSAndroid Build Coastguard Worker (void)out;
563*ec779b8eSAndroid Build Coastguard Worker (void)inputIndex;
564*ec779b8eSAndroid Build Coastguard Worker (void)vl;
565*ec779b8eSAndroid Build Coastguard Worker (void)vr;
566*ec779b8eSAndroid Build Coastguard Worker (void)phaseFraction;
567*ec779b8eSAndroid Build Coastguard Worker (void)phaseIncrement;
568*ec779b8eSAndroid Build Coastguard Worker (void)in;
569*ec779b8eSAndroid Build Coastguard Worker #define MO_PARAM5 "36" // offset of parameter 5 (outputIndex)
570*ec779b8eSAndroid Build Coastguard Worker
571*ec779b8eSAndroid Build Coastguard Worker asm(
572*ec779b8eSAndroid Build Coastguard Worker "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
573*ec779b8eSAndroid Build Coastguard Worker // get parameters
574*ec779b8eSAndroid Build Coastguard Worker " ldr r6, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction
575*ec779b8eSAndroid Build Coastguard Worker " ldr r6, [r6]\n" // phaseFraction
576*ec779b8eSAndroid Build Coastguard Worker " ldr r7, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex
577*ec779b8eSAndroid Build Coastguard Worker " ldr r7, [r7]\n" // inputIndex
578*ec779b8eSAndroid Build Coastguard Worker " ldr r8, [sp, #" MO_PARAM5 " + 4]\n" // out
579*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex
580*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [r0]\n" // outputIndex
581*ec779b8eSAndroid Build Coastguard Worker " add r8, r8, r0, asl #2\n" // curOut
582*ec779b8eSAndroid Build Coastguard Worker " ldr r9, [sp, #" MO_PARAM5 " + 24]\n" // phaseIncrement
583*ec779b8eSAndroid Build Coastguard Worker " ldr r10, [sp, #" MO_PARAM5 " + 12]\n" // vl
584*ec779b8eSAndroid Build Coastguard Worker " ldr r11, [sp, #" MO_PARAM5 " + 16]\n" // vr
585*ec779b8eSAndroid Build Coastguard Worker
586*ec779b8eSAndroid Build Coastguard Worker // r0 pin, x0, Samp
587*ec779b8eSAndroid Build Coastguard Worker
588*ec779b8eSAndroid Build Coastguard Worker // r1 in
589*ec779b8eSAndroid Build Coastguard Worker // r2 maxOutPt
590*ec779b8eSAndroid Build Coastguard Worker // r3 maxInIdx
591*ec779b8eSAndroid Build Coastguard Worker
592*ec779b8eSAndroid Build Coastguard Worker // r4 x1, i1, i3, Out1
593*ec779b8eSAndroid Build Coastguard Worker // r5 out0
594*ec779b8eSAndroid Build Coastguard Worker
595*ec779b8eSAndroid Build Coastguard Worker // r6 frac
596*ec779b8eSAndroid Build Coastguard Worker // r7 inputIndex
597*ec779b8eSAndroid Build Coastguard Worker // r8 curOut
598*ec779b8eSAndroid Build Coastguard Worker
599*ec779b8eSAndroid Build Coastguard Worker // r9 inc
600*ec779b8eSAndroid Build Coastguard Worker // r10 vl
601*ec779b8eSAndroid Build Coastguard Worker // r11 vr
602*ec779b8eSAndroid Build Coastguard Worker
603*ec779b8eSAndroid Build Coastguard Worker // r12
604*ec779b8eSAndroid Build Coastguard Worker // r13 sp
605*ec779b8eSAndroid Build Coastguard Worker // r14
606*ec779b8eSAndroid Build Coastguard Worker
607*ec779b8eSAndroid Build Coastguard Worker // the following loop works on 2 frames
608*ec779b8eSAndroid Build Coastguard Worker
609*ec779b8eSAndroid Build Coastguard Worker "1:\n"
610*ec779b8eSAndroid Build Coastguard Worker " cmp r8, r2\n" // curOut - maxCurOut
611*ec779b8eSAndroid Build Coastguard Worker " bcs 2f\n"
612*ec779b8eSAndroid Build Coastguard Worker
613*ec779b8eSAndroid Build Coastguard Worker #define MO_ONE_FRAME \
614*ec779b8eSAndroid Build Coastguard Worker " add r0, r1, r7, asl #1\n" /* in + inputIndex */\
615*ec779b8eSAndroid Build Coastguard Worker " ldrsh r4, [r0]\n" /* in[inputIndex] */\
616*ec779b8eSAndroid Build Coastguard Worker " ldr r5, [r8]\n" /* out[outputIndex] */\
617*ec779b8eSAndroid Build Coastguard Worker " ldrsh r0, [r0, #-2]\n" /* in[inputIndex-1] */\
618*ec779b8eSAndroid Build Coastguard Worker " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\
619*ec779b8eSAndroid Build Coastguard Worker " sub r4, r4, r0\n" /* in[inputIndex] - in[inputIndex-1] */\
620*ec779b8eSAndroid Build Coastguard Worker " mov r4, r4, lsl #2\n" /* <<2 */\
621*ec779b8eSAndroid Build Coastguard Worker " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\
622*ec779b8eSAndroid Build Coastguard Worker " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\
623*ec779b8eSAndroid Build Coastguard Worker " add r0, r0, r4\n" /* x0 - (..) */\
624*ec779b8eSAndroid Build Coastguard Worker " mla r5, r0, r10, r5\n" /* vl*interp + out[] */\
625*ec779b8eSAndroid Build Coastguard Worker " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\
626*ec779b8eSAndroid Build Coastguard Worker " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\
627*ec779b8eSAndroid Build Coastguard Worker " mla r4, r0, r11, r4\n" /* vr*interp + out[] */\
628*ec779b8eSAndroid Build Coastguard Worker " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */\
629*ec779b8eSAndroid Build Coastguard Worker " str r4, [r8], #4\n" /* out[outputIndex++] = ... */
630*ec779b8eSAndroid Build Coastguard Worker
631*ec779b8eSAndroid Build Coastguard Worker MO_ONE_FRAME // frame 1
632*ec779b8eSAndroid Build Coastguard Worker MO_ONE_FRAME // frame 2
633*ec779b8eSAndroid Build Coastguard Worker
634*ec779b8eSAndroid Build Coastguard Worker " cmp r7, r3\n" // inputIndex - maxInIdx
635*ec779b8eSAndroid Build Coastguard Worker " bcc 1b\n"
636*ec779b8eSAndroid Build Coastguard Worker "2:\n"
637*ec779b8eSAndroid Build Coastguard Worker
638*ec779b8eSAndroid Build Coastguard Worker " bic r6, r6, #0xC0000000\n" // phaseFraction & ...
639*ec779b8eSAndroid Build Coastguard Worker // save modified values
640*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction
641*ec779b8eSAndroid Build Coastguard Worker " str r6, [r0]\n" // phaseFraction
642*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex
643*ec779b8eSAndroid Build Coastguard Worker " str r7, [r0]\n" // inputIndex
644*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" MO_PARAM5 " + 4]\n" // out
645*ec779b8eSAndroid Build Coastguard Worker " sub r8, r0\n" // curOut - out
646*ec779b8eSAndroid Build Coastguard Worker " asr r8, #2\n" // new outputIndex
647*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex
648*ec779b8eSAndroid Build Coastguard Worker " str r8, [r0]\n" // save outputIndex
649*ec779b8eSAndroid Build Coastguard Worker
650*ec779b8eSAndroid Build Coastguard Worker " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}\n"
651*ec779b8eSAndroid Build Coastguard Worker );
652*ec779b8eSAndroid Build Coastguard Worker }
653*ec779b8eSAndroid Build Coastguard Worker
654*ec779b8eSAndroid Build Coastguard Worker /*******************************************************************
655*ec779b8eSAndroid Build Coastguard Worker *
656*ec779b8eSAndroid Build Coastguard Worker * AsmStereo16Loop
657*ec779b8eSAndroid Build Coastguard Worker * asm optimized stereo loop version; one loop is 2 frames
658*ec779b8eSAndroid Build Coastguard Worker * Input:
659*ec779b8eSAndroid Build Coastguard Worker * in : pointer on input samples
660*ec779b8eSAndroid Build Coastguard Worker * maxOutPt : pointer on first not filled
661*ec779b8eSAndroid Build Coastguard Worker * maxInIdx : index on first not used
662*ec779b8eSAndroid Build Coastguard Worker * outputIndex : pointer on current output index
663*ec779b8eSAndroid Build Coastguard Worker * out : pointer on output buffer
664*ec779b8eSAndroid Build Coastguard Worker * inputIndex : pointer on current input index
665*ec779b8eSAndroid Build Coastguard Worker * vl, vr : left and right gain
666*ec779b8eSAndroid Build Coastguard Worker * phaseFraction : pointer on current phase fraction
667*ec779b8eSAndroid Build Coastguard Worker * phaseIncrement
668*ec779b8eSAndroid Build Coastguard Worker * Ouput:
669*ec779b8eSAndroid Build Coastguard Worker * outputIndex :
670*ec779b8eSAndroid Build Coastguard Worker * out : updated buffer
671*ec779b8eSAndroid Build Coastguard Worker * inputIndex : index of next to use
672*ec779b8eSAndroid Build Coastguard Worker * phaseFraction : phase fraction for next interpolation
673*ec779b8eSAndroid Build Coastguard Worker *
674*ec779b8eSAndroid Build Coastguard Worker *******************************************************************/
675*ec779b8eSAndroid Build Coastguard Worker __attribute__((noinline))
AsmStereo16Loop(int16_t * in,int32_t * maxOutPt,int32_t maxInIdx,size_t & outputIndex,int32_t * out,size_t & inputIndex,int32_t vl,int32_t vr,uint32_t & phaseFraction,uint32_t phaseIncrement)676*ec779b8eSAndroid Build Coastguard Worker void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
677*ec779b8eSAndroid Build Coastguard Worker size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
678*ec779b8eSAndroid Build Coastguard Worker uint32_t &phaseFraction, uint32_t phaseIncrement)
679*ec779b8eSAndroid Build Coastguard Worker {
680*ec779b8eSAndroid Build Coastguard Worker (void)maxOutPt; // remove unused parameter warnings
681*ec779b8eSAndroid Build Coastguard Worker (void)maxInIdx;
682*ec779b8eSAndroid Build Coastguard Worker (void)outputIndex;
683*ec779b8eSAndroid Build Coastguard Worker (void)out;
684*ec779b8eSAndroid Build Coastguard Worker (void)inputIndex;
685*ec779b8eSAndroid Build Coastguard Worker (void)vl;
686*ec779b8eSAndroid Build Coastguard Worker (void)vr;
687*ec779b8eSAndroid Build Coastguard Worker (void)phaseFraction;
688*ec779b8eSAndroid Build Coastguard Worker (void)phaseIncrement;
689*ec779b8eSAndroid Build Coastguard Worker (void)in;
690*ec779b8eSAndroid Build Coastguard Worker #define ST_PARAM5 "40" // offset of parameter 5 (outputIndex)
691*ec779b8eSAndroid Build Coastguard Worker asm(
692*ec779b8eSAndroid Build Coastguard Worker "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
693*ec779b8eSAndroid Build Coastguard Worker // get parameters
694*ec779b8eSAndroid Build Coastguard Worker " ldr r6, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction
695*ec779b8eSAndroid Build Coastguard Worker " ldr r6, [r6]\n" // phaseFraction
696*ec779b8eSAndroid Build Coastguard Worker " ldr r7, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex
697*ec779b8eSAndroid Build Coastguard Worker " ldr r7, [r7]\n" // inputIndex
698*ec779b8eSAndroid Build Coastguard Worker " ldr r8, [sp, #" ST_PARAM5 " + 4]\n" // out
699*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex
700*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [r0]\n" // outputIndex
701*ec779b8eSAndroid Build Coastguard Worker " add r8, r8, r0, asl #2\n" // curOut
702*ec779b8eSAndroid Build Coastguard Worker " ldr r9, [sp, #" ST_PARAM5 " + 24]\n" // phaseIncrement
703*ec779b8eSAndroid Build Coastguard Worker " ldr r10, [sp, #" ST_PARAM5 " + 12]\n" // vl
704*ec779b8eSAndroid Build Coastguard Worker " ldr r11, [sp, #" ST_PARAM5 " + 16]\n" // vr
705*ec779b8eSAndroid Build Coastguard Worker
706*ec779b8eSAndroid Build Coastguard Worker // r0 pin, x0, Samp
707*ec779b8eSAndroid Build Coastguard Worker
708*ec779b8eSAndroid Build Coastguard Worker // r1 in
709*ec779b8eSAndroid Build Coastguard Worker // r2 maxOutPt
710*ec779b8eSAndroid Build Coastguard Worker // r3 maxInIdx
711*ec779b8eSAndroid Build Coastguard Worker
712*ec779b8eSAndroid Build Coastguard Worker // r4 x1, i1, i3, out1
713*ec779b8eSAndroid Build Coastguard Worker // r5 out0
714*ec779b8eSAndroid Build Coastguard Worker
715*ec779b8eSAndroid Build Coastguard Worker // r6 frac
716*ec779b8eSAndroid Build Coastguard Worker // r7 inputIndex
717*ec779b8eSAndroid Build Coastguard Worker // r8 curOut
718*ec779b8eSAndroid Build Coastguard Worker
719*ec779b8eSAndroid Build Coastguard Worker // r9 inc
720*ec779b8eSAndroid Build Coastguard Worker // r10 vl
721*ec779b8eSAndroid Build Coastguard Worker // r11 vr
722*ec779b8eSAndroid Build Coastguard Worker
723*ec779b8eSAndroid Build Coastguard Worker // r12 temporary
724*ec779b8eSAndroid Build Coastguard Worker // r13 sp
725*ec779b8eSAndroid Build Coastguard Worker // r14
726*ec779b8eSAndroid Build Coastguard Worker
727*ec779b8eSAndroid Build Coastguard Worker "3:\n"
728*ec779b8eSAndroid Build Coastguard Worker " cmp r8, r2\n" // curOut - maxCurOut
729*ec779b8eSAndroid Build Coastguard Worker " bcs 4f\n"
730*ec779b8eSAndroid Build Coastguard Worker
731*ec779b8eSAndroid Build Coastguard Worker #define ST_ONE_FRAME \
732*ec779b8eSAndroid Build Coastguard Worker " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\
733*ec779b8eSAndroid Build Coastguard Worker \
734*ec779b8eSAndroid Build Coastguard Worker " add r0, r1, r7, asl #2\n" /* in + 2*inputIndex */\
735*ec779b8eSAndroid Build Coastguard Worker \
736*ec779b8eSAndroid Build Coastguard Worker " ldrsh r4, [r0]\n" /* in[2*inputIndex] */\
737*ec779b8eSAndroid Build Coastguard Worker " ldr r5, [r8]\n" /* out[outputIndex] */\
738*ec779b8eSAndroid Build Coastguard Worker " ldrsh r12, [r0, #-4]\n" /* in[2*inputIndex-2] */\
739*ec779b8eSAndroid Build Coastguard Worker " sub r4, r4, r12\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\
740*ec779b8eSAndroid Build Coastguard Worker " mov r4, r4, lsl #2\n" /* <<2 */\
741*ec779b8eSAndroid Build Coastguard Worker " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\
742*ec779b8eSAndroid Build Coastguard Worker " add r12, r12, r4\n" /* x0 - (..) */\
743*ec779b8eSAndroid Build Coastguard Worker " mla r5, r12, r10, r5\n" /* vl*interp + out[] */\
744*ec779b8eSAndroid Build Coastguard Worker " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\
745*ec779b8eSAndroid Build Coastguard Worker " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\
746*ec779b8eSAndroid Build Coastguard Worker \
747*ec779b8eSAndroid Build Coastguard Worker " ldrsh r12, [r0, #+2]\n" /* in[2*inputIndex+1] */\
748*ec779b8eSAndroid Build Coastguard Worker " ldrsh r0, [r0, #-2]\n" /* in[2*inputIndex-1] */\
749*ec779b8eSAndroid Build Coastguard Worker " sub r12, r12, r0\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\
750*ec779b8eSAndroid Build Coastguard Worker " mov r12, r12, lsl #2\n" /* <<2 */\
751*ec779b8eSAndroid Build Coastguard Worker " smulwt r12, r12, r6\n" /* (x1-x0)*.. */\
752*ec779b8eSAndroid Build Coastguard Worker " add r12, r0, r12\n" /* x0 - (..) */\
753*ec779b8eSAndroid Build Coastguard Worker " mla r4, r12, r11, r4\n" /* vr*interp + out[] */\
754*ec779b8eSAndroid Build Coastguard Worker " str r4, [r8], #4\n" /* out[outputIndex++] = ... */\
755*ec779b8eSAndroid Build Coastguard Worker \
756*ec779b8eSAndroid Build Coastguard Worker " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\
757*ec779b8eSAndroid Build Coastguard Worker " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */
758*ec779b8eSAndroid Build Coastguard Worker
759*ec779b8eSAndroid Build Coastguard Worker ST_ONE_FRAME // frame 1
760*ec779b8eSAndroid Build Coastguard Worker ST_ONE_FRAME // frame 1
761*ec779b8eSAndroid Build Coastguard Worker
762*ec779b8eSAndroid Build Coastguard Worker " cmp r7, r3\n" // inputIndex - maxInIdx
763*ec779b8eSAndroid Build Coastguard Worker " bcc 3b\n"
764*ec779b8eSAndroid Build Coastguard Worker "4:\n"
765*ec779b8eSAndroid Build Coastguard Worker
766*ec779b8eSAndroid Build Coastguard Worker " bic r6, r6, #0xC0000000\n" // phaseFraction & ...
767*ec779b8eSAndroid Build Coastguard Worker // save modified values
768*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction
769*ec779b8eSAndroid Build Coastguard Worker " str r6, [r0]\n" // phaseFraction
770*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex
771*ec779b8eSAndroid Build Coastguard Worker " str r7, [r0]\n" // inputIndex
772*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" ST_PARAM5 " + 4]\n" // out
773*ec779b8eSAndroid Build Coastguard Worker " sub r8, r0\n" // curOut - out
774*ec779b8eSAndroid Build Coastguard Worker " asr r8, #2\n" // new outputIndex
775*ec779b8eSAndroid Build Coastguard Worker " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex
776*ec779b8eSAndroid Build Coastguard Worker " str r8, [r0]\n" // save outputIndex
777*ec779b8eSAndroid Build Coastguard Worker
778*ec779b8eSAndroid Build Coastguard Worker " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}\n"
779*ec779b8eSAndroid Build Coastguard Worker );
780*ec779b8eSAndroid Build Coastguard Worker }
781*ec779b8eSAndroid Build Coastguard Worker
782*ec779b8eSAndroid Build Coastguard Worker #endif // ASM_ARM_RESAMP1
783*ec779b8eSAndroid Build Coastguard Worker
784*ec779b8eSAndroid Build Coastguard Worker
785*ec779b8eSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
786*ec779b8eSAndroid Build Coastguard Worker
787*ec779b8eSAndroid Build Coastguard Worker } // namespace android
788