bool PcmAudioService::enqueue() { if (_controller->hasPlayingTacks()) { if (_controller->isPaused()) { SLresult r = (*_bufferQueueItf)->Enqueue(_bufferQueueItf, __silenceData.data(), __silenceData.size()); SL_RETURN_VAL_IF_FAILED(r, false, "enqueue silent data failed!"); } else { _controller->mixOneFrame(); auto current = _controller->current(); ALOG_ASSERT(current != nullptr, "current buffer is nullptr ..."); SLresult r = (*_bufferQueueItf)->Enqueue(_bufferQueueItf, current->buf, current->size); SL_RETURN_VAL_IF_FAILED(r, false, "enqueue failed!"); } } else { SLresult r = (*_bufferQueueItf)->Enqueue(_bufferQueueItf, __silenceData.data(), __silenceData.size()); SL_RETURN_VAL_IF_FAILED(r, false, "enqueue silent data failed!"); } return true; }
bool UrlAudioPlayer::setPosition(float pos) { SLmillisecond millisecond = 1000.0f * pos; SLresult r = (*_seekItf)->SetPosition(_seekItf, millisecond, SL_SEEKMODE_ACCURATE); SL_RETURN_VAL_IF_FAILED(r, false, "UrlAudioPlayer::setPosition %f failed", pos); return true; }
float UrlAudioPlayer::getPosition() const { SLmillisecond millisecond; SLresult r = (*_playItf)->GetPosition(_playItf, &millisecond); SL_RETURN_VAL_IF_FAILED(r, 0.0f, "UrlAudioPlayer::getPosition failed"); return millisecond / 1000.0f; }
float UrlAudioPlayer::getDuration() const { if (_duration > 0) { return _duration; } SLmillisecond duration; SLresult r = (*_playItf)->GetDuration(_playItf, &duration); SL_RETURN_VAL_IF_FAILED(r, 0.0f, "UrlAudioPlayer::getDuration failed"); if (duration == SL_TIME_UNKNOWN) { return -1.0f; } else { const_cast<UrlAudioPlayer *>(this)->_duration = duration / 1000.0f; if (_duration <= 0) { return -1.0f; } } return _duration; }
bool PcmAudioService::init(AudioMixerController* controller, int numChannels, int sampleRate, int bufferSizeInBytes) { _controller = controller; _numChannels = numChannels; _sampleRate = sampleRate; _bufferSizeInBytes = bufferSizeInBytes; SLuint32 channelMask = SL_SPEAKER_FRONT_CENTER; if (numChannels > 1) { channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; } SLDataFormat_PCM formatPcm = { SL_DATAFORMAT_PCM, (SLuint32) numChannels, (SLuint32) sampleRate * 1000, SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, channelMask, SL_BYTEORDER_LITTLEENDIAN }; SLDataLocator_AndroidSimpleBufferQueue locBufQueue = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, AUDIO_PLAYER_BUFFER_COUNT }; SLDataSource source = {&locBufQueue, &formatPcm}; SLDataLocator_OutputMix locOutmix = { SL_DATALOCATOR_OUTPUTMIX, _outputMixObj }; SLDataSink sink = {&locOutmix, nullptr}; const SLInterfaceID ids[] = { SL_IID_PLAY, SL_IID_VOLUME, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, }; const SLboolean req[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, }; SLresult r; r = (*_engineItf)->CreateAudioPlayer(_engineItf, &_playObj, &source, &sink, sizeof(ids) / sizeof(ids[0]), ids, req); SL_RETURN_VAL_IF_FAILED(r, false, "CreateAudioPlayer failed"); r = (*_playObj)->Realize(_playObj, SL_BOOLEAN_FALSE); SL_RETURN_VAL_IF_FAILED(r, false, "Realize failed"); r = (*_playObj)->GetInterface(_playObj, SL_IID_PLAY, &_playItf); SL_RETURN_VAL_IF_FAILED(r, false, "GetInterface SL_IID_PLAY failed"); r = (*_playObj)->GetInterface(_playObj, SL_IID_VOLUME, &_volumeItf); SL_RETURN_VAL_IF_FAILED(r, false, "GetInterface SL_IID_VOLUME failed"); r = (*_playObj)->GetInterface(_playObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &_bufferQueueItf); SL_RETURN_VAL_IF_FAILED(r, false, "GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE failed"); r = (*_bufferQueueItf)->RegisterCallback(_bufferQueueItf, SLPcmAudioPlayerCallbackProxy::samplePlayerCallback, this); SL_RETURN_VAL_IF_FAILED(r, false, "_bufferQueueItf RegisterCallback failed"); if (__silenceData.empty()) { __silenceData.resize(_numChannels * _bufferSizeInBytes, 0x00); } r = (*_bufferQueueItf)->Enqueue(_bufferQueueItf, __silenceData.data(), __silenceData.size()); SL_RETURN_VAL_IF_FAILED(r, false, "_bufferQueueItf Enqueue failed"); r = (*_playItf)->SetPlayState(_playItf, SL_PLAYSTATE_PLAYING); SL_RETURN_VAL_IF_FAILED(r, false, "SetPlayState failed"); return true; }
bool UrlAudioPlayer::prepare(const std::string &url, SLuint32 locatorType, std::shared_ptr<AssetFd> assetFd, int start, int length) { _url = url; _assetFd = assetFd; const char* locatorTypeStr= "UNKNOWN"; if (locatorType == SL_DATALOCATOR_ANDROIDFD) locatorTypeStr = "SL_DATALOCATOR_ANDROIDFD"; else if (locatorType == SL_DATALOCATOR_URI) locatorTypeStr = "SL_DATALOCATOR_URI"; else { ALOGE("Oops, invalid locatorType: %d", (int)locatorType); return false; } ALOGV("UrlAudioPlayer::prepare: %s, %s, %d, %d, %d", _url.c_str(), locatorTypeStr, _assetFd->getFd(), start, length); SLDataSource audioSrc; SLDataFormat_MIME formatMime = {SL_DATAFORMAT_MIME, nullptr, SL_CONTAINERTYPE_UNSPECIFIED}; audioSrc.pFormat = &formatMime; //Note: locFd & locUri should be outside of the following if/else block // Although locFd & locUri are only used inside if/else block, its lifecycle // will be destroyed right after '}' block. And since we pass a pointer to // 'audioSrc.pLocator=&locFd/&locUri', pLocator will point to an invalid address // while invoking Engine::createAudioPlayer interface. So be care of change the position // of these two variables. SLDataLocator_AndroidFD locFd; SLDataLocator_URI locUri; if (locatorType == SL_DATALOCATOR_ANDROIDFD) { locFd = {locatorType, _assetFd->getFd(), start, length}; audioSrc.pLocator = &locFd; } else if (locatorType == SL_DATALOCATOR_URI) { locUri = {locatorType, (SLchar *) _url.c_str()}; audioSrc.pLocator = &locUri; ALOGV("locUri: locatorType: %d", (int)locUri.locatorType); } // configure audio sink SLDataLocator_OutputMix locOutmix = {SL_DATALOCATOR_OUTPUTMIX, _outputMixObj}; SLDataSink audioSnk = {&locOutmix, nullptr}; // create audio player const SLInterfaceID ids[3] = {SL_IID_SEEK, SL_IID_PREFETCHSTATUS, SL_IID_VOLUME}; const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; SLresult result = (*_engineItf)->CreateAudioPlayer(_engineItf, &_playObj, &audioSrc, &audioSnk, 3, ids, req); SL_RETURN_VAL_IF_FAILED(result, false, "CreateAudioPlayer failed"); // realize the player result = (*_playObj)->Realize(_playObj, SL_BOOLEAN_FALSE); SL_RETURN_VAL_IF_FAILED(result, false, "Realize failed"); // get the play interface result = (*_playObj)->GetInterface(_playObj, SL_IID_PLAY, &_playItf); SL_RETURN_VAL_IF_FAILED(result, false, "GetInterface SL_IID_PLAY failed"); // get the seek interface result = (*_playObj)->GetInterface(_playObj, SL_IID_SEEK, &_seekItf); SL_RETURN_VAL_IF_FAILED(result, false, "GetInterface SL_IID_SEEK failed"); // get the volume interface result = (*_playObj)->GetInterface(_playObj, SL_IID_VOLUME, &_volumeItf); SL_RETURN_VAL_IF_FAILED(result, false, "GetInterface SL_IID_VOLUME failed"); result = (*_playItf)->RegisterCallback(_playItf, SLUrlAudioPlayerCallbackProxy::playEventCallback, this); SL_RETURN_VAL_IF_FAILED(result, false, "RegisterCallback failed"); result = (*_playItf)->SetCallbackEventsMask(_playItf, SL_PLAYEVENT_HEADATEND); SL_RETURN_VAL_IF_FAILED(result, false, "SetCallbackEventsMask SL_PLAYEVENT_HEADATEND failed"); setState(State::INITIALIZED); setVolume(1.0f); return true; }