예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}