summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul McLean <pmclean@google.com>2014-05-15 14:29:58 -0700
committerPaul McLean <pmclean@google.com>2014-05-16 12:42:17 -0700
commitbb74f23cd3dc877c7eaf4db2132f724d11aeeb8f (patch)
treed1805e811851de8bb2a84956c781f4adb8f41f3c /src
parent5c763ec9f7e6975b9eba69eb64b6c50ccba33e85 (diff)
downloadandroid_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.cpp72
-rw-r--r--src/android/android_sles_conversions.h20
-rw-r--r--src/data.c29
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;
}
diff --git a/src/data.c b/src/data.c
index 727b484..4b25632 100644
--- a/src/data.c
+++ b/src/data.c
@@ -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.