blob: 7282aa9a67bf96153848d16306330ac7541ab781 [file] [log] [blame]
Eric Laurentb3184d72011-08-17 18:36:09 -07001/*
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
28struct 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
49static 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
61static 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.
73int 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) {
Eric Laurentcdde1972011-11-28 10:57:39 -080091 rsmp->frames_needed = (framesRq * rsmp->in_sample_rate) / rsmp->out_sample_rate + 1;
Eric Laurentb3184d72011-08-17 18:36:09 -070092 rsmp->frames_rq = framesRq;
93 }
94
95 size_t framesWr = 0;
Kévin PETIT96d859c2014-03-26 11:56:32 +000096 spx_uint32_t inFrames = 0;
Eric Laurentb3184d72011-08-17 18:36:09 -070097 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
Kévin PETIT96d859c2014-03-26 11:56:32 +0000120 spx_uint32_t outFrames = framesRq - framesWr;
Eric Laurentb3184d72011-08-17 18:36:09 -0700121 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;
Steve Blockd0e47292012-01-06 10:23:51 +0000138 ALOGW_IF((framesWr != framesRq) && (rsmp->frames_in != 0),
Kévin PETIT96d859c2014-03-26 11:56:32 +0000139 "ReSampler::resample() remaining %zu frames in and %zu frames out",
Eric Laurentb3184d72011-08-17 18:36:09 -0700140 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
152int 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,
Eric Laurent7e71a032014-05-02 09:20:08 -0700173 (spx_uint32_t *)inFrameCount,
Eric Laurentb3184d72011-08-17 18:36:09 -0700174 out,
Eric Laurent7e71a032014-05-02 09:20:08 -0700175 (spx_uint32_t *)outFrameCount);
Eric Laurentb3184d72011-08-17 18:36:09 -0700176 } else {
177 speex_resampler_process_interleaved_int(rsmp->speex_resampler,
178 in,
Eric Laurent7e71a032014-05-02 09:20:08 -0700179 (spx_uint32_t *)inFrameCount,
Eric Laurentb3184d72011-08-17 18:36:09 -0700180 out,
Eric Laurent7e71a032014-05-02 09:20:08 -0700181 (spx_uint32_t *)outFrameCount);
Eric Laurentb3184d72011-08-17 18:36:09 -0700182 }
183
Kévin PETIT96d859c2014-03-26 11:56:32 +0000184 ALOGV("resampler_resample_from_input() DONE in %zu out %zu", *inFrameCount, *outFrameCount);
Eric Laurentb3184d72011-08-17 18:36:09 -0700185
186 return 0;
187}
188
189int 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
Steve Block473d4a52011-10-26 11:12:08 +0100199 ALOGV("create_resampler() In SR %d Out SR %d channels %d",
Eric Laurentb3184d72011-08-17 18:36:09 -0700200 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) {
Steve Blockd0e47292012-01-06 10:23:51 +0000220 ALOGW("ReSampler: Cannot create speex resampler: %s", speex_resampler_strerror(error));
Glenn Kastenbea20ac2012-02-14 13:56:42 -0800221 free(rsmp);
Eric Laurentb3184d72011-08-17 18:36:09 -0700222 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;
Steve Block473d4a52011-10-26 11:12:08 +0100245 ALOGV("create_resampler() DONE rsmp %p &rsmp->itfe %p speex %p",
Eric Laurentb3184d72011-08-17 18:36:09 -0700246 rsmp, &rsmp->itfe, rsmp->speex_resampler);
247 return 0;
248}
249
250void 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}