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
29struct 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
50static 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
62static 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.
74int 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
153int 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
190int 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
251void 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}
266