123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- /*
- ** Copyright 2011, The Android Open-Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
- //#define LOG_NDEBUG 0
- #define LOG_TAG "resampler"
- #include <errno.h>
- #include <stdlib.h>
- #include <log/log.h>
- #include <system/audio.h>
- #include <audio_utils/resampler.h>
- #include <speex/speex_resampler.h>
- struct resampler {
- struct resampler_itfe itfe;
- SpeexResamplerState *speex_resampler; // handle on speex resampler
- struct resampler_buffer_provider *provider; // buffer provider installed by client
- uint32_t in_sample_rate; // input sampling rate in Hz
- uint32_t out_sample_rate; // output sampling rate in Hz
- uint32_t channel_count; // number of channels (interleaved)
- int16_t *in_buf; // input buffer
- size_t in_buf_size; // input buffer size
- size_t frames_in; // number of frames in input buffer
- size_t frames_rq; // cached number of output frames
- size_t frames_needed; // minimum number of input frames to produce
- // frames_rq output frames
- int32_t speex_delay_ns; // delay introduced by speex resampler in ns
- };
- //------------------------------------------------------------------------------
- // speex based resampler
- //------------------------------------------------------------------------------
- static void resampler_reset(struct resampler_itfe *resampler)
- {
- struct resampler *rsmp = (struct resampler *)resampler;
- rsmp->frames_in = 0;
- rsmp->frames_rq = 0;
- if (rsmp != NULL && rsmp->speex_resampler != NULL) {
- speex_resampler_reset_mem(rsmp->speex_resampler);
- }
- }
- static int32_t resampler_delay_ns(struct resampler_itfe *resampler)
- {
- struct resampler *rsmp = (struct resampler *)resampler;
- int32_t delay = (int32_t)((1000000000 * (int64_t)rsmp->frames_in) / rsmp->in_sample_rate);
- delay += rsmp->speex_delay_ns;
- return delay;
- }
- // outputs a number of frames less or equal to *outFrameCount and updates *outFrameCount
- // with the actual number of frames produced.
- int resampler_resample_from_provider(struct resampler_itfe *resampler,
- int16_t *out,
- size_t *outFrameCount)
- {
- struct resampler *rsmp = (struct resampler *)resampler;
- if (rsmp == NULL || out == NULL || outFrameCount == NULL) {
- return -EINVAL;
- }
- if (rsmp->provider == NULL) {
- *outFrameCount = 0;
- return -ENOSYS;
- }
- size_t framesRq = *outFrameCount;
- // update and cache the number of frames needed at the input sampling rate to produce
- // the number of frames requested at the output sampling rate
- if (framesRq != rsmp->frames_rq) {
- rsmp->frames_needed = (framesRq * rsmp->in_sample_rate) / rsmp->out_sample_rate + 1;
- rsmp->frames_rq = framesRq;
- }
- size_t framesWr = 0;
- spx_uint32_t inFrames = 0;
- while (framesWr < framesRq) {
- if (rsmp->frames_in < rsmp->frames_needed) {
- // make sure that the number of frames present in rsmp->in_buf (rsmp->frames_in) is at
- // least the number of frames needed to produce the number of frames requested at
- // the output sampling rate
- if (rsmp->in_buf_size < rsmp->frames_needed) {
- rsmp->in_buf_size = rsmp->frames_needed;
- rsmp->in_buf = (int16_t *)realloc(rsmp->in_buf,
- rsmp->in_buf_size * rsmp->channel_count * sizeof(int16_t));
- }
- struct resampler_buffer buf;
- buf.frame_count = rsmp->frames_needed - rsmp->frames_in;
- rsmp->provider->get_next_buffer(rsmp->provider, &buf);
- if (buf.raw == NULL) {
- break;
- }
- memcpy(rsmp->in_buf + rsmp->frames_in * rsmp->channel_count,
- buf.raw,
- buf.frame_count * rsmp->channel_count * sizeof(int16_t));
- rsmp->frames_in += buf.frame_count;
- rsmp->provider->release_buffer(rsmp->provider, &buf);
- }
- spx_uint32_t outFrames = framesRq - framesWr;
- inFrames = rsmp->frames_in;
- if (rsmp->channel_count == 1) {
- speex_resampler_process_int(rsmp->speex_resampler,
- 0,
- rsmp->in_buf,
- &inFrames,
- out + framesWr,
- &outFrames);
- } else {
- speex_resampler_process_interleaved_int(rsmp->speex_resampler,
- rsmp->in_buf,
- &inFrames,
- out + framesWr * rsmp->channel_count,
- &outFrames);
- }
- framesWr += outFrames;
- rsmp->frames_in -= inFrames;
- ALOGW_IF((framesWr != framesRq) && (rsmp->frames_in != 0),
- "ReSampler::resample() remaining %zu frames in and %zu frames out",
- rsmp->frames_in, (framesRq - framesWr));
- }
- if (rsmp->frames_in) {
- memmove(rsmp->in_buf,
- rsmp->in_buf + inFrames * rsmp->channel_count,
- rsmp->frames_in * rsmp->channel_count * sizeof(int16_t));
- }
- *outFrameCount = framesWr;
- return 0;
- }
- int resampler_resample_from_input(struct resampler_itfe *resampler,
- int16_t *in,
- size_t *inFrameCount,
- int16_t *out,
- size_t *outFrameCount)
- {
- struct resampler *rsmp = (struct resampler *)resampler;
- if (rsmp == NULL || in == NULL || inFrameCount == NULL ||
- out == NULL || outFrameCount == NULL) {
- return -EINVAL;
- }
- if (rsmp->provider != NULL) {
- *outFrameCount = 0;
- return -ENOSYS;
- }
- if (rsmp->channel_count == 1) {
- speex_resampler_process_int(rsmp->speex_resampler,
- 0,
- in,
- (spx_uint32_t *)inFrameCount,
- out,
- (spx_uint32_t *)outFrameCount);
- } else {
- speex_resampler_process_interleaved_int(rsmp->speex_resampler,
- in,
- (spx_uint32_t *)inFrameCount,
- out,
- (spx_uint32_t *)outFrameCount);
- }
- ALOGV("resampler_resample_from_input() DONE in %zu out %zu", *inFrameCount, *outFrameCount);
- return 0;
- }
- int create_resampler(uint32_t inSampleRate,
- uint32_t outSampleRate,
- uint32_t channelCount,
- uint32_t quality,
- struct resampler_buffer_provider* provider,
- struct resampler_itfe **resampler)
- {
- int error;
- struct resampler *rsmp;
- ALOGV("create_resampler() In SR %d Out SR %d channels %d",
- inSampleRate, outSampleRate, channelCount);
- if (resampler == NULL) {
- return -EINVAL;
- }
- *resampler = NULL;
- if (quality <= RESAMPLER_QUALITY_MIN || quality >= RESAMPLER_QUALITY_MAX) {
- return -EINVAL;
- }
- rsmp = (struct resampler *)calloc(1, sizeof(struct resampler));
- rsmp->speex_resampler = speex_resampler_init(channelCount,
- inSampleRate,
- outSampleRate,
- quality,
- &error);
- if (rsmp->speex_resampler == NULL) {
- ALOGW("ReSampler: Cannot create speex resampler: %s", speex_resampler_strerror(error));
- free(rsmp);
- return -ENODEV;
- }
- rsmp->itfe.reset = resampler_reset;
- rsmp->itfe.resample_from_provider = resampler_resample_from_provider;
- rsmp->itfe.resample_from_input = resampler_resample_from_input;
- rsmp->itfe.delay_ns = resampler_delay_ns;
- rsmp->provider = provider;
- rsmp->in_sample_rate = inSampleRate;
- rsmp->out_sample_rate = outSampleRate;
- rsmp->channel_count = channelCount;
- rsmp->in_buf = NULL;
- rsmp->in_buf_size = 0;
- resampler_reset(&rsmp->itfe);
- int frames = speex_resampler_get_input_latency(rsmp->speex_resampler);
- rsmp->speex_delay_ns = (int32_t)((1000000000 * (int64_t)frames) / rsmp->in_sample_rate);
- frames = speex_resampler_get_output_latency(rsmp->speex_resampler);
- rsmp->speex_delay_ns += (int32_t)((1000000000 * (int64_t)frames) / rsmp->out_sample_rate);
- *resampler = &rsmp->itfe;
- ALOGV("create_resampler() DONE rsmp %p &rsmp->itfe %p speex %p",
- rsmp, &rsmp->itfe, rsmp->speex_resampler);
- return 0;
- }
- void release_resampler(struct resampler_itfe *resampler)
- {
- struct resampler *rsmp = (struct resampler *)resampler;
- if (rsmp == NULL) {
- return;
- }
- free(rsmp->in_buf);
- if (rsmp->speex_resampler != NULL) {
- speex_resampler_destroy(rsmp->speex_resampler);
- }
- free(rsmp);
- }
|