• 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 = (outFrameCount*mInSampleRate)/mSampleRate;
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         // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
72     }
73     int16_t *in = mBuffer.i16;
74 
75     while (outputIndex < outputSampleCount) {
76         int32_t sample;
77         int32_t x;
78 
79         // calculate output sample
80         x = phaseFraction >> kPreInterpShift;
81         out[outputIndex++] += vl * interp(&left, x);
82         out[outputIndex++] += vr * interp(&right, x);
83         // out[outputIndex++] += vr * in[inputIndex*2];
84 
85         // increment phase
86         phaseFraction += phaseIncrement;
87         uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
88         phaseFraction &= kPhaseMask;
89 
90         // time to fetch another sample
91         while (indexIncrement--) {
92 
93             inputIndex++;
94             if (inputIndex == mBuffer.frameCount) {
95                 inputIndex = 0;
96                 provider->releaseBuffer(&mBuffer);
97                 mBuffer.frameCount = inFrameCount;
98                 provider->getNextBuffer(&mBuffer,
99                                         calculateOutputPTS(outputIndex / 2));
100                 if (mBuffer.raw == NULL)
101                     goto save_state;  // ugly, but efficient
102                 in = mBuffer.i16;
103                 // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount);
104             }
105 
106             // advance sample state
107             advance(&left, in[inputIndex*2]);
108             advance(&right, in[inputIndex*2+1]);
109         }
110     }
111 
112 save_state:
113     // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
114     mInputIndex = inputIndex;
115     mPhaseFraction = phaseFraction;
116 }
117 
resampleMono16(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)118 void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount,
119         AudioBufferProvider* provider) {
120 
121     int32_t vl = mVolume[0];
122     int32_t vr = mVolume[1];
123 
124     size_t inputIndex = mInputIndex;
125     uint32_t phaseFraction = mPhaseFraction;
126     uint32_t phaseIncrement = mPhaseIncrement;
127     size_t outputIndex = 0;
128     size_t outputSampleCount = outFrameCount * 2;
129     size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
130 
131     // fetch first buffer
132     if (mBuffer.frameCount == 0) {
133         mBuffer.frameCount = inFrameCount;
134         provider->getNextBuffer(&mBuffer, mPTS);
135         if (mBuffer.raw == NULL)
136             return;
137         // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount);
138     }
139     int16_t *in = mBuffer.i16;
140 
141     while (outputIndex < outputSampleCount) {
142         int32_t sample;
143         int32_t x;
144 
145         // calculate output sample
146         x = phaseFraction >> kPreInterpShift;
147         sample = interp(&left, x);
148         out[outputIndex++] += vl * sample;
149         out[outputIndex++] += vr * sample;
150 
151         // increment phase
152         phaseFraction += phaseIncrement;
153         uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
154         phaseFraction &= kPhaseMask;
155 
156         // time to fetch another sample
157         while (indexIncrement--) {
158 
159             inputIndex++;
160             if (inputIndex == mBuffer.frameCount) {
161                 inputIndex = 0;
162                 provider->releaseBuffer(&mBuffer);
163                 mBuffer.frameCount = inFrameCount;
164                 provider->getNextBuffer(&mBuffer,
165                                         calculateOutputPTS(outputIndex / 2));
166                 if (mBuffer.raw == NULL)
167                     goto save_state;  // ugly, but efficient
168                 // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
169                 in = mBuffer.i16;
170             }
171 
172             // advance sample state
173             advance(&left, in[inputIndex]);
174         }
175     }
176 
177 save_state:
178     // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
179     mInputIndex = inputIndex;
180     mPhaseFraction = phaseFraction;
181 }
182 
183 // ----------------------------------------------------------------------------
184 }
185 ; // namespace android
186