diff options
author | Eric Laurent <elaurent@google.com> | 2011-06-17 13:48:45 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2011-07-05 16:16:06 -0700 |
commit | 61f43974dc34fb00dc52edb10f0a01d6134a8a27 (patch) | |
tree | 4bd82b0eab14567068de27cfdab108c1c6596da8 /libaudio | |
parent | 88482dc964d975e7eadfd43f5e7dae04886e7b0d (diff) | |
download | device_samsung_crespo-61f43974dc34fb00dc52edb10f0a01d6134a8a27.zip device_samsung_crespo-61f43974dc34fb00dc52edb10f0a01d6134a8a27.tar.gz device_samsung_crespo-61f43974dc34fb00dc52edb10f0a01d6134a8a27.tar.bz2 |
Audio HAL: replaced downsampler by speex resampler
Use speex resampler for more flexibility and prepare integration
of audio pre processing which require upsampling.
Change-Id: I7dd234bd89116d028655a043c84c1a18faf3bc67
Diffstat (limited to 'libaudio')
-rw-r--r-- | libaudio/Android.mk | 5 | ||||
-rw-r--r-- | libaudio/AudioHardware.cpp | 480 | ||||
-rw-r--r-- | libaudio/AudioHardware.h | 51 |
3 files changed, 151 insertions, 385 deletions
diff --git a/libaudio/Android.mk b/libaudio/Android.mk index 9df67c7..9ab312b 100644 --- a/libaudio/Android.mk +++ b/libaudio/Android.mk @@ -8,7 +8,8 @@ LOCAL_STATIC_LIBRARIES:= libmedia_helper LOCAL_SHARED_LIBRARIES:= \ libutils \ libhardware_legacy \ - libtinyalsa + libtinyalsa \ + libspeexresampler LOCAL_WHOLE_STATIC_LIBRARIES := libaudiohw_legacy LOCAL_MODULE_TAGS := optional @@ -18,7 +19,7 @@ ifeq ($(TARGET_SIMULATOR),true) else LOCAL_SHARED_LIBRARIES += libdl endif - +LOCAL_C_INCLUDES += $(call include-path-for, speex) LOCAL_C_INCLUDES += external/tinyalsa/include include $(BUILD_SHARED_LIBRARY) diff --git a/libaudio/AudioHardware.cpp b/libaudio/AudioHardware.cpp index 9d5933a..4bbe7d6 100644 --- a/libaudio/AudioHardware.cpp +++ b/libaudio/AudioHardware.cpp @@ -43,8 +43,13 @@ extern "C" { namespace android_audio_legacy { -const uint32_t AudioHardware::inputSamplingRates[] = { - 8000, 11025, 16000, 22050, 44100 +const uint32_t AudioHardware::inputConfigTable[][AudioHardware::INPUT_CONFIG_CNT] = { + {8000, 4}, + {11025, 4}, + {16000, 2}, + {22050, 2}, + {32000, 1}, + {44100, 1} }; // trace driver operations for dump @@ -533,8 +538,8 @@ size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int ch LOGW("getInputBufferSize bad channel count: %d", channelCount); return 0; } - if (sampleRate != 8000 && sampleRate != 11025 && sampleRate != 16000 && - sampleRate != 22050 && sampleRate != 44100) { + + if (sampleRate != getInputSampleRate(sampleRate)) { LOGW("getInputBufferSize bad sample rate: %d", sampleRate); return 0; } @@ -918,16 +923,17 @@ const char *AudioHardware::getInputRouteFromDevice(uint32_t device) uint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate) { - uint32_t i; + size_t i; uint32_t prevDelta; uint32_t delta; + size_t size = sizeof(inputConfigTable)/sizeof(uint32_t)/INPUT_CONFIG_CNT; - for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) { - delta = abs(sampleRate - inputSamplingRates[i]); + for (i = 0, prevDelta = 0xFFFFFFFF; i < size; i++, prevDelta = delta) { + delta = abs(sampleRate - inputConfigTable[i][INPUT_CONFIG_SAMPLE_RATE]); if (delta > prevDelta) break; } // i is always > 0 here - return inputSamplingRates[i-1]; + return inputConfigTable[i-1][INPUT_CONFIG_SAMPLE_RATE]; } // getActiveInput_l() must be called with mLock held @@ -1368,17 +1374,16 @@ status_t AudioHardware::AudioStreamInALSA::set( mChannelCount = AudioSystem::popCount(mChannels); mSampleRate = rate; if (mSampleRate != AUDIO_HW_OUT_SAMPLERATE) { - mDownSampler = new AudioHardware::DownSampler(mSampleRate, - mChannelCount, - AUDIO_HW_IN_PERIOD_SZ, - this); + mDownSampler = new AudioHardware::ReSampler(AUDIO_HW_OUT_SAMPLERATE, + mSampleRate, + mChannelCount, + this); status_t status = mDownSampler->initCheck(); if (status != NO_ERROR) { delete mDownSampler; LOGW("AudioStreamInALSA::set() downsampler init failed: %d", status); return status; } - mPcmIn = new int16_t[AUDIO_HW_IN_PERIOD_SZ * mChannelCount]; } return NO_ERROR; @@ -1389,15 +1394,13 @@ AudioHardware::AudioStreamInALSA::~AudioStreamInALSA() standby(); if (mDownSampler != NULL) { delete mDownSampler; - if (mPcmIn != NULL) { - delete[] mPcmIn; - } + delete[] mPcmIn; } } ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes) { - // LOGV("AudioStreamInALSA::read(%p, %u)", buffer, bytes); + // LOGV("AudioStreamInALSA::read(%p, %d)", buffer, (int)bytes); status_t status = NO_INIT; int ret; @@ -1734,24 +1737,19 @@ void AudioHardware::AudioStreamInALSA::releaseBuffer(Buffer* buffer) size_t AudioHardware::AudioStreamInALSA::getBufferSize(uint32_t sampleRate, int channelCount) { - size_t ratio; - - switch (sampleRate) { - case 8000: - case 11025: - ratio = 4; - break; - case 16000: - case 22050: - ratio = 2; - break; - case 44100: - default: - ratio = 1; - break; - } + size_t i; + size_t size = sizeof(inputConfigTable)/sizeof(uint32_t)/INPUT_CONFIG_CNT; - return (AUDIO_HW_IN_PERIOD_SZ*channelCount*sizeof(int16_t)) / ratio ; + for (i = 0; i < size; i++) { + if (sampleRate == inputConfigTable[i][INPUT_CONFIG_SAMPLE_RATE]) { + return (AUDIO_HW_IN_PERIOD_SZ*channelCount*sizeof(int16_t)) / + inputConfigTable[i][INPUT_CONFIG_BUFFER_RATIO]; + } + } + // this should never happen as getBufferSize() is always called after getInputSampleRate() + // that checks for valid sampling rates. + LOGE("AudioStreamInALSA::getBufferSize() invalid sampling rate %d", sampleRate); + return 0; } int AudioHardware::AudioStreamInALSA::prepareLock() @@ -1773,215 +1771,64 @@ void AudioHardware::AudioStreamInALSA::unlock() { } //------------------------------------------------------------------------------ -// DownSampler +// speex based resampler //------------------------------------------------------------------------------ -/* - * 2.30 fixed point FIR filter coefficients for conversion 44100 -> 22050. - * (Works equivalently for 22010 -> 11025 or any other halving, of course.) - * - * Transition band from about 18 kHz, passband ripple < 0.1 dB, - * stopband ripple at about -55 dB, linear phase. - * - * Design and display in MATLAB or Octave using: - * - * filter = fir1(19, 0.5); filter = round(filter * 2**30); freqz(filter * 2**-30); - */ -static const int32_t filter_22khz_coeff[] = { - 2089257, 2898328, -5820678, -10484531, - 19038724, 30542725, -50469415, -81505260, - 152544464, 478517512, 478517512, 152544464, - -81505260, -50469415, 30542725, 19038724, - -10484531, -5820678, 2898328, 2089257, -}; -#define NUM_COEFF_22KHZ (sizeof(filter_22khz_coeff) / sizeof(filter_22khz_coeff[0])) -#define OVERLAP_22KHZ (NUM_COEFF_22KHZ - 2) +#define RESAMPLER_QUALITY 2 -/* - * Convolution of signals A and reverse(B). (In our case, the filter response - * is symmetric, so the reversing doesn't matter.) - * A is taken to be in 0.16 fixed-point, and B is taken to be in 2.30 fixed-point. - * The answer will be in 16.16 fixed-point, unclipped. - * - * This function would probably be the prime candidate for SIMD conversion if - * you want more speed. - */ -int32_t fir_convolve(const int16_t* a, const int32_t* b, int num_samples) -{ - int32_t sum = 1 << 13; - for (int i = 0; i < num_samples; ++i) { - sum += a[i] * (b[i] >> 16); - } - return sum >> 14; -} - -/* Clip from 16.16 fixed-point to 0.16 fixed-point. */ -int16_t clip(int32_t x) +AudioHardware::ReSampler::ReSampler(uint32_t inSampleRate, + uint32_t outSampleRate, + uint32_t channelCount, + BufferProvider* provider) + : mStatus(NO_INIT), mSpeexResampler(NULL), mProvider(provider), + mInSampleRate(inSampleRate), mOutSampleRate(outSampleRate), mChannelCount(channelCount), + mInBuf(NULL), mInBufSize(0) { - if (x < -32768) { - return -32768; - } else if (x > 32767) { - return 32767; - } else { - return x; - } -} + LOGV("AudioHardware::ReSampler() cstor %p In SR %d Out SR %d channels %d", + this, mInSampleRate, mInSampleRate, mChannelCount); -/* - * Convert a chunk from 44 kHz to 22 kHz. Will update num_samples_in and num_samples_out - * accordingly, since it may leave input samples in the buffer due to overlap. - * - * Input and output are taken to be in 0.16 fixed-point. - */ -void resample_2_1(int16_t* input, int16_t* output, int* num_samples_in, int* num_samples_out) -{ - if (*num_samples_in < (int)NUM_COEFF_22KHZ) { - *num_samples_out = 0; + if (mProvider == NULL) { return; } - int odd_smp = *num_samples_in & 0x1; - int num_samples = *num_samples_in - odd_smp - OVERLAP_22KHZ; - - for (int i = 0; i < num_samples; i += 2) { - output[i / 2] = clip(fir_convolve(input + i, filter_22khz_coeff, NUM_COEFF_22KHZ)); - } - - memmove(input, input + num_samples, (OVERLAP_22KHZ + odd_smp) * sizeof(*input)); - *num_samples_out = num_samples / 2; - *num_samples_in = OVERLAP_22KHZ + odd_smp; -} - -/* - * 2.30 fixed point FIR filter coefficients for conversion 22050 -> 16000, - * or 11025 -> 8000. - * - * Transition band from about 14 kHz, passband ripple < 0.1 dB, - * stopband ripple at about -50 dB, linear phase. - * - * Design and display in MATLAB or Octave using: - * - * filter = fir1(23, 16000 / 22050); filter = round(filter * 2**30); freqz(filter * 2**-30); - */ -static const int32_t filter_16khz_coeff[] = { - 2057290, -2973608, 1880478, 4362037, - -14639744, 18523609, -1609189, -38502470, - 78073125, -68353935, -59103896, 617555440, - 617555440, -59103896, -68353935, 78073125, - -38502470, -1609189, 18523609, -14639744, - 4362037, 1880478, -2973608, 2057290, -}; -#define NUM_COEFF_16KHZ (sizeof(filter_16khz_coeff) / sizeof(filter_16khz_coeff[0])) -#define OVERLAP_16KHZ (NUM_COEFF_16KHZ - 1) - -/* - * Convert a chunk from 22 kHz to 16 kHz. Will update num_samples_in and - * num_samples_out accordingly, since it may leave input samples in the buffer - * due to overlap. - * - * This implementation is rather ad-hoc; it first low-pass filters the data - * into a temporary buffer, and then converts chunks of 441 input samples at a - * time into 320 output samples by simple linear interpolation. A better - * implementation would use a polyphase filter bank to do these two operations - * in one step. - * - * Input and output are taken to be in 0.16 fixed-point. - */ - -#define RESAMPLE_16KHZ_SAMPLES_IN 441 -#define RESAMPLE_16KHZ_SAMPLES_OUT 320 - -void resample_441_320(int16_t* input, int16_t* output, int* num_samples_in, int* num_samples_out) -{ - const int num_blocks = (*num_samples_in - OVERLAP_16KHZ) / RESAMPLE_16KHZ_SAMPLES_IN; - if (num_blocks < 1) { - *num_samples_out = 0; + int error; + mSpeexResampler = speex_resampler_init(channelCount, + inSampleRate, + outSampleRate, + RESAMPLER_QUALITY, + &error); + if (mSpeexResampler == NULL) { + LOGW("ReSampler: Cannot create speex resampler: %s", speex_resampler_strerror(error)); return; } - for (int i = 0; i < num_blocks; ++i) { - uint32_t tmp[RESAMPLE_16KHZ_SAMPLES_IN]; - for (int j = 0; j < RESAMPLE_16KHZ_SAMPLES_IN; ++j) { - tmp[j] = fir_convolve(input + i * RESAMPLE_16KHZ_SAMPLES_IN + j, - filter_16khz_coeff, - NUM_COEFF_16KHZ); - } - - const float step_float = (float)RESAMPLE_16KHZ_SAMPLES_IN / (float)RESAMPLE_16KHZ_SAMPLES_OUT; - const uint32_t step = (uint32_t)(step_float * 32768.0f + 0.5f); // 17.15 fixed point - - uint32_t in_sample_num = 0; // 17.15 fixed point - for (int j = 0; j < RESAMPLE_16KHZ_SAMPLES_OUT; ++j, in_sample_num += step) { - const uint32_t whole = in_sample_num >> 15; - const uint32_t frac = (in_sample_num & 0x7fff); // 0.15 fixed point - const int32_t s1 = tmp[whole]; - const int32_t s2 = tmp[whole + 1]; - *output++ = clip(s1 + (((s2 - s1) * (int32_t)frac) >> 15)); - } - - } + reset(); - const int samples_consumed = num_blocks * RESAMPLE_16KHZ_SAMPLES_IN; - memmove(input, input + samples_consumed, (*num_samples_in - samples_consumed) * sizeof(*input)); - *num_samples_in -= samples_consumed; - *num_samples_out = RESAMPLE_16KHZ_SAMPLES_OUT * num_blocks; + mStatus = NO_ERROR; } - -AudioHardware::DownSampler::DownSampler(uint32_t outSampleRate, - uint32_t channelCount, - uint32_t frameCount, - AudioHardware::BufferProvider* provider) - : mStatus(NO_INIT), mProvider(provider), mSampleRate(outSampleRate), - mChannelCount(channelCount), mFrameCount(frameCount), - mInLeft(NULL), mInRight(NULL), mTmpLeft(NULL), mTmpRight(NULL), - mTmp2Left(NULL), mTmp2Right(NULL), mOutLeft(NULL), mOutRight(NULL) - +AudioHardware::ReSampler::~ReSampler() { - LOGV("AudioHardware::DownSampler() cstor %p SR %d channels %d frames %d", - this, mSampleRate, mChannelCount, mFrameCount); + free(mInBuf); - if (mSampleRate != 8000 && mSampleRate != 11025 && mSampleRate != 16000 && - mSampleRate != 22050) { - LOGW("AudioHardware::DownSampler cstor: bad sampling rate: %d", mSampleRate); - return; + if (mSpeexResampler != NULL) { + speex_resampler_destroy(mSpeexResampler); } - - mInLeft = new int16_t[mFrameCount]; - mInRight = new int16_t[mFrameCount]; - mTmpLeft = new int16_t[mFrameCount]; - mTmpRight = new int16_t[mFrameCount]; - mTmp2Left = new int16_t[mFrameCount]; - mTmp2Right = new int16_t[mFrameCount]; - mOutLeft = new int16_t[mFrameCount]; - mOutRight = new int16_t[mFrameCount]; - - mStatus = NO_ERROR; } -AudioHardware::DownSampler::~DownSampler() +void AudioHardware::ReSampler::reset() { - if (mInLeft) delete[] mInLeft; - if (mInRight) delete[] mInRight; - if (mTmpLeft) delete[] mTmpLeft; - if (mTmpRight) delete[] mTmpRight; - if (mTmp2Left) delete[] mTmp2Left; - if (mTmp2Right) delete[] mTmp2Right; - if (mOutLeft) delete[] mOutLeft; - if (mOutRight) delete[] mOutRight; -} + mFramesIn = 0; + mFramesRq = 0; -void AudioHardware::DownSampler::reset() -{ - mInInBuf = 0; - mInTmpBuf = 0; - mInTmp2Buf = 0; - mOutBufPos = 0; - mInOutBuf = 0; + if (mSpeexResampler != NULL) { + speex_resampler_reset_mem(mSpeexResampler); + } } - -int AudioHardware::DownSampler::resample(int16_t* out, size_t *outFrameCount) +// outputs a number of frames less or equal to *outFrameCount and updates *outFrameCount +// with the actual number of frames produced. +int AudioHardware::ReSampler::resample(int16_t *out, size_t *outFrameCount) { if (mStatus != NO_ERROR) { return mStatus; @@ -1991,156 +1838,71 @@ int AudioHardware::DownSampler::resample(int16_t* out, size_t *outFrameCount) return BAD_VALUE; } - int16_t *outLeft = mTmp2Left; - int16_t *outRight = mTmp2Left; - if (mSampleRate == 22050) { - outLeft = mTmpLeft; - outRight = mTmpRight; - } else if (mSampleRate == 8000){ - outLeft = mOutLeft; - outRight = mOutRight; - } - - int outFrames = 0; - int remaingFrames = *outFrameCount; - - if (mInOutBuf) { - int frames = (remaingFrames > mInOutBuf) ? mInOutBuf : remaingFrames; - - for (int i = 0; i < frames; ++i) { - out[i] = outLeft[mOutBufPos + i]; - } - if (mChannelCount == 2) { - for (int i = 0; i < frames; ++i) { - out[i * 2] = outLeft[mOutBufPos + i]; - out[i * 2 + 1] = outRight[mOutBufPos + i]; + 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 != mFramesRq) { + mFramesNeeded = (framesRq * mOutSampleRate) / mInSampleRate + 1; + mFramesRq = framesRq; + } + + size_t framesWr = 0; + size_t inFrames = 0; + while (framesWr < framesRq) { + if (mFramesIn < mFramesNeeded) { + // make sure that the number of frames present in mInBuf (mFramesIn) is at least + // the number of frames needed to produce the number of frames requested at + // the output sampling rate + if (mInBufSize < mFramesNeeded) { + mInBufSize = mFramesNeeded; + mInBuf = (int16_t *)realloc(mInBuf, mInBufSize * mChannelCount * sizeof(int16_t)); } - } - remaingFrames -= frames; - mInOutBuf -= frames; - mOutBufPos += frames; - outFrames += frames; - } - - while (remaingFrames) { - LOGW_IF((mInOutBuf != 0), "mInOutBuf should be 0 here"); - - AudioHardware::BufferProvider::Buffer buf; - buf.frameCount = mFrameCount - mInInBuf; - int ret = mProvider->getNextBuffer(&buf); - if (buf.raw == NULL) { - *outFrameCount = outFrames; - return ret; - } - - for (size_t i = 0; i < buf.frameCount; ++i) { - mInLeft[i + mInInBuf] = buf.i16[i]; - } - if (mChannelCount == 2) { - for (size_t i = 0; i < buf.frameCount; ++i) { - mInLeft[i + mInInBuf] = buf.i16[i * 2]; - mInRight[i + mInInBuf] = buf.i16[i * 2 + 1]; - } - } - mInInBuf += buf.frameCount; - mProvider->releaseBuffer(&buf); - - /* 44010 -> 22050 */ - { - int samples_in_left = mInInBuf; - int samples_out_left; - resample_2_1(mInLeft, mTmpLeft + mInTmpBuf, &samples_in_left, &samples_out_left); - - if (mChannelCount == 2) { - int samples_in_right = mInInBuf; - int samples_out_right; - resample_2_1(mInRight, mTmpRight + mInTmpBuf, &samples_in_right, &samples_out_right); + AudioHardware::BufferProvider::Buffer buf; + buf.frameCount = mFramesNeeded - mFramesIn; + mProvider->getNextBuffer(&buf); + if (buf.raw == NULL) { + break; } - - mInInBuf = samples_in_left; - mInTmpBuf += samples_out_left; - mInOutBuf = samples_out_left; + memcpy(mInBuf + mFramesIn * mChannelCount, + buf.raw, + buf.frameCount * mChannelCount * sizeof(int16_t)); + mFramesIn += buf.frameCount; + mProvider->releaseBuffer(&buf); } - if (mSampleRate == 11025 || mSampleRate == 8000) { - /* 22050 - > 11025 */ - int samples_in_left = mInTmpBuf; - int samples_out_left; - resample_2_1(mTmpLeft, mTmp2Left + mInTmp2Buf, &samples_in_left, &samples_out_left); - - if (mChannelCount == 2) { - int samples_in_right = mInTmpBuf; - int samples_out_right; - resample_2_1(mTmpRight, mTmp2Right + mInTmp2Buf, &samples_in_right, &samples_out_right); - } - - - mInTmpBuf = samples_in_left; - mInTmp2Buf += samples_out_left; - mInOutBuf = samples_out_left; - - if (mSampleRate == 8000) { - /* 11025 -> 8000*/ - int samples_in_left = mInTmp2Buf; - int samples_out_left; - resample_441_320(mTmp2Left, mOutLeft, &samples_in_left, &samples_out_left); - - if (mChannelCount == 2) { - int samples_in_right = mInTmp2Buf; - int samples_out_right; - resample_441_320(mTmp2Right, mOutRight, &samples_in_right, &samples_out_right); - } - - mInTmp2Buf = samples_in_left; - mInOutBuf = samples_out_left; - } else { - mInTmp2Buf = 0; - } - - } else if (mSampleRate == 16000) { - /* 22050 -> 16000*/ - int samples_in_left = mInTmpBuf; - int samples_out_left; - resample_441_320(mTmpLeft, mTmp2Left, &samples_in_left, &samples_out_left); - - if (mChannelCount == 2) { - int samples_in_right = mInTmpBuf; - int samples_out_right; - resample_441_320(mTmpRight, mTmp2Right, &samples_in_right, &samples_out_right); - } - - mInTmpBuf = samples_in_left; - mInOutBuf = samples_out_left; + size_t outFrames = framesRq - framesWr; + inFrames = mFramesIn; + if (mChannelCount == 1) { + speex_resampler_process_int(mSpeexResampler, + 0, + mInBuf, + &inFrames, + out + framesWr * mChannelCount, + &outFrames); } else { - mInTmpBuf = 0; - } - - int frames = (remaingFrames > mInOutBuf) ? mInOutBuf : remaingFrames; - - for (int i = 0; i < frames; ++i) { - out[outFrames + i] = outLeft[i]; - } - if (mChannelCount == 2) { - for (int i = 0; i < frames; ++i) { - out[(outFrames + i) * 2] = outLeft[i]; - out[(outFrames + i) * 2 + 1] = outRight[i]; - } + speex_resampler_process_interleaved_int(mSpeexResampler, + mInBuf, + &inFrames, + out + framesWr * mChannelCount, + &outFrames); } - remaingFrames -= frames; - outFrames += frames; - mOutBufPos = frames; - mInOutBuf -= frames; + framesWr += outFrames; + mFramesIn -= inFrames; + LOGW_IF((framesWr != framesRq) && (mFramesIn != 0), + "ReSampler::resample() remaining %d frames in and %d frames out", + mFramesIn, (framesRq - framesWr)); } + if (mFramesIn) { + memmove(mInBuf, + mInBuf + inFrames * mChannelCount, + mFramesIn * mChannelCount * sizeof(int16_t)); + } + *outFrameCount = framesWr; - return 0; + return NO_ERROR; } - - - - - //------------------------------------------------------------------------------ // Factory //------------------------------------------------------------------------------ diff --git a/libaudio/AudioHardware.h b/libaudio/AudioHardware.h index 3a8fdb9..c791f37 100644 --- a/libaudio/AudioHardware.h +++ b/libaudio/AudioHardware.h @@ -28,6 +28,8 @@ #include "secril-client.h" +#include "speex/speex_resampler.h" + extern "C" { struct pcm; struct mixer; @@ -182,7 +184,17 @@ private: int mDriverOp; static uint32_t checkInputSampleRate(uint32_t sampleRate); - static const uint32_t inputSamplingRates[]; + + // column index in inputConfigTable[][] + enum { + INPUT_CONFIG_SAMPLE_RATE, + INPUT_CONFIG_BUFFER_RATIO, + INPUT_CONFIG_CNT + }; + + // contains the list of valid sampling rates for input streams as well as the ratio + // between the kernel buffer size and audio hal buffer size for each sampling rate + static const uint32_t inputConfigTable[][INPUT_CONFIG_CNT]; class AudioStreamOutALSA : public AudioStreamOut, public RefBase { @@ -246,8 +258,6 @@ private: bool mSleepReq; }; - class DownSampler; - class BufferProvider { public: @@ -267,38 +277,31 @@ private: virtual void releaseBuffer(Buffer* buffer) = 0; }; - class DownSampler { + class ReSampler { public: - DownSampler(uint32_t outSampleRate, + ReSampler(uint32_t inSampleRate, + uint32_t outSampleRate, uint32_t channelCount, - uint32_t frameCount, BufferProvider* provider); - virtual ~DownSampler(); + virtual ~ReSampler(); - void reset(); status_t initCheck() { return mStatus; } + void reset(); int resample(int16_t* out, size_t *outFrameCount); private: status_t mStatus; + SpeexResamplerState *mSpeexResampler; BufferProvider* mProvider; - uint32_t mSampleRate; + uint32_t mInSampleRate; + uint32_t mOutSampleRate; uint32_t mChannelCount; - uint32_t mFrameCount; - int16_t *mInLeft; - int16_t *mInRight; - int16_t *mTmpLeft; - int16_t *mTmpRight; - int16_t *mTmp2Left; - int16_t *mTmp2Right; - int16_t *mOutLeft; - int16_t *mOutRight; - int mInInBuf; - int mInTmpBuf; - int mInTmp2Buf; - int mOutBufPos; - int mInOutBuf; + int16_t *mInBuf; + size_t mInBufSize; + size_t mFramesIn; + size_t mFramesRq; + size_t mFramesNeeded; }; @@ -355,7 +358,7 @@ private: uint32_t mChannelCount; uint32_t mSampleRate; size_t mBufferSize; - DownSampler *mDownSampler; + ReSampler *mDownSampler; status_t mReadStatus; size_t mInPcmInBuf; int16_t *mPcmIn; |