diff options
| author | Paul McLean <pmclean@google.com> | 2014-05-15 14:29:58 -0700 |
|---|---|---|
| committer | Paul McLean <pmclean@google.com> | 2014-05-16 12:42:17 -0700 |
| commit | bb74f23cd3dc877c7eaf4db2132f724d11aeeb8f (patch) | |
| tree | d1805e811851de8bb2a84956c781f4adb8f41f3c /src | |
| parent | 5c763ec9f7e6975b9eba69eb64b6c50ccba33e85 (diff) | |
| download | android_frameworks_wilhelm-bb74f23cd3dc877c7eaf4db2132f724d11aeeb8f.tar.gz android_frameworks_wilhelm-bb74f23cd3dc877c7eaf4db2132f724d11aeeb8f.tar.bz2 android_frameworks_wilhelm-bb74f23cd3dc877c7eaf4db2132f724d11aeeb8f.zip | |
Initial Implementation of new NDK audio formats
Support for 24-bit audio formats - Support for Quad, 5.1 and 7.1
multi-channel output
Change-Id: I4e4f5d2915a43970ae01f552ba506591902aa070
Diffstat (limited to 'src')
| -rw-r--r-- | src/android/AudioPlayer_to_android.cpp | 72 | ||||
| -rw-r--r-- | src/android/android_sles_conversions.h | 20 | ||||
| -rw-r--r-- | src/data.c | 29 |
3 files changed, 110 insertions, 11 deletions
diff --git a/src/android/AudioPlayer_to_android.cpp b/src/android/AudioPlayer_to_android.cpp index d72cf4b..d17f680 100644 --- a/src/android/AudioPlayer_to_android.cpp +++ b/src/android/AudioPlayer_to_android.cpp @@ -854,6 +854,60 @@ static void sfplayer_handlePrefetchEvent(int event, int data1, int data2, void* ap->mCallbackProtector->exitCb(); } +// From EffectDownmix.h +const uint32_t kSides = AUDIO_CHANNEL_OUT_SIDE_LEFT | AUDIO_CHANNEL_OUT_SIDE_RIGHT; +const uint32_t kBacks = AUDIO_CHANNEL_OUT_BACK_LEFT | AUDIO_CHANNEL_OUT_BACK_RIGHT; +const uint32_t kUnsupported = + AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER | AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | + AUDIO_CHANNEL_OUT_TOP_CENTER | + AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT | + AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER | + AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT | + AUDIO_CHANNEL_OUT_TOP_BACK_LEFT | + AUDIO_CHANNEL_OUT_TOP_BACK_CENTER | + AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT; + +//TODO(pmclean) This will need to be revisited when arbitrary N-channel support is added. +SLresult android_audioPlayer_validateChannelMask(uint32_t mask, int numChans) { + // Check that the number of channels falls within bounds. + if (numChans < 0 || numChans > 8) { + return SL_RESULT_CONTENT_UNSUPPORTED; + } + // Are there the right number of channels in the mask? + if (popcount(mask) != numChans) { + return SL_RESULT_CONTENT_UNSUPPORTED; + } + // check against unsupported channels + if (mask & kUnsupported) { + ALOGE("Unsupported channels (top or front left/right of center)"); + return SL_RESULT_CONTENT_UNSUPPORTED; + } + // verify has FL/FR + if ((mask & AUDIO_CHANNEL_OUT_STEREO) != AUDIO_CHANNEL_OUT_STEREO) { + ALOGE("Front channels must be present"); + return SL_RESULT_CONTENT_UNSUPPORTED; + } + // verify uses SIDE as a pair (ok if not using SIDE at all) + bool hasSides = false; + if ((mask & kSides) != 0) { + if ((mask & kSides) != kSides) { + ALOGE("Side channels must be used as a pair"); + return SL_RESULT_CONTENT_UNSUPPORTED; + } + hasSides = true; + } + // verify uses BACK as a pair (ok if not using BACK at all) + bool hasBacks = false; + if ((mask & kBacks) != 0) { + if ((mask & kBacks) != kBacks) { + ALOGE("Back channels must be used as a pair"); + return SL_RESULT_CONTENT_UNSUPPORTED; + } + hasBacks = true; + } + + return SL_RESULT_SUCCESS; +} //----------------------------------------------------------------------------- SLresult android_audioPlayer_checkSourceSink(CAudioPlayer *pAudioPlayer) @@ -886,16 +940,14 @@ SLresult android_audioPlayer_checkSourceSink(CAudioPlayer *pAudioPlayer) // currently only PCM buffer queues are supported, case SL_DATAFORMAT_PCM: { SLDataFormat_PCM *df_pcm = (SLDataFormat_PCM *) pAudioSrc->pFormat; - switch (df_pcm->numChannels) { - case 1: - case 2: - break; - default: - // this should have already been rejected by checkDataFormat - SL_LOGE("Cannot create audio player: unsupported " \ - "PCM data source with %u channels", (unsigned) df_pcm->numChannels); - return SL_RESULT_CONTENT_UNSUPPORTED; + SLresult result = android_audioPlayer_validateChannelMask(df_pcm->channelMask, + df_pcm->numChannels); + if (result != SL_RESULT_SUCCESS) { + SL_LOGE("Cannot create audio player: unsupported PCM data source with %u channels", + (unsigned) df_pcm->numChannels); + return result; } + switch (df_pcm->samplesPerSec) { case SL_SAMPLINGRATE_8: case SL_SAMPLINGRATE_11_025: @@ -919,6 +971,7 @@ SLresult android_audioPlayer_checkSourceSink(CAudioPlayer *pAudioPlayer) switch (df_pcm->bitsPerSample) { case SL_PCMSAMPLEFORMAT_FIXED_8: case SL_PCMSAMPLEFORMAT_FIXED_16: + case SL_PCMSAMPLEFORMAT_FIXED_24: break; // others default: @@ -930,6 +983,7 @@ SLresult android_audioPlayer_checkSourceSink(CAudioPlayer *pAudioPlayer) switch (df_pcm->containerSize) { case 8: case 16: + case 24: break; // others default: diff --git a/src/android/android_sles_conversions.h b/src/android/android_sles_conversions.h index cab6578..6e53ac9 100644 --- a/src/android/android_sles_conversions.h +++ b/src/android/android_sles_conversions.h @@ -52,8 +52,13 @@ static inline audio_format_t sles_to_android_sampleFormat(SLuint32 pcmFormat) { case SL_PCMSAMPLEFORMAT_FIXED_8: return AUDIO_FORMAT_PCM_8_BIT; break; - case SL_PCMSAMPLEFORMAT_FIXED_20: case SL_PCMSAMPLEFORMAT_FIXED_24: + return AUDIO_FORMAT_PCM_8_24_BIT; + // Maybe one of these??? + // return AUDIO_FORMAT_PCM_32_BIT; + // return AUDIO_FORMAT_PCM_24_BIT_PACKED; + break; + case SL_PCMSAMPLEFORMAT_FIXED_20: case SL_PCMSAMPLEFORMAT_FIXED_28: case SL_PCMSAMPLEFORMAT_FIXED_32: default: @@ -93,6 +98,19 @@ static inline uint32_t channelCountToMask(uint32_t channelCount) return SL_SPEAKER_FRONT_LEFT; case 2: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; + // Android-specific + case 4: + return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT + | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT; + case 6: + return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT| SL_SPEAKER_FRONT_CENTER + | SL_SPEAKER_LOW_FREQUENCY + | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT; + case 8: + return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER + | SL_SPEAKER_LOW_FREQUENCY + | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT + | SL_SPEAKER_SIDE_LEFT |SL_SPEAKER_SIDE_RIGHT; default: return UNKNOWN_CHANNELMASK; } @@ -332,6 +332,15 @@ static void freeDataLocator(DataLocator *pDataLocator) /** \brief Check a data format and make local deep copy */ +#define SL_ANDROID_SPEAKER_QUAD (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT \ + | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT) + +#define SL_ANDROID_SPEAKER_5DOT1 (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT \ + | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY| SL_SPEAKER_BACK_LEFT \ + | SL_SPEAKER_BACK_RIGHT) + +#define SL_ANDROID_SPEAKER_7DOT1 (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT \ + |SL_SPEAKER_SIDE_RIGHT) static SLresult checkDataFormat(const char *name, void *pFormat, DataFormat *pDataFormat, SLuint32 allowedDataFormatMask) @@ -354,6 +363,9 @@ static SLresult checkDataFormat(const char *name, void *pFormat, DataFormat *pDa switch (pDataFormat->mPCM.numChannels) { case 1: // mono case 2: // stereo + case 4: // QUAD + case 6: // 5.1 + case 8: // 8.1 break; case 0: // unknown result = SL_RESULT_PARAMETER_INVALID; @@ -399,9 +411,9 @@ static SLresult checkDataFormat(const char *name, void *pFormat, DataFormat *pDa switch (pDataFormat->mPCM.bitsPerSample) { case SL_PCMSAMPLEFORMAT_FIXED_8: case SL_PCMSAMPLEFORMAT_FIXED_16: + case SL_PCMSAMPLEFORMAT_FIXED_24: break; case SL_PCMSAMPLEFORMAT_FIXED_20: - case SL_PCMSAMPLEFORMAT_FIXED_24: case SL_PCMSAMPLEFORMAT_FIXED_28: case SL_PCMSAMPLEFORMAT_FIXED_32: result = SL_RESULT_CONTENT_UNSUPPORTED; @@ -442,6 +454,21 @@ static SLresult checkDataFormat(const char *name, void *pFormat, DataFormat *pDa result = SL_RESULT_PARAMETER_INVALID; } break; + case SL_ANDROID_SPEAKER_QUAD: + if (4 != pDataFormat->mPCM.numChannels) { + result = SL_RESULT_PARAMETER_INVALID; + } + break; + case SL_ANDROID_SPEAKER_5DOT1: + if (6 != pDataFormat->mPCM.numChannels) { + result = SL_RESULT_PARAMETER_INVALID; + } + break; + case SL_ANDROID_SPEAKER_7DOT1: + if (8 != pDataFormat->mPCM.numChannels) { + result = SL_RESULT_PARAMETER_INVALID; + } + break; case 0: // The default of front left rather than center for mono may be non-intuitive, // but the left channel is the first channel for stereo or multichannel content. |
