1 /* 2 * Copyright (C) 2016 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 18 // cribbed from samples/native-audio 19 20 #define CHATTY ALOGD 21 #define LOG_TAG "audioplay" 22 23 #include "audioplay.h" 24 25 #include <string.h> 26 27 #include <utils/Log.h> 28 #include <utils/threads.h> 29 30 // for native audio 31 #include <SLES/OpenSLES.h> 32 #include <SLES/OpenSLES_Android.h> 33 34 #include "BootAnimationUtil.h" 35 36 namespace audioplay { 37 namespace { 38 39 using namespace android; 40 41 // engine interfaces 42 static SLObjectItf engineObject = nullptr; 43 static SLEngineItf engineEngine; 44 45 // output mix interfaces 46 static SLObjectItf outputMixObject = nullptr; 47 48 // buffer queue player interfaces 49 static SLObjectItf bqPlayerObject = nullptr; 50 static SLPlayItf bqPlayerPlay; 51 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; 52 static SLMuteSoloItf bqPlayerMuteSolo; 53 static SLVolumeItf bqPlayerVolume; 54 55 // pointer and size of the next player buffer to enqueue, and number of remaining buffers 56 static const uint8_t* nextBuffer; 57 static unsigned nextSize; 58 59 static const uint32_t ID_RIFF = 0x46464952; 60 static const uint32_t ID_WAVE = 0x45564157; 61 static const uint32_t ID_FMT = 0x20746d66; 62 static const uint32_t ID_DATA = 0x61746164; 63 64 struct RiffWaveHeader { 65 uint32_t riff_id; 66 uint32_t riff_sz; 67 uint32_t wave_id; 68 }; 69 70 struct ChunkHeader { 71 uint32_t id; 72 uint32_t sz; 73 }; 74 75 struct ChunkFormat { 76 uint16_t audio_format; 77 uint16_t num_channels; 78 uint32_t sample_rate; 79 uint32_t byte_rate; 80 uint16_t block_align; 81 uint16_t bits_per_sample; 82 }; 83 84 // this callback handler is called every time a buffer finishes playing 85 void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { 86 (void)bq; 87 (void)context; 88 audioplay::setPlaying(false); 89 } 90 91 bool hasPlayer() { 92 return (engineObject != nullptr && bqPlayerObject != nullptr); 93 } 94 95 // create the engine and output mix objects 96 bool createEngine() { 97 SLresult result; 98 99 // create engine 100 result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr); 101 if (result != SL_RESULT_SUCCESS) { 102 ALOGE("slCreateEngine failed with result %d", result); 103 return false; 104 } 105 (void)result; 106 107 // realize the engine 108 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 109 if (result != SL_RESULT_SUCCESS) { 110 ALOGE("sl engine Realize failed with result %d", result); 111 return false; 112 } 113 (void)result; 114 115 // get the engine interface, which is needed in order to create other objects 116 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 117 if (result != SL_RESULT_SUCCESS) { 118 ALOGE("sl engine GetInterface failed with result %d", result); 119 return false; 120 } 121 (void)result; 122 123 // create output mix 124 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr); 125 if (result != SL_RESULT_SUCCESS) { 126 ALOGE("sl engine CreateOutputMix failed with result %d", result); 127 return false; 128 } 129 (void)result; 130 131 // realize the output mix 132 result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); 133 if (result != SL_RESULT_SUCCESS) { 134 ALOGE("sl outputMix Realize failed with result %d", result); 135 return false; 136 } 137 (void)result; 138 139 return true; 140 } 141 142 // create buffer queue audio player 143 bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) { 144 SLresult result; 145 146 // configure audio source 147 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1}; 148 149 // Determine channelMask from num_channels 150 SLuint32 channelMask; 151 switch (chunkFormat->num_channels) { 152 case 1: 153 channelMask = SL_SPEAKER_FRONT_CENTER; 154 break; 155 case 2: 156 channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 157 break; 158 default: 159 // Default of 0 will derive mask from num_channels and log a warning. 160 channelMask = 0; 161 } 162 163 SLDataFormat_PCM format_pcm = { 164 SL_DATAFORMAT_PCM, 165 chunkFormat->num_channels, 166 chunkFormat->sample_rate * 1000, // convert to milliHz 167 chunkFormat->bits_per_sample, 168 16, 169 channelMask, 170 SL_BYTEORDER_LITTLEENDIAN 171 }; 172 SLDataSource audioSrc = {&loc_bufq, &format_pcm}; 173 174 // configure audio sink 175 SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; 176 SLDataSink audioSnk = {&loc_outmix, nullptr}; 177 178 // create audio player 179 const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME, SL_IID_ANDROIDCONFIGURATION}; 180 const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 181 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 182 3, ids, req); 183 if (result != SL_RESULT_SUCCESS) { 184 ALOGE("sl CreateAudioPlayer failed with result %d", result); 185 return false; 186 } 187 (void)result; 188 189 // Use the System stream for boot sound playback. 190 SLAndroidConfigurationItf playerConfig; 191 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, 192 SL_IID_ANDROIDCONFIGURATION, &playerConfig); 193 if (result != SL_RESULT_SUCCESS) { 194 ALOGE("config GetInterface failed with result %d", result); 195 return false; 196 } 197 SLint32 streamType = SL_ANDROID_STREAM_SYSTEM; 198 result = (*playerConfig)->SetConfiguration(playerConfig, 199 SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32)); 200 if (result != SL_RESULT_SUCCESS) { 201 ALOGE("SetConfiguration failed with result %d", result); 202 return false; 203 } 204 // use normal performance mode as low latency is not needed. This is not mandatory so 205 // do not bail if we fail 206 SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE; 207 result = (*playerConfig)->SetConfiguration( 208 playerConfig, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(SLuint32)); 209 ALOGW_IF(result != SL_RESULT_SUCCESS, 210 "could not set performance mode on player, error %d", result); 211 (void)result; 212 213 // realize the player 214 result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); 215 if (result != SL_RESULT_SUCCESS) { 216 ALOGE("sl player Realize failed with result %d", result); 217 return false; 218 } 219 (void)result; 220 221 // get the play interface 222 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); 223 if (result != SL_RESULT_SUCCESS) { 224 ALOGE("sl player GetInterface failed with result %d", result); 225 return false; 226 } 227 (void)result; 228 229 // get the buffer queue interface 230 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, 231 &bqPlayerBufferQueue); 232 if (result != SL_RESULT_SUCCESS) { 233 ALOGE("sl playberBufferQueue GetInterface failed with result %d", result); 234 return false; 235 } 236 (void)result; 237 238 // register callback on the buffer queue 239 result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr); 240 if (result != SL_RESULT_SUCCESS) { 241 ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result); 242 return false; 243 } 244 (void)result; 245 246 // get the volume interface 247 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); 248 if (result != SL_RESULT_SUCCESS) { 249 ALOGE("sl volume GetInterface failed with result %d", result); 250 return false; 251 } 252 (void)result; 253 254 // set the player's state to playing 255 audioplay::setPlaying(true); 256 CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue); 257 return true; 258 } 259 260 bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat, 261 const uint8_t** oSoundBuf, unsigned* oSoundBufSize) { 262 *oSoundBuf = clipBuf; 263 *oSoundBufSize = clipBufSize; 264 *oChunkFormat = nullptr; 265 const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf; 266 if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || 267 (wavHeader->wave_id != ID_WAVE)) { 268 ALOGE("Error: audio file is not a riff/wave file\n"); 269 return false; 270 } 271 *oSoundBuf += sizeof(*wavHeader); 272 *oSoundBufSize -= sizeof(*wavHeader); 273 274 while (true) { 275 const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf; 276 if (*oSoundBufSize < sizeof(*chunkHeader)) { 277 ALOGE("EOF reading chunk headers"); 278 return false; 279 } 280 281 *oSoundBuf += sizeof(*chunkHeader); 282 *oSoundBufSize -= sizeof(*chunkHeader); 283 284 bool endLoop = false; 285 switch (chunkHeader->id) { 286 case ID_FMT: 287 *oChunkFormat = (const ChunkFormat*)*oSoundBuf; 288 *oSoundBuf += chunkHeader->sz; 289 *oSoundBufSize -= chunkHeader->sz; 290 break; 291 case ID_DATA: 292 /* Stop looking for chunks */ 293 *oSoundBufSize = chunkHeader->sz; 294 endLoop = true; 295 break; 296 default: 297 /* Unknown chunk, skip bytes */ 298 *oSoundBuf += chunkHeader->sz; 299 *oSoundBufSize -= chunkHeader->sz; 300 } 301 if (endLoop) { 302 break; 303 } 304 } 305 306 if (*oChunkFormat == nullptr) { 307 ALOGE("format not found in WAV file"); 308 return false; 309 } 310 return true; 311 } 312 313 class InitAudioThread : public Thread { 314 public: 315 InitAudioThread(uint8_t* exampleAudioData, int exampleAudioLength) 316 : Thread(false), 317 mExampleAudioData(exampleAudioData), 318 mExampleAudioLength(exampleAudioLength) {} 319 private: 320 virtual bool threadLoop() { 321 audioplay::create(mExampleAudioData, mExampleAudioLength); 322 // Exit immediately 323 return false; 324 } 325 326 uint8_t* mExampleAudioData; 327 int mExampleAudioLength; 328 }; 329 330 // Typedef to aid readability. 331 typedef android::BootAnimation::Animation Animation; 332 333 class AudioAnimationCallbacks : public android::BootAnimation::Callbacks { 334 public: 335 void init(const Vector<Animation::Part>& parts) override { 336 const Animation::Part* partWithAudio = nullptr; 337 for (const Animation::Part& part : parts) { 338 if (part.audioData != nullptr) { 339 partWithAudio = ∂ 340 break; 341 } 342 } 343 344 if (partWithAudio == nullptr) { 345 return; 346 } 347 348 ALOGD("found audio.wav, creating playback engine"); 349 // The audioData is used to initialize the audio system. Different data 350 // can be played later for other parts BUT the assumption is that they 351 // will all be the same format and only the format of this audioData 352 // will work correctly. 353 initAudioThread = new InitAudioThread(partWithAudio->audioData, 354 partWithAudio->audioLength); 355 initAudioThread->run("BootAnimation::InitAudioThread", PRIORITY_NORMAL); 356 }; 357 358 void playPart(int partNumber, const Animation::Part& part, int playNumber) override { 359 // only play audio file the first time we animate the part 360 if (playNumber == 0 && part.audioData && playSoundsAllowed()) { 361 ALOGD("playing clip for part%d, size=%d", 362 partNumber, part.audioLength); 363 // Block until the audio engine is finished initializing. 364 if (initAudioThread != nullptr) { 365 initAudioThread->join(); 366 } 367 audioplay::playClip(part.audioData, part.audioLength); 368 } 369 }; 370 371 void shutdown() override { 372 // we've finally played everything we're going to play 373 audioplay::setPlaying(false); 374 audioplay::destroy(); 375 }; 376 377 private: 378 sp<InitAudioThread> initAudioThread = nullptr; 379 }; 380 381 } // namespace 382 383 bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) { 384 if (!createEngine()) { 385 return false; 386 } 387 388 // Parse the example clip. 389 const ChunkFormat* chunkFormat; 390 const uint8_t* soundBuf; 391 unsigned soundBufSize; 392 if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) { 393 return false; 394 } 395 396 // Initialize the BufferQueue based on this clip's format. 397 if (!createBufferQueueAudioPlayer(chunkFormat)) { 398 return false; 399 } 400 return true; 401 } 402 403 bool playClip(const uint8_t* buf, int size) { 404 // Parse the WAV header 405 const ChunkFormat* chunkFormat; 406 if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) { 407 return false; 408 } 409 410 if (!hasPlayer()) { 411 ALOGD("cannot play clip %p without a player", buf); 412 return false; 413 } 414 415 CHATTY("playClip on player %p: buf=%p size=%d nextSize %d", 416 bqPlayerBufferQueue, buf, size, nextSize); 417 418 if (nextSize > 0) { 419 // here we only enqueue one buffer because it is a long clip, 420 // but for streaming playback we would typically enqueue at least 2 buffers to start 421 SLresult result; 422 result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); 423 if (SL_RESULT_SUCCESS != result) { 424 return false; 425 } 426 audioplay::setPlaying(true); 427 } 428 429 return true; 430 } 431 432 // set the playing state for the buffer queue audio player 433 void setPlaying(bool isPlaying) { 434 if (!hasPlayer()) return; 435 436 SLresult result; 437 438 if (nullptr != bqPlayerPlay) { 439 // set the player's state 440 result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, 441 isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED); 442 } 443 444 } 445 446 void destroy() { 447 // destroy buffer queue audio player object, and invalidate all associated interfaces 448 if (bqPlayerObject != nullptr) { 449 CHATTY("destroying audio player"); 450 (*bqPlayerObject)->Destroy(bqPlayerObject); 451 bqPlayerObject = nullptr; 452 bqPlayerPlay = nullptr; 453 bqPlayerBufferQueue = nullptr; 454 bqPlayerMuteSolo = nullptr; 455 bqPlayerVolume = nullptr; 456 } 457 458 // destroy output mix object, and invalidate all associated interfaces 459 if (outputMixObject != nullptr) { 460 (*outputMixObject)->Destroy(outputMixObject); 461 outputMixObject = nullptr; 462 } 463 464 // destroy engine object, and invalidate all associated interfaces 465 if (engineObject != nullptr) { 466 CHATTY("destroying audio engine"); 467 (*engineObject)->Destroy(engineObject); 468 engineObject = nullptr; 469 engineEngine = nullptr; 470 } 471 } 472 473 sp<BootAnimation::Callbacks> createAnimationCallbacks() { 474 return new AudioAnimationCallbacks(); 475 } 476 477 } // namespace audioplay 478