Loading include/media/AudioResamplerPublic.h +19 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef ANDROID_AUDIO_RESAMPLER_PUBLIC_H #define ANDROID_AUDIO_RESAMPLER_PUBLIC_H #include <stdint.h> // AUDIO_RESAMPLER_DOWN_RATIO_MAX is the maximum ratio between the original // audio sample rate and the target rate when downsampling, // as permitted in the audio framework, e.g. AudioTrack and AudioFlinger. Loading @@ -26,6 +28,12 @@ // TODO: replace with an API #define AUDIO_RESAMPLER_DOWN_RATIO_MAX 256 // AUDIO_RESAMPLER_UP_RATIO_MAX is the maximum suggested ratio between the original // audio sample rate and the target rate when upsampling. It is loosely enforced by // the system. One issue with large upsampling ratios is the approximation by // an int32_t of the phase increments, making the resulting sample rate inexact. #define AUDIO_RESAMPLER_UP_RATIO_MAX 65536 // Returns the source frames needed to resample to destination frames. This is not a precise // value and depends on the resampler (and possibly how it handles rounding internally). // Nevertheless, this should be an upper bound on the requirements of the resampler. Loading @@ -39,4 +47,15 @@ static inline size_t sourceFramesNeeded( size_t((uint64_t)dstFramesRequired * srcSampleRate / dstSampleRate + 1 + 1); } // An upper bound for the number of destination frames possible from srcFrames // after sample rate conversion. This may be used for buffer sizing. static inline size_t destinationFramesPossible(size_t srcFrames, uint32_t srcSampleRate, uint32_t dstSampleRate) { if (srcSampleRate == dstSampleRate) { return srcFrames; } uint64_t dstFrames = (uint64_t)srcFrames * dstSampleRate / srcSampleRate; return dstFrames > 2 ? dstFrames - 2 : 0; } #endif // ANDROID_AUDIO_RESAMPLER_PUBLIC_H media/libmedia/AudioRecord.cpp +3 −7 Original line number Diff line number Diff line Loading @@ -189,13 +189,9 @@ status_t AudioRecord::set( } // validate parameters if (!audio_is_valid_format(format)) { ALOGE("Invalid format %#x", format); return BAD_VALUE; } // Temporary restriction: AudioFlinger currently supports 16-bit PCM only if (format != AUDIO_FORMAT_PCM_16_BIT) { ALOGE("Format %#x is not supported", format); // AudioFlinger capture only supports linear PCM if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) { ALOGE("Format %#x is not linear pcm", format); return BAD_VALUE; } mFormat = format; Loading services/audioflinger/AudioFlinger.cpp +42 −14 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ #include "AudioFlinger.h" #include "ServiceUtilities.h" #include <media/AudioResamplerPublic.h> #include <media/EffectsFactoryApi.h> #include <audio_effects/effect_visualizer.h> #include <audio_effects/effect_ns.h> Loading Loading @@ -1140,19 +1142,46 @@ size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t form if (ret != NO_ERROR) { return 0; } if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) { return 0; } AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE; audio_config_t config; memset(&config, 0, sizeof(config)); config.sample_rate = sampleRate; config.channel_mask = channelMask; config.format = format; audio_config_t config, proposed; memset(&proposed, 0, sizeof(proposed)); proposed.sample_rate = sampleRate; proposed.channel_mask = channelMask; proposed.format = format; audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice(); size_t size = dev->get_input_buffer_size(dev, &config); size_t frames; for (;;) { // Note: config is currently a const parameter for get_input_buffer_size() // but we use a copy from proposed in case config changes from the call. config = proposed; frames = dev->get_input_buffer_size(dev, &config); if (frames != 0) { break; // hal success, config is the result } // change one parameter of the configuration each iteration to a more "common" value // to see if the device will support it. if (proposed.format != AUDIO_FORMAT_PCM_16_BIT) { proposed.format = AUDIO_FORMAT_PCM_16_BIT; } else if (proposed.sample_rate != 44100) { // 44.1 is claimed as must in CDD as well as proposed.sample_rate = 44100; // legacy AudioRecord.java. TODO: Query hw? } else { ALOGW("getInputBufferSize failed with minimum buffer size sampleRate %u, " "format %#x, channelMask 0x%X", sampleRate, format, channelMask); break; // retries failed, break out of loop with frames == 0. } } mHardwareStatus = AUDIO_HW_IDLE; return size; if (frames > 0 && config.sample_rate != sampleRate) { frames = destinationFramesPossible(frames, sampleRate, config.sample_rate); } return frames; // may be converted to bytes at the Java level. } uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const Loading Loading @@ -1419,9 +1448,8 @@ sp<IAudioRecord> AudioFlinger::openRecord( goto Exit; } // we don't yet support anything other than 16-bit PCM if (!(audio_is_valid_format(format) && audio_is_linear_pcm(format) && format == AUDIO_FORMAT_PCM_16_BIT)) { // we don't yet support anything other than linear PCM if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) { ALOGE("openRecord() invalid format %#x", format); lStatus = BAD_VALUE; goto Exit; Loading Loading @@ -2002,11 +2030,11 @@ sp<AudioFlinger::RecordThread> AudioFlinger::openInput_l(audio_module_handle_t m status, address.string()); // If the input could not be opened with the requested parameters and we can handle the // conversion internally, try to open again with the proposed parameters. The AudioFlinger can // resample the input and do mono to stereo or stereo to mono conversions on 16 bit PCM inputs. // conversion internally, try to open again with the proposed parameters. if (status == BAD_VALUE && config->format == halconfig.format && halconfig.format == AUDIO_FORMAT_PCM_16_BIT && (halconfig.sample_rate <= 2 * config->sample_rate) && audio_is_linear_pcm(config->format) && audio_is_linear_pcm(halconfig.format) && (halconfig.sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) && (audio_channel_count_from_in_mask(halconfig.channel_mask) <= FCC_2) && (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_2)) { // FIXME describe the change proposed by HAL (save old values so we can log them here) Loading services/audioflinger/Threads.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -86,7 +86,13 @@ #define ALOGVV(a...) do { } while(0) #endif // TODO: Move these macro/inlines to a header file. #define max(a, b) ((a) > (b) ? (a) : (b)) template <typename T> static inline T min(const T& a, const T& b) { return a < b ? a : b; } namespace android { Loading Loading @@ -5622,6 +5628,13 @@ reacquire_wakelock: break; } // Don't allow framesOut to be larger than what is possible with resampling // from framesIn. // This isn't strictly necessary but helps limit buffer resizing in // RecordBufferConverter. TODO: remove when no longer needed. framesOut = min(framesOut, destinationFramesPossible( framesIn, mSampleRate, activeTrack->mSampleRate)); // process frames from the RecordThread buffer provider to the RecordTrack buffer framesOut = activeTrack->mRecordBufferConverter->convert( activeTrack->mSink.raw, activeTrack->mResamplerBufferProvider, framesOut); Loading Loading
include/media/AudioResamplerPublic.h +19 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef ANDROID_AUDIO_RESAMPLER_PUBLIC_H #define ANDROID_AUDIO_RESAMPLER_PUBLIC_H #include <stdint.h> // AUDIO_RESAMPLER_DOWN_RATIO_MAX is the maximum ratio between the original // audio sample rate and the target rate when downsampling, // as permitted in the audio framework, e.g. AudioTrack and AudioFlinger. Loading @@ -26,6 +28,12 @@ // TODO: replace with an API #define AUDIO_RESAMPLER_DOWN_RATIO_MAX 256 // AUDIO_RESAMPLER_UP_RATIO_MAX is the maximum suggested ratio between the original // audio sample rate and the target rate when upsampling. It is loosely enforced by // the system. One issue with large upsampling ratios is the approximation by // an int32_t of the phase increments, making the resulting sample rate inexact. #define AUDIO_RESAMPLER_UP_RATIO_MAX 65536 // Returns the source frames needed to resample to destination frames. This is not a precise // value and depends on the resampler (and possibly how it handles rounding internally). // Nevertheless, this should be an upper bound on the requirements of the resampler. Loading @@ -39,4 +47,15 @@ static inline size_t sourceFramesNeeded( size_t((uint64_t)dstFramesRequired * srcSampleRate / dstSampleRate + 1 + 1); } // An upper bound for the number of destination frames possible from srcFrames // after sample rate conversion. This may be used for buffer sizing. static inline size_t destinationFramesPossible(size_t srcFrames, uint32_t srcSampleRate, uint32_t dstSampleRate) { if (srcSampleRate == dstSampleRate) { return srcFrames; } uint64_t dstFrames = (uint64_t)srcFrames * dstSampleRate / srcSampleRate; return dstFrames > 2 ? dstFrames - 2 : 0; } #endif // ANDROID_AUDIO_RESAMPLER_PUBLIC_H
media/libmedia/AudioRecord.cpp +3 −7 Original line number Diff line number Diff line Loading @@ -189,13 +189,9 @@ status_t AudioRecord::set( } // validate parameters if (!audio_is_valid_format(format)) { ALOGE("Invalid format %#x", format); return BAD_VALUE; } // Temporary restriction: AudioFlinger currently supports 16-bit PCM only if (format != AUDIO_FORMAT_PCM_16_BIT) { ALOGE("Format %#x is not supported", format); // AudioFlinger capture only supports linear PCM if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) { ALOGE("Format %#x is not linear pcm", format); return BAD_VALUE; } mFormat = format; Loading
services/audioflinger/AudioFlinger.cpp +42 −14 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ #include "AudioFlinger.h" #include "ServiceUtilities.h" #include <media/AudioResamplerPublic.h> #include <media/EffectsFactoryApi.h> #include <audio_effects/effect_visualizer.h> #include <audio_effects/effect_ns.h> Loading Loading @@ -1140,19 +1142,46 @@ size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t form if (ret != NO_ERROR) { return 0; } if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) { return 0; } AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE; audio_config_t config; memset(&config, 0, sizeof(config)); config.sample_rate = sampleRate; config.channel_mask = channelMask; config.format = format; audio_config_t config, proposed; memset(&proposed, 0, sizeof(proposed)); proposed.sample_rate = sampleRate; proposed.channel_mask = channelMask; proposed.format = format; audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice(); size_t size = dev->get_input_buffer_size(dev, &config); size_t frames; for (;;) { // Note: config is currently a const parameter for get_input_buffer_size() // but we use a copy from proposed in case config changes from the call. config = proposed; frames = dev->get_input_buffer_size(dev, &config); if (frames != 0) { break; // hal success, config is the result } // change one parameter of the configuration each iteration to a more "common" value // to see if the device will support it. if (proposed.format != AUDIO_FORMAT_PCM_16_BIT) { proposed.format = AUDIO_FORMAT_PCM_16_BIT; } else if (proposed.sample_rate != 44100) { // 44.1 is claimed as must in CDD as well as proposed.sample_rate = 44100; // legacy AudioRecord.java. TODO: Query hw? } else { ALOGW("getInputBufferSize failed with minimum buffer size sampleRate %u, " "format %#x, channelMask 0x%X", sampleRate, format, channelMask); break; // retries failed, break out of loop with frames == 0. } } mHardwareStatus = AUDIO_HW_IDLE; return size; if (frames > 0 && config.sample_rate != sampleRate) { frames = destinationFramesPossible(frames, sampleRate, config.sample_rate); } return frames; // may be converted to bytes at the Java level. } uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const Loading Loading @@ -1419,9 +1448,8 @@ sp<IAudioRecord> AudioFlinger::openRecord( goto Exit; } // we don't yet support anything other than 16-bit PCM if (!(audio_is_valid_format(format) && audio_is_linear_pcm(format) && format == AUDIO_FORMAT_PCM_16_BIT)) { // we don't yet support anything other than linear PCM if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) { ALOGE("openRecord() invalid format %#x", format); lStatus = BAD_VALUE; goto Exit; Loading Loading @@ -2002,11 +2030,11 @@ sp<AudioFlinger::RecordThread> AudioFlinger::openInput_l(audio_module_handle_t m status, address.string()); // If the input could not be opened with the requested parameters and we can handle the // conversion internally, try to open again with the proposed parameters. The AudioFlinger can // resample the input and do mono to stereo or stereo to mono conversions on 16 bit PCM inputs. // conversion internally, try to open again with the proposed parameters. if (status == BAD_VALUE && config->format == halconfig.format && halconfig.format == AUDIO_FORMAT_PCM_16_BIT && (halconfig.sample_rate <= 2 * config->sample_rate) && audio_is_linear_pcm(config->format) && audio_is_linear_pcm(halconfig.format) && (halconfig.sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) && (audio_channel_count_from_in_mask(halconfig.channel_mask) <= FCC_2) && (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_2)) { // FIXME describe the change proposed by HAL (save old values so we can log them here) Loading
services/audioflinger/Threads.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -86,7 +86,13 @@ #define ALOGVV(a...) do { } while(0) #endif // TODO: Move these macro/inlines to a header file. #define max(a, b) ((a) > (b) ? (a) : (b)) template <typename T> static inline T min(const T& a, const T& b) { return a < b ? a : b; } namespace android { Loading Loading @@ -5622,6 +5628,13 @@ reacquire_wakelock: break; } // Don't allow framesOut to be larger than what is possible with resampling // from framesIn. // This isn't strictly necessary but helps limit buffer resizing in // RecordBufferConverter. TODO: remove when no longer needed. framesOut = min(framesOut, destinationFramesPossible( framesIn, mSampleRate, activeTrack->mSampleRate)); // process frames from the RecordThread buffer provider to the RecordTrack buffer framesOut = activeTrack->mRecordBufferConverter->convert( activeTrack->mSink.raw, activeTrack->mResamplerBufferProvider, framesOut); Loading