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