resampler.c revision d0e472977acbfd5c8d56d506f40039f451f84f8f
1c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler/*
2c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** Copyright 2011, The Android Open-Source Project
3c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler**
4c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** Licensed under the Apache License, Version 2.0 (the "License");
5c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** you may not use this file except in compliance with the License.
6c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** You may obtain a copy of the License at
7c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler**
8c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler**     http://www.apache.org/licenses/LICENSE-2.0
9c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler**
10c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** Unless required by applicable law or agreed to in writing, software
11c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** distributed under the License is distributed on an "AS IS" BASIS,
12c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** See the License for the specific language governing permissions and
14c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler** limitations under the License.
15c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler*/
16c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
17c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler//#define LOG_NDEBUG 0
18c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler#define LOG_TAG "resampler"
19ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert
20ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert#include <errno.h>
21ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert#include <stdlib.h>
22ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert#include <cutils/log.h>
2390dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock#include <system/audio.h>
24ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert#include <audio_utils/resampler.h>
2590dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock#include <speex/speex_resampler.h>
264560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson
27ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert
2817b4ca405a8b0d154f4d8354ab62044cd25b2204Daniel Sandlerstruct resampler {
2990dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    struct resampler_itfe itfe;
30c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler    SpeexResamplerState *speex_resampler;       // handle on speex resampler
31c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler    struct resampler_buffer_provider *provider; // buffer provider installed by client
3278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    uint32_t in_sample_rate;                    // input sampling rate in Hz
3378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    uint32_t out_sample_rate;                   // output sampling rate in Hz
3417b4ca405a8b0d154f4d8354ab62044cd25b2204Daniel Sandler    uint32_t channel_count;                     // number of channels (interleaved)
35e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    int16_t *in_buf;                            // input buffer
36e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    size_t in_buf_size;                         // input buffer size
37c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler    size_t frames_in;                           // number of frames in input buffer
38e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    size_t frames_rq;                           // cached number of output frames
394560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson    size_t frames_needed;                       // minimum number of input frames to produce
40c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson                                                // frames_rq output frames
41c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson    int32_t speex_delay_ns;                     // delay introduced by speex resampler in ns
42e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler};
439df9aff951dce59b327f56f5821386a7b40798bdIsaac Katzenelson
44c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler
4578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein//------------------------------------------------------------------------------
464560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson// speex based resampler
47ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert//------------------------------------------------------------------------------
48ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert
49ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albertstatic void resampler_reset(struct resampler_itfe *resampler)
50ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert{
51ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert    struct resampler *rsmp = (struct resampler *)resampler;
52ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert
53ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert    rsmp->frames_in = 0;
54eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    rsmp->frames_rq = 0;
55eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
56eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    if (rsmp != NULL && rsmp->speex_resampler != NULL) {
57eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        speex_resampler_reset_mem(rsmp->speex_resampler);
58eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    }
59eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas}
60eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
61eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultasstatic int32_t resampler_delay_ns(struct resampler_itfe *resampler)
62eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas{
63eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    struct resampler *rsmp = (struct resampler *)resampler;
64eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
65eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    int32_t delay = (int32_t)((1000000000 * (int64_t)rsmp->frames_in) / rsmp->in_sample_rate);
66eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    delay += rsmp->speex_delay_ns;
67eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
68eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    return delay;
69eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas}
70eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
71eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas// outputs a number of frames less or equal to *outFrameCount and updates *outFrameCount
72eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas// with the actual number of frames produced.
73eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultasint resampler_resample_from_provider(struct resampler_itfe *resampler,
74eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas                       int16_t *out,
75eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas                       size_t *outFrameCount)
76eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas{
77eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas    struct resampler *rsmp = (struct resampler *)resampler;
78eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
7990dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    if (rsmp == NULL || out == NULL || outFrameCount == NULL) {
8090dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        return -EINVAL;
8178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    }
8290dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    if (rsmp->provider == NULL) {
834560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson        *outFrameCount = 0;
8490dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        return -ENOSYS;
8590dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    }
8690dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock
8790dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    size_t framesRq = *outFrameCount;
88c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson    // update and cache the number of frames needed at the input sampling rate to produce
89c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson    // the number of frames requested at the output sampling rate
90c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson    if (framesRq != rsmp->frames_rq) {
919a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler        rsmp->frames_needed = (framesRq * rsmp->in_sample_rate) / rsmp->out_sample_rate + 1;
929a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler        rsmp->frames_rq = framesRq;
93e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler    }
9490dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock
9590dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    size_t framesWr = 0;
9690dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    size_t inFrames = 0;
9790dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    while (framesWr < framesRq) {
9890dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        if (rsmp->frames_in < rsmp->frames_needed) {
9990dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock            // make sure that the number of frames present in rsmp->in_buf (rsmp->frames_in) is at
100e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler            // least the number of frames needed to produce the number of frames requested at
101e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler            // the output sampling rate
102e269bd8658721a71fd9d42084b280042c5258945Daniel Sandler            if (rsmp->in_buf_size < rsmp->frames_needed) {
10390dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock                rsmp->in_buf_size = rsmp->frames_needed;
10490dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock                rsmp->in_buf = (int16_t *)realloc(rsmp->in_buf,
10590dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock                                        rsmp->in_buf_size * rsmp->channel_count * sizeof(int16_t));
106c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler            }
10757ca681913fa5b9cd86a7342a91cfe4cc5b910dfDaniel Sandler            struct resampler_buffer buf;
10857ca681913fa5b9cd86a7342a91cfe4cc5b910dfDaniel Sandler            buf.frame_count = rsmp->frames_needed - rsmp->frames_in;
10957ca681913fa5b9cd86a7342a91cfe4cc5b910dfDaniel Sandler            rsmp->provider->get_next_buffer(rsmp->provider, &buf);
1103d6adf080cb4a1469244e393807f6921b9f1149bJohn Spurlock            if (buf.raw == NULL) {
1111a7820902f3a6428f0bb586f8f1b5a2824838cb0Daniel Sandler                break;
1129a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler            }
1139a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler            memcpy(rsmp->in_buf + rsmp->frames_in * rsmp->channel_count,
114eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas                    buf.raw,
115eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas                    buf.frame_count * rsmp->channel_count * sizeof(int16_t));
116eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas            rsmp->frames_in += buf.frame_count;
117eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas            rsmp->provider->release_buffer(rsmp->provider, &buf);
118eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        }
119eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas
120eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        size_t outFrames = framesRq - framesWr;
121ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert        inFrames = rsmp->frames_in;
122ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert        if (rsmp->channel_count == 1) {
123ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert            speex_resampler_process_int(rsmp->speex_resampler,
124ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert                                        0,
1250d4404c04475a66c9bcbda6960bd94597985b785Daniel Sandler                                        rsmp->in_buf,
126c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler                                        &inFrames,
127c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler                                        out + framesWr,
128c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler                                        &outFrames);
12990dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock        } else {
13090dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock            speex_resampler_process_interleaved_int(rsmp->speex_resampler,
13190dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock                                        rsmp->in_buf,
13290dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock                                        &inFrames,
133c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler                                        out + framesWr * rsmp->channel_count,
134ed2084787cec0f02e6cead215d409d6f2f60f737Alon Albert                                        &outFrames);
135eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        }
136eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        framesWr += outFrames;
137eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        rsmp->frames_in -= inFrames;
138eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas        ALOGW_IF((framesWr != framesRq) && (rsmp->frames_in != 0),
139c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler                "ReSampler::resample() remaining %d frames in and %d frames out",
140c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler                rsmp->frames_in, (framesRq - framesWr));
1414560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson    }
142b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson    if (rsmp->frames_in) {
14378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        memmove(rsmp->in_buf,
144b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson                rsmp->in_buf + inFrames * rsmp->channel_count,
14578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                rsmp->frames_in * rsmp->channel_count * sizeof(int16_t));
14678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    }
14778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    *outFrameCount = framesWr;
14878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
1498f873a2bca1277f37cc8d08655d73385e5508232Daniel Sandler    return 0;
1509a1fd04f15b653a6600629aee41c7d3fd7d843b3Daniel Sandler}
15190dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock
15290dc136d444ba29fe8db6b20872022b18f18dc94John Spurlockint resampler_resample_from_input(struct resampler_itfe *resampler,
153b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson                                  int16_t *in,
154b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson                                  size_t *inFrameCount,
1554560461b08b1660fa5776523d8344df0d8d23f1dItzhak Katzenelson                                  int16_t *out,
15690dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock                                  size_t *outFrameCount)
15790dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock{
15878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    struct resampler *rsmp = (struct resampler *)resampler;
15978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
160c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson    if (rsmp == NULL || in == NULL || inFrameCount == NULL ||
161eb3a1f0714e209a8335d84142778465aa6b44c5cRobyn Coultas            out == NULL || outFrameCount == NULL) {
162c5b45b80a280794ca131b9857c5885c337d4d6e1Isaac Katzenelson        return -EINVAL;
16390dc136d444ba29fe8db6b20872022b18f18dc94John Spurlock    }
164c57490dff5bfbf601d4b708fdae029df99f807b2Daniel Sandler    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                                    inFrameCount,
174                                    out,
175                                    outFrameCount);
176    } else {
177        speex_resampler_process_interleaved_int(rsmp->speex_resampler,
178                                                in,
179                                                inFrameCount,
180                                                out,
181                                                outFrameCount);
182    }
183
184    ALOGV("resampler_resample_from_input() DONE in %d out % d", *inFrameCount, *outFrameCount);
185
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
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        return -ENODEV;
222    }
223
224    rsmp->itfe.reset = resampler_reset;
225    rsmp->itfe.resample_from_provider = resampler_resample_from_provider;
226    rsmp->itfe.resample_from_input = resampler_resample_from_input;
227    rsmp->itfe.delay_ns = resampler_delay_ns;
228
229    rsmp->provider = provider;
230    rsmp->in_sample_rate = inSampleRate;
231    rsmp->out_sample_rate = outSampleRate;
232    rsmp->channel_count = channelCount;
233    rsmp->in_buf = NULL;
234    rsmp->in_buf_size = 0;
235
236    resampler_reset(&rsmp->itfe);
237
238    int frames = speex_resampler_get_input_latency(rsmp->speex_resampler);
239    rsmp->speex_delay_ns = (int32_t)((1000000000 * (int64_t)frames) / rsmp->in_sample_rate);
240    frames = speex_resampler_get_output_latency(rsmp->speex_resampler);
241    rsmp->speex_delay_ns += (int32_t)((1000000000 * (int64_t)frames) / rsmp->out_sample_rate);
242
243    *resampler = &rsmp->itfe;
244    ALOGV("create_resampler() DONE rsmp %p &rsmp->itfe %p speex %p",
245         rsmp, &rsmp->itfe, rsmp->speex_resampler);
246    return 0;
247}
248
249void release_resampler(struct resampler_itfe *resampler)
250{
251    struct resampler *rsmp = (struct resampler *)resampler;
252
253    if (rsmp == NULL) {
254        return;
255    }
256
257    free(rsmp->in_buf);
258
259    if (rsmp->speex_resampler != NULL) {
260        speex_resampler_destroy(rsmp->speex_resampler);
261    }
262    free(rsmp);
263}
264