OSDN Git Service

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