Home | History | Annotate | Download | only in audio_utils
      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 
     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 
     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.
     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     size_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         size_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 %d frames in and %d 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 
    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                                     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 
    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 
    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