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 "AudioResamplerCubic"
18 
19 #include <stdint.h>
20 #include <string.h>
21 #include <sys/types.h>
22 
23 #include <log/log.h>
24 
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 size_t 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         return resampleMono16(out, outFrameCount, provider);
45     case 2:
46         return resampleStereo16(out, outFrameCount, provider);
47     default:
48         LOG_ALWAYS_FATAL("invalid channel count: %d", mChannelCount);
49         return 0;
50     }
51 }
52 
resampleStereo16(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)53 size_t AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount,
54         AudioBufferProvider* provider) {
55 
56     int32_t vl = mVolume[0];
57     int32_t vr = mVolume[1];
58 
59     size_t inputIndex = mInputIndex;
60     uint32_t phaseFraction = mPhaseFraction;
61     uint32_t phaseIncrement = mPhaseIncrement;
62     size_t outputIndex = 0;
63     size_t outputSampleCount = outFrameCount * 2;
64     size_t inFrameCount = getInFrameCountRequired(outFrameCount);
65 
66     // fetch first buffer
67     if (mBuffer.frameCount == 0) {
68         mBuffer.frameCount = inFrameCount;
69         provider->getNextBuffer(&mBuffer);
70         if (mBuffer.raw == NULL) {
71             return 0;
72         }
73         // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
74     }
75     int16_t *in = mBuffer.i16;
76 
77     while (outputIndex < outputSampleCount) {
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                 if (mBuffer.raw == NULL) {
101                     goto save_state;  // ugly, but efficient
102                 }
103                 in = mBuffer.i16;
104                 // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount);
105             }
106 
107             // advance sample state
108             advance(&left, in[inputIndex*2]);
109             advance(&right, in[inputIndex*2+1]);
110         }
111     }
112 
113 save_state:
114     // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
115     mInputIndex = inputIndex;
116     mPhaseFraction = phaseFraction;
117     return outputIndex / 2 /* channels for stereo */;
118 }
119 
resampleMono16(int32_t * out,size_t outFrameCount,AudioBufferProvider * provider)120 size_t 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);
137         if (mBuffer.raw == NULL) {
138             return 0;
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                 if (mBuffer.raw == NULL) {
169                     goto save_state;  // ugly, but efficient
170                 }
171                 // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
172                 in = mBuffer.i16;
173             }
174 
175             // advance sample state
176             advance(&left, in[inputIndex]);
177         }
178     }
179 
180 save_state:
181     // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
182     mInputIndex = inputIndex;
183     mPhaseFraction = phaseFraction;
184     return outputIndex;
185 }
186 
187 // ----------------------------------------------------------------------------
188 } // namespace android
189