1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //#define LOG_NDEBUG 0 18 #define LOG_TAG "SL-Utils" 19 20 #include "sl-utils.h" 21 #include <utils/Mutex.h> 22 23 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 24 25 // These will wind up in <SLES/OpenSLES_Android.h> 26 #define SL_ANDROID_SPEAKER_QUAD (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT \ 27 | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT) 28 29 #define SL_ANDROID_SPEAKER_5DOT1 (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT \ 30 | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY| SL_SPEAKER_BACK_LEFT \ 31 | SL_SPEAKER_BACK_RIGHT) 32 33 #define SL_ANDROID_SPEAKER_7DOT1 (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT \ 34 |SL_SPEAKER_SIDE_RIGHT) 35 36 namespace android { 37 38 static Mutex gLock; 39 static SLObjectItf gEngineObject; 40 static unsigned gRefCount; 41 42 static const char *gErrorStrings[] = { 43 "SL_RESULT_SUCCESS", // 0 44 "SL_RESULT_PRECONDITIONS_VIOLATE", // 1 45 "SL_RESULT_PARAMETER_INVALID", // 2 46 "SL_RESULT_MEMORY_FAILURE", // 3 47 "SL_RESULT_RESOURCE_ERROR", // 4 48 "SL_RESULT_RESOURCE_LOST", // 5 49 "SL_RESULT_IO_ERROR", // 6 50 "SL_RESULT_BUFFER_INSUFFICIENT", // 7 51 "SL_RESULT_CONTENT_CORRUPTED", // 8 52 "SL_RESULT_CONTENT_UNSUPPORTED", // 9 53 "SL_RESULT_CONTENT_NOT_FOUND", // 10 54 "SL_RESULT_PERMISSION_DENIED", // 11 55 "SL_RESULT_FEATURE_UNSUPPORTED", // 12 56 "SL_RESULT_INTERNAL_ERROR", // 13 57 "SL_RESULT_UNKNOWN_ERROR", // 14 58 "SL_RESULT_OPERATION_ABORTED", // 15 59 "SL_RESULT_CONTROL_LOST", // 16 60 }; 61 62 const char *getSLErrStr(int code) { 63 if ((size_t)code >= ARRAY_SIZE(gErrorStrings)) { 64 return "SL_RESULT_UNKNOWN"; 65 } 66 return gErrorStrings[code]; 67 } 68 69 SLuint32 channelCountToMask(unsigned channelCount) { 70 switch (channelCount) { 71 case 1: 72 return SL_SPEAKER_FRONT_LEFT; // we prefer left over center 73 case 2: 74 return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 75 case 3: 76 return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER; 77 case 4: 78 return SL_ANDROID_SPEAKER_QUAD; 79 case 5: 80 return SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER; 81 case 6: 82 return SL_ANDROID_SPEAKER_5DOT1; 83 case 7: 84 return SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER; 85 case 8: 86 return SL_ANDROID_SPEAKER_7DOT1; 87 default: 88 return 0; 89 } 90 } 91 92 static SLObjectItf createEngine() { 93 static SLEngineOption EngineOption[] = { 94 { 95 (SLuint32) SL_ENGINEOPTION_THREADSAFE, 96 (SLuint32) SL_BOOLEAN_TRUE 97 }, 98 }; 99 // create engine in thread-safe mode 100 SLObjectItf engine; 101 SLresult result = slCreateEngine(&engine, 102 1 /* numOptions */, EngineOption /* pEngineOptions */, 103 0 /* numInterfaces */, NULL /* pInterfaceIds */, NULL /* pInterfaceRequired */); 104 if (result != SL_RESULT_SUCCESS) { 105 ALOGE("slCreateEngine() failed: %s", getSLErrStr(result)); 106 return NULL; 107 } 108 // realize the engine 109 result = (*engine)->Realize(engine, SL_BOOLEAN_FALSE /* async */); 110 if (result != SL_RESULT_SUCCESS) { 111 ALOGE("Realize() failed: %s", getSLErrStr(result)); 112 (*engine)->Destroy(engine); 113 return NULL; 114 } 115 return engine; 116 } 117 118 SLObjectItf OpenSLEngine(bool global) { 119 120 if (!global) { 121 return createEngine(); 122 } 123 Mutex::Autolock l(gLock); 124 if (gRefCount == 0) { 125 gEngineObject = createEngine(); 126 } 127 gRefCount++; 128 return gEngineObject; 129 } 130 131 void CloseSLEngine(SLObjectItf engine) { 132 Mutex::Autolock l(gLock); 133 if (engine == gEngineObject) { 134 if (gRefCount == 0) { 135 ALOGE("CloseSLEngine(%p): refcount already 0", engine); 136 return; 137 } 138 if (--gRefCount != 0) { 139 return; 140 } 141 gEngineObject = NULL; 142 } 143 (*engine)->Destroy(engine); 144 } 145 146 } // namespace android 147 148