1 /*
2 ** Copyright 2011, 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_NDEBUG 0
18 #define LOG_TAG "resampler"
19 
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <cutils/log.h>
23 #include <system/audio.h>
24 #include <audio_utils/resampler.h>
25 #include <speex/speex_resampler.h>
26 
27 
28 struct resampler {
29     struct resampler_itfe itfe;
30     SpeexResamplerState *speex_resampler;       // handle on speex resampler
31     struct resampler_buffer_provider *provider; // buffer provider installed by client
32     uint32_t in_sample_rate;                    // input sampling rate in Hz
33     uint32_t out_sample_rate;                   // output sampling rate in Hz
34     uint32_t channel_count;                     // number of channels (interleaved)
35     int16_t *in_buf;                            // input buffer
36     size_t in_buf_size;                         // input buffer size
37     size_t frames_in;                           // number of frames in input buffer
38     size_t frames_rq;                           // cached number of output frames
39     size_t frames_needed;                       // minimum number of input frames to produce
40                                                 // frames_rq output frames
41     int32_t speex_delay_ns;                     // delay introduced by speex resampler in ns
42 };
43 
44 
45 //------------------------------------------------------------------------------
46 // speex based resampler
47 //------------------------------------------------------------------------------
48 
resampler_reset(struct resampler_itfe * resampler)49 static void resampler_reset(struct resampler_itfe *resampler)
50 {
51     struct resampler *rsmp = (struct resampler *)resampler;
52 
53     rsmp->frames_in = 0;
54     rsmp->frames_rq = 0;
55 
56     if (rsmp != NULL && rsmp->speex_resampler != NULL) {
57         speex_resampler_reset_mem(rsmp->speex_resampler);
58     }
59 }
60 
resampler_delay_ns(struct resampler_itfe * resampler)61 static int32_t resampler_delay_ns(struct resampler_itfe *resampler)
62 {
63     struct resampler *rsmp = (struct resampler *)resampler;
64 
65     int32_t delay = (int32_t)((1000000000 * (int64_t)rsmp->frames_in) / rsmp->in_sample_rate);
66     delay += rsmp->speex_delay_ns;
67 
68     return delay;
69 }
70 
71 // outputs a number of frames less or equal to *outFrameCount and updates *outFrameCount
72 // with the actual number of frames produced.
resampler_resample_from_provider(struct resampler_itfe * resampler,int16_t * out,size_t * outFrameCount)73 int resampler_resample_from_provider(struct resampler_itfe *resampler,
74                        int16_t *out,
75                        size_t *outFrameCount)
76 {
77     struct resampler *rsmp = (struct resampler *)resampler;
78 
79     if (rsmp == NULL || out == NULL || outFrameCount == NULL) {
80         return -EINVAL;
81     }
82     if (rsmp->provider == NULL) {
83         *outFrameCount = 0;
84         return -ENOSYS;
85     }
86 
87     size_t framesRq = *outFrameCount;
88     // update and cache the number of frames needed at the input sampling rate to produce
89     // the number of frames requested at the output sampling rate
90     if (framesRq != rsmp->frames_rq) {
91         rsmp->frames_needed = (framesRq * rsmp->in_sample_rate) / rsmp->out_sample_rate + 1;
92         rsmp->frames_rq = framesRq;
93     }
94 
95     size_t framesWr = 0;
96     spx_uint32_t inFrames = 0;
97     while (framesWr < framesRq) {
98         if (rsmp->frames_in < rsmp->frames_needed) {
99             // make sure that the number of frames present in rsmp->in_buf (rsmp->frames_in) is at
100             // least the number of frames needed to produce the number of frames requested at
101             // the output sampling rate
102             if (rsmp->in_buf_size < rsmp->frames_needed) {
103                 rsmp->in_buf_size = rsmp->frames_needed;
104                 rsmp->in_buf = (int16_t *)realloc(rsmp->in_buf,
105                                         rsmp->in_buf_size * rsmp->channel_count * sizeof(int16_t));
106             }
107             struct resampler_buffer buf;
108             buf.frame_count = rsmp->frames_needed - rsmp->frames_in;
109             rsmp->provider->get_next_buffer(rsmp->provider, &buf);
110             if (buf.raw == NULL) {
111                 break;
112             }
113             memcpy(rsmp->in_buf + rsmp->frames_in * rsmp->channel_count,
114                     buf.raw,
115                     buf.frame_count * rsmp->channel_count * sizeof(int16_t));
116             rsmp->frames_in += buf.frame_count;
117             rsmp->provider->release_buffer(rsmp->provider, &buf);
118         }
119 
120         spx_uint32_t outFrames = framesRq - framesWr;
121         inFrames = rsmp->frames_in;
122         if (rsmp->channel_count == 1) {
123             speex_resampler_process_int(rsmp->speex_resampler,
124                                         0,
125                                         rsmp->in_buf,
126                                         &inFrames,
127                                         out + framesWr,
128                                         &outFrames);
129         } else {
130             speex_resampler_process_interleaved_int(rsmp->speex_resampler,
131                                         rsmp->in_buf,
132                                         &inFrames,
133                                         out + framesWr * rsmp->channel_count,
134                                         &outFrames);
135         }
136         framesWr += outFrames;
137         rsmp->frames_in -= inFrames;
138         ALOGW_IF((framesWr != framesRq) && (rsmp->frames_in != 0),
139                 "ReSampler::resample() remaining %zu frames in and %zu frames out",
140                 rsmp->frames_in, (framesRq - framesWr));
141     }
142     if (rsmp->frames_in) {
143         memmove(rsmp->in_buf,
144                 rsmp->in_buf + inFrames * rsmp->channel_count,
145                 rsmp->frames_in * rsmp->channel_count * sizeof(int16_t));
146     }
147     *outFrameCount = framesWr;
148 
149     return 0;
150 }
151 
resampler_resample_from_input(struct resampler_itfe * resampler,int16_t * in,size_t * inFrameCount,int16_t * out,size_t * outFrameCount)152 int resampler_resample_from_input(struct resampler_itfe *resampler,
153                                   int16_t *in,
154                                   size_t *inFrameCount,
155                                   int16_t *out,
156                                   size_t *outFrameCount)
157 {
158     struct resampler *rsmp = (struct resampler *)resampler;
159 
160     if (rsmp == NULL || in == NULL || inFrameCount == NULL ||
161             out == NULL || outFrameCount == NULL) {
162         return -EINVAL;
163     }
164     if (rsmp->provider != NULL) {
165         *outFrameCount = 0;
166         return -ENOSYS;
167     }
168 
169     if (rsmp->channel_count == 1) {
170         speex_resampler_process_int(rsmp->speex_resampler,
171                                     0,
172                                     in,
173                                     (spx_uint32_t *)inFrameCount,
174                                     out,
175                                     (spx_uint32_t *)outFrameCount);
176     } else {
177         speex_resampler_process_interleaved_int(rsmp->speex_resampler,
178                                                 in,
179                                                 (spx_uint32_t *)inFrameCount,
180                                                 out,
181                                                 (spx_uint32_t *)outFrameCount);
182     }
183 
184     ALOGV("resampler_resample_from_input() DONE in %zu out %zu", *inFrameCount, *outFrameCount);
185 
186     return 0;
187 }
188 
create_resampler(uint32_t inSampleRate,uint32_t outSampleRate,uint32_t channelCount,uint32_t quality,struct resampler_buffer_provider * provider,struct resampler_itfe ** resampler)189 int create_resampler(uint32_t inSampleRate,
190                     uint32_t outSampleRate,
191                     uint32_t channelCount,
192                     uint32_t quality,
193                     struct resampler_buffer_provider* provider,
194                     struct resampler_itfe **resampler)
195 {
196     int error;
197     struct resampler *rsmp;
198 
199     ALOGV("create_resampler() In SR %d Out SR %d channels %d",
200          inSampleRate, outSampleRate, channelCount);
201 
202     if (resampler == NULL) {
203         return -EINVAL;
204     }
205 
206     *resampler = NULL;
207 
208     if (quality <= RESAMPLER_QUALITY_MIN || quality >= RESAMPLER_QUALITY_MAX) {
209         return -EINVAL;
210     }
211 
212     rsmp = (struct resampler *)calloc(1, sizeof(struct resampler));
213 
214     rsmp->speex_resampler = speex_resampler_init(channelCount,
215                                       inSampleRate,
216                                       outSampleRate,
217                                       quality,
218                                       &error);
219     if (rsmp->speex_resampler == NULL) {
220         ALOGW("ReSampler: Cannot create speex resampler: %s", speex_resampler_strerror(error));
221         free(rsmp);
222         return -ENODEV;
223     }
224 
225     rsmp->itfe.reset = resampler_reset;
226     rsmp->itfe.resample_from_provider = resampler_resample_from_provider;
227     rsmp->itfe.resample_from_input = resampler_resample_from_input;
228     rsmp->itfe.delay_ns = resampler_delay_ns;
229 
230     rsmp->provider = provider;
231     rsmp->in_sample_rate = inSampleRate;
232     rsmp->out_sample_rate = outSampleRate;
233     rsmp->channel_count = channelCount;
234     rsmp->in_buf = NULL;
235     rsmp->in_buf_size = 0;
236 
237     resampler_reset(&rsmp->itfe);
238 
239     int frames = speex_resampler_get_input_latency(rsmp->speex_resampler);
240     rsmp->speex_delay_ns = (int32_t)((1000000000 * (int64_t)frames) / rsmp->in_sample_rate);
241     frames = speex_resampler_get_output_latency(rsmp->speex_resampler);
242     rsmp->speex_delay_ns += (int32_t)((1000000000 * (int64_t)frames) / rsmp->out_sample_rate);
243 
244     *resampler = &rsmp->itfe;
245     ALOGV("create_resampler() DONE rsmp %p &rsmp->itfe %p speex %p",
246          rsmp, &rsmp->itfe, rsmp->speex_resampler);
247     return 0;
248 }
249 
release_resampler(struct resampler_itfe * resampler)250 void release_resampler(struct resampler_itfe *resampler)
251 {
252     struct resampler *rsmp = (struct resampler *)resampler;
253 
254     if (rsmp == NULL) {
255         return;
256     }
257 
258     free(rsmp->in_buf);
259 
260     if (rsmp->speex_resampler != NULL) {
261         speex_resampler_destroy(rsmp->speex_resampler);
262     }
263     free(rsmp);
264 }
265