Loading libvideoeditor/lvpp/VideoEditorSRC.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -321,8 +321,7 @@ void VideoEditorSRC::checkAndSetResampler() { mResampler = AudioResampler::create( 16 /* bit depth */, mChannelCnt, mOutputSampleRate, AudioResampler::DEFAULT); mOutputSampleRate); CHECK(mResampler); mResampler->setSampleRate(mSampleRate); mResampler->setVolume(kUnityGain, kUnityGain); Loading libvideoeditor/vss/src/VideoEditorResampler.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,7 @@ M4OSA_Context LVAudioResamplerCreate(M4OSA_Int32 bitDepth, M4OSA_Int32 inChanne VideoEditorResampler *context = new VideoEditorResampler(); context->mResampler = AudioResampler::create( bitDepth, inChannelCount, sampleRate, AudioResampler::DEFAULT); bitDepth, inChannelCount, sampleRate); if (context->mResampler == NULL) { return NULL; } Loading services/audioflinger/Android.mk +3 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,9 @@ LOCAL_SRC_FILES:= \ AudioPolicyService.cpp \ ServiceUtilities.cpp \ AudioResamplerSinc.cpp.arm # AudioResamplerCubic.cpp.arm # uncomment to enable AudioResampler::MED_QUALITY # LOCAL_SRC_FILES += AudioResamplerCubic.cpp.arm LOCAL_SRC_FILES += StateQueue.cpp Loading services/audioflinger/AudioMixer.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -539,11 +539,23 @@ bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate) if (sampleRate != value) { sampleRate = value; if (resampler == NULL) { ALOGV("creating resampler from track %d Hz to device %d Hz", value, devSampleRate); AudioResampler::src_quality quality; // force lowest quality level resampler if use case isn't music or video // FIXME this is flawed for dynamic sample rates, as we choose the resampler // quality level based on the initial ratio, but that could change later. // Should have a way to distinguish tracks with static ratios vs. dynamic ratios. if (!((value == 44100 && devSampleRate == 48000) || (value == 48000 && devSampleRate == 44100))) { quality = AudioResampler::LOW_QUALITY; } else { quality = AudioResampler::DEFAULT_QUALITY; } resampler = AudioResampler::create( format, // the resampler sees the number of channels after the downmixer, if any downmixerBufferProvider != NULL ? MAX_NUM_CHANNELS : channelCount, devSampleRate); devSampleRate, quality); resampler->setLocalTimeFreq(localTimeFreq); } return true; Loading services/audioflinger/AudioResampler.cpp +118 −16 Original line number Diff line number Diff line Loading @@ -24,9 +24,7 @@ #include <cutils/properties.h> #include "AudioResampler.h" #include "AudioResamplerSinc.h" #if 0 #include "AudioResamplerCubic.h" #endif #ifdef __arm__ #include <machine/cpu-features.h> Loading @@ -42,7 +40,7 @@ namespace android { class AudioResamplerOrder1 : public AudioResampler { public: AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) : AudioResampler(bitDepth, inChannelCount, sampleRate), mX0L(0), mX0R(0) { AudioResampler(bitDepth, inChannelCount, sampleRate, LOW_QUALITY), mX0L(0), mX0R(0) { } virtual void resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); Loading Loading @@ -79,29 +77,120 @@ private: int mX0R; }; bool AudioResampler::qualityIsSupported(src_quality quality) { switch (quality) { case DEFAULT_QUALITY: case LOW_QUALITY: #if 0 // these have not been qualified recently so are not supported unless explicitly requested case MED_QUALITY: case HIGH_QUALITY: #endif case VERY_HIGH_QUALITY: return true; default: return false; } } // ---------------------------------------------------------------------------- AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, int32_t sampleRate, int quality) { // can only create low quality resample now AudioResampler* resampler; static pthread_once_t once_control = PTHREAD_ONCE_INIT; static AudioResampler::src_quality defaultQuality = AudioResampler::DEFAULT_QUALITY; void AudioResampler::init_routine() { char value[PROPERTY_VALUE_MAX]; if (property_get("af.resampler.quality", value, 0)) { quality = atoi(value); ALOGD("forcing AudioResampler quality to %d", quality); if (property_get("af.resampler.quality", value, NULL) > 0) { char *endptr; unsigned long l = strtoul(value, &endptr, 0); if (*endptr == '\0') { defaultQuality = (src_quality) l; ALOGD("forcing AudioResampler quality to %d", defaultQuality); if (defaultQuality < DEFAULT_QUALITY || defaultQuality > VERY_HIGH_QUALITY) { defaultQuality = DEFAULT_QUALITY; } } } } if (quality == DEFAULT) uint32_t AudioResampler::qualityMHz(src_quality quality) { switch (quality) { default: case DEFAULT_QUALITY: case LOW_QUALITY: return 3; case MED_QUALITY: return 6; case HIGH_QUALITY: return 20; case VERY_HIGH_QUALITY: return 34; } } static const uint32_t maxMHz = 75; // an arbitrary number that permits 2 VHQ, should be tunable static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static uint32_t currentMHz = 0; AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, int32_t sampleRate, src_quality quality) { bool atFinalQuality; if (quality == DEFAULT_QUALITY) { // read the resampler default quality property the first time it is needed int ok = pthread_once(&once_control, init_routine); if (ok != 0) { ALOGE("%s pthread_once failed: %d", __func__, ok); } quality = defaultQuality; atFinalQuality = false; } else { atFinalQuality = true; } // naive implementation of CPU load throttling doesn't account for whether resampler is active pthread_mutex_lock(&mutex); for (;;) { uint32_t deltaMHz = qualityMHz(quality); uint32_t newMHz = currentMHz + deltaMHz; if ((qualityIsSupported(quality) && newMHz <= maxMHz) || atFinalQuality) { ALOGV("resampler load %u -> %u MHz due to delta +%u MHz from quality %d", currentMHz, newMHz, deltaMHz, quality); currentMHz = newMHz; break; } // not enough CPU available for proposed quality level, so try next lowest level switch (quality) { default: case DEFAULT_QUALITY: case LOW_QUALITY: atFinalQuality = true; break; case MED_QUALITY: quality = LOW_QUALITY; break; case HIGH_QUALITY: quality = MED_QUALITY; break; case VERY_HIGH_QUALITY: quality = HIGH_QUALITY; break; } } pthread_mutex_unlock(&mutex); AudioResampler* resampler; switch (quality) { default: case DEFAULT_QUALITY: case LOW_QUALITY: ALOGV("Create linear Resampler"); resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate); break; #if 0 #if 0 // disabled because it has not been qualified recently, if requested will use default: case MED_QUALITY: ALOGV("Create cubic Resampler"); resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate); Loading @@ -110,6 +199,7 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, case HIGH_QUALITY: ALOGV("Create HIGH_QUALITY sinc Resampler"); resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate); break; case VERY_HIGH_QUALITY: ALOGV("Create VERY_HIGH_QUALITY sinc Resampler = %d", quality); resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate, quality); Loading @@ -122,17 +212,20 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, } AudioResampler::AudioResampler(int bitDepth, int inChannelCount, int32_t sampleRate) : int32_t sampleRate, src_quality quality) : mBitDepth(bitDepth), mChannelCount(inChannelCount), mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0), mPhaseFraction(0), mLocalTimeFreq(0), mPTS(AudioBufferProvider::kInvalidPTS) { mPTS(AudioBufferProvider::kInvalidPTS), mQuality(quality) { // sanity check on format if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) { ALOGE("Unsupported sample format, %d bits, %d channels", bitDepth, inChannelCount); // ALOG_ASSERT(0); } if (sampleRate <= 0) { ALOGE("Unsupported sample rate %d Hz", sampleRate); } // initialize common members mVolume[0] = mVolume[1] = 0; Loading @@ -141,6 +234,15 @@ AudioResampler::AudioResampler(int bitDepth, int inChannelCount, } AudioResampler::~AudioResampler() { pthread_mutex_lock(&mutex); src_quality quality = getQuality(); uint32_t deltaMHz = qualityMHz(quality); int32_t newMHz = currentMHz - deltaMHz; ALOGV("resampler load %u -> %d MHz due to delta -%u MHz from quality %d", currentMHz, newMHz, deltaMHz, quality); LOG_ALWAYS_FATAL_IF(newMHz < 0, "negative resampler load %d MHz", newMHz); currentMHz = newMHz; pthread_mutex_unlock(&mutex); } void AudioResampler::setSampleRate(int32_t inSampleRate) { Loading Loading
libvideoeditor/lvpp/VideoEditorSRC.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -321,8 +321,7 @@ void VideoEditorSRC::checkAndSetResampler() { mResampler = AudioResampler::create( 16 /* bit depth */, mChannelCnt, mOutputSampleRate, AudioResampler::DEFAULT); mOutputSampleRate); CHECK(mResampler); mResampler->setSampleRate(mSampleRate); mResampler->setVolume(kUnityGain, kUnityGain); Loading
libvideoeditor/vss/src/VideoEditorResampler.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,7 @@ M4OSA_Context LVAudioResamplerCreate(M4OSA_Int32 bitDepth, M4OSA_Int32 inChanne VideoEditorResampler *context = new VideoEditorResampler(); context->mResampler = AudioResampler::create( bitDepth, inChannelCount, sampleRate, AudioResampler::DEFAULT); bitDepth, inChannelCount, sampleRate); if (context->mResampler == NULL) { return NULL; } Loading
services/audioflinger/Android.mk +3 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,9 @@ LOCAL_SRC_FILES:= \ AudioPolicyService.cpp \ ServiceUtilities.cpp \ AudioResamplerSinc.cpp.arm # AudioResamplerCubic.cpp.arm # uncomment to enable AudioResampler::MED_QUALITY # LOCAL_SRC_FILES += AudioResamplerCubic.cpp.arm LOCAL_SRC_FILES += StateQueue.cpp Loading
services/audioflinger/AudioMixer.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -539,11 +539,23 @@ bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate) if (sampleRate != value) { sampleRate = value; if (resampler == NULL) { ALOGV("creating resampler from track %d Hz to device %d Hz", value, devSampleRate); AudioResampler::src_quality quality; // force lowest quality level resampler if use case isn't music or video // FIXME this is flawed for dynamic sample rates, as we choose the resampler // quality level based on the initial ratio, but that could change later. // Should have a way to distinguish tracks with static ratios vs. dynamic ratios. if (!((value == 44100 && devSampleRate == 48000) || (value == 48000 && devSampleRate == 44100))) { quality = AudioResampler::LOW_QUALITY; } else { quality = AudioResampler::DEFAULT_QUALITY; } resampler = AudioResampler::create( format, // the resampler sees the number of channels after the downmixer, if any downmixerBufferProvider != NULL ? MAX_NUM_CHANNELS : channelCount, devSampleRate); devSampleRate, quality); resampler->setLocalTimeFreq(localTimeFreq); } return true; Loading
services/audioflinger/AudioResampler.cpp +118 −16 Original line number Diff line number Diff line Loading @@ -24,9 +24,7 @@ #include <cutils/properties.h> #include "AudioResampler.h" #include "AudioResamplerSinc.h" #if 0 #include "AudioResamplerCubic.h" #endif #ifdef __arm__ #include <machine/cpu-features.h> Loading @@ -42,7 +40,7 @@ namespace android { class AudioResamplerOrder1 : public AudioResampler { public: AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) : AudioResampler(bitDepth, inChannelCount, sampleRate), mX0L(0), mX0R(0) { AudioResampler(bitDepth, inChannelCount, sampleRate, LOW_QUALITY), mX0L(0), mX0R(0) { } virtual void resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider); Loading Loading @@ -79,29 +77,120 @@ private: int mX0R; }; bool AudioResampler::qualityIsSupported(src_quality quality) { switch (quality) { case DEFAULT_QUALITY: case LOW_QUALITY: #if 0 // these have not been qualified recently so are not supported unless explicitly requested case MED_QUALITY: case HIGH_QUALITY: #endif case VERY_HIGH_QUALITY: return true; default: return false; } } // ---------------------------------------------------------------------------- AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, int32_t sampleRate, int quality) { // can only create low quality resample now AudioResampler* resampler; static pthread_once_t once_control = PTHREAD_ONCE_INIT; static AudioResampler::src_quality defaultQuality = AudioResampler::DEFAULT_QUALITY; void AudioResampler::init_routine() { char value[PROPERTY_VALUE_MAX]; if (property_get("af.resampler.quality", value, 0)) { quality = atoi(value); ALOGD("forcing AudioResampler quality to %d", quality); if (property_get("af.resampler.quality", value, NULL) > 0) { char *endptr; unsigned long l = strtoul(value, &endptr, 0); if (*endptr == '\0') { defaultQuality = (src_quality) l; ALOGD("forcing AudioResampler quality to %d", defaultQuality); if (defaultQuality < DEFAULT_QUALITY || defaultQuality > VERY_HIGH_QUALITY) { defaultQuality = DEFAULT_QUALITY; } } } } if (quality == DEFAULT) uint32_t AudioResampler::qualityMHz(src_quality quality) { switch (quality) { default: case DEFAULT_QUALITY: case LOW_QUALITY: return 3; case MED_QUALITY: return 6; case HIGH_QUALITY: return 20; case VERY_HIGH_QUALITY: return 34; } } static const uint32_t maxMHz = 75; // an arbitrary number that permits 2 VHQ, should be tunable static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static uint32_t currentMHz = 0; AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, int32_t sampleRate, src_quality quality) { bool atFinalQuality; if (quality == DEFAULT_QUALITY) { // read the resampler default quality property the first time it is needed int ok = pthread_once(&once_control, init_routine); if (ok != 0) { ALOGE("%s pthread_once failed: %d", __func__, ok); } quality = defaultQuality; atFinalQuality = false; } else { atFinalQuality = true; } // naive implementation of CPU load throttling doesn't account for whether resampler is active pthread_mutex_lock(&mutex); for (;;) { uint32_t deltaMHz = qualityMHz(quality); uint32_t newMHz = currentMHz + deltaMHz; if ((qualityIsSupported(quality) && newMHz <= maxMHz) || atFinalQuality) { ALOGV("resampler load %u -> %u MHz due to delta +%u MHz from quality %d", currentMHz, newMHz, deltaMHz, quality); currentMHz = newMHz; break; } // not enough CPU available for proposed quality level, so try next lowest level switch (quality) { default: case DEFAULT_QUALITY: case LOW_QUALITY: atFinalQuality = true; break; case MED_QUALITY: quality = LOW_QUALITY; break; case HIGH_QUALITY: quality = MED_QUALITY; break; case VERY_HIGH_QUALITY: quality = HIGH_QUALITY; break; } } pthread_mutex_unlock(&mutex); AudioResampler* resampler; switch (quality) { default: case DEFAULT_QUALITY: case LOW_QUALITY: ALOGV("Create linear Resampler"); resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate); break; #if 0 #if 0 // disabled because it has not been qualified recently, if requested will use default: case MED_QUALITY: ALOGV("Create cubic Resampler"); resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate); Loading @@ -110,6 +199,7 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, case HIGH_QUALITY: ALOGV("Create HIGH_QUALITY sinc Resampler"); resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate); break; case VERY_HIGH_QUALITY: ALOGV("Create VERY_HIGH_QUALITY sinc Resampler = %d", quality); resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate, quality); Loading @@ -122,17 +212,20 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, } AudioResampler::AudioResampler(int bitDepth, int inChannelCount, int32_t sampleRate) : int32_t sampleRate, src_quality quality) : mBitDepth(bitDepth), mChannelCount(inChannelCount), mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0), mPhaseFraction(0), mLocalTimeFreq(0), mPTS(AudioBufferProvider::kInvalidPTS) { mPTS(AudioBufferProvider::kInvalidPTS), mQuality(quality) { // sanity check on format if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) { ALOGE("Unsupported sample format, %d bits, %d channels", bitDepth, inChannelCount); // ALOG_ASSERT(0); } if (sampleRate <= 0) { ALOGE("Unsupported sample rate %d Hz", sampleRate); } // initialize common members mVolume[0] = mVolume[1] = 0; Loading @@ -141,6 +234,15 @@ AudioResampler::AudioResampler(int bitDepth, int inChannelCount, } AudioResampler::~AudioResampler() { pthread_mutex_lock(&mutex); src_quality quality = getQuality(); uint32_t deltaMHz = qualityMHz(quality); int32_t newMHz = currentMHz - deltaMHz; ALOGV("resampler load %u -> %d MHz due to delta -%u MHz from quality %d", currentMHz, newMHz, deltaMHz, quality); LOG_ALWAYS_FATAL_IF(newMHz < 0, "negative resampler load %d MHz", newMHz); currentMHz = newMHz; pthread_mutex_unlock(&mutex); } void AudioResampler::setSampleRate(int32_t inSampleRate) { Loading