• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "AudioSRC"
18 
19 #include <stdint.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <cutils/log.h>
23 
24 #include "AudioResampler.h"
25 #include "AudioResamplerCubic.h"
26 
27 namespace android {
28 // ----------------------------------------------------------------------------
29 
init()30 void AudioResamplerCubic::init() {
31     memset(&left, 0, sizeof(state));
32     memset(&right, 0, sizeof(state));
33 }
34 
resample(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)35 void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount,
36         AudioBufferProvider* provider) {
37 
38     // should never happen, but we overflow if it does
39     // ALOG_ASSERT(outFrameCount < 32767);
40 
41     // select the appropriate resampler
42     switch (mChannelCount) {
43     case 1:
44         resampleMono16(out, outFrameCount, provider);
45         break;
46     case 2:
47         resampleStereo16(out, outFrameCount, provider);
48         break;
49     }
50 }
51 
resampleStereo16(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)52 void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount,
53         AudioBufferProvider* provider) {
54 
55     int32_t vl = mVolume[0];
56     int32_t vr = mVolume[1];
57 
58     size_t inputIndex = mInputIndex;
59     uint32_t phaseFraction = mPhaseFraction;
60     uint32_t phaseIncrement = mPhaseIncrement;
61     size_t outputIndex = 0;
62     size_t outputSampleCount = outFrameCount * 2;
63     size_t inFrameCount = getInFrameCountRequired(outFrameCount);
64 
65     // fetch first buffer
66     if (mBuffer.frameCount == 0) {
67         mBuffer.frameCount = inFrameCount;
68         provider->getNextBuffer(&mBuffer, mPTS);
69         if (mBuffer.raw == NULL) {
70             return;
71         }
72         // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
73     }
74     int16_t *in = mBuffer.i16;
75 
76     while (outputIndex < outputSampleCount) {
77         int32_t sample;
78         int32_t x;
79 
80         // calculate output sample
81         x = phaseFraction >> kPreInterpShift;
82         out[outputIndex++] += vl * interp(&left, x);
83         out[outputIndex++] += vr * interp(&right, x);
84         // out[outputIndex++] += vr * in[inputIndex*2];
85 
86         // increment phase
87         phaseFraction += phaseIncrement;
88         uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
89         phaseFraction &= kPhaseMask;
90 
91         // time to fetch another sample
92         while (indexIncrement--) {
93 
94             inputIndex++;
95             if (inputIndex == mBuffer.frameCount) {
96                 inputIndex = 0;
97                 provider->releaseBuffer(&mBuffer);
98                 mBuffer.frameCount = inFrameCount;
99                 provider->getNextBuffer(&mBuffer,
100                                         calculateOutputPTS(outputIndex / 2));
101                 if (mBuffer.raw == NULL) {
102                     goto save_state;  // ugly, but efficient
103                 }
104                 in = mBuffer.i16;
105                 // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount);
106             }
107 
108             // advance sample state
109             advance(&left, in[inputIndex*2]);
110             advance(&right, in[inputIndex*2+1]);
111         }
112     }
113 
114 save_state:
115     // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
116     mInputIndex = inputIndex;
117     mPhaseFraction = phaseFraction;
118 }
119 
resampleMono16(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)120 void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount,
121         AudioBufferProvider* provider) {
122 
123     int32_t vl = mVolume[0];
124     int32_t vr = mVolume[1];
125 
126     size_t inputIndex = mInputIndex;
127     uint32_t phaseFraction = mPhaseFraction;
128     uint32_t phaseIncrement = mPhaseIncrement;
129     size_t outputIndex = 0;
130     size_t outputSampleCount = outFrameCount * 2;
131     size_t inFrameCount = getInFrameCountRequired(outFrameCount);
132 
133     // fetch first buffer
134     if (mBuffer.frameCount == 0) {
135         mBuffer.frameCount = inFrameCount;
136         provider->getNextBuffer(&mBuffer, mPTS);
137         if (mBuffer.raw == NULL) {
138             return;
139         }
140         // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount);
141     }
142     int16_t *in = mBuffer.i16;
143 
144     while (outputIndex < outputSampleCount) {
145         int32_t sample;
146         int32_t x;
147 
148         // calculate output sample
149         x = phaseFraction >> kPreInterpShift;
150         sample = interp(&left, x);
151         out[outputIndex++] += vl * sample;
152         out[outputIndex++] += vr * sample;
153 
154         // increment phase
155         phaseFraction += phaseIncrement;
156         uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
157         phaseFraction &= kPhaseMask;
158 
159         // time to fetch another sample
160         while (indexIncrement--) {
161 
162             inputIndex++;
163             if (inputIndex == mBuffer.frameCount) {
164                 inputIndex = 0;
165                 provider->releaseBuffer(&mBuffer);
166                 mBuffer.frameCount = inFrameCount;
167                 provider->getNextBuffer(&mBuffer,
168                                         calculateOutputPTS(outputIndex / 2));
169                 if (mBuffer.raw == NULL) {
170                     goto save_state;  // ugly, but efficient
171                 }
172                 // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
173                 in = mBuffer.i16;
174             }
175 
176             // advance sample state
177             advance(&left, in[inputIndex]);
178         }
179     }
180 
181 save_state:
182     // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
183     mInputIndex = inputIndex;
184     mPhaseFraction = phaseFraction;
185 }
186 
187 // ----------------------------------------------------------------------------
188 }
189 ; // namespace android
190