【问题标题】:Why OpenSL ES won't play audio every time an application is started为什么每次启动应用程序时 OpenSL ES 都不会播放音频
【发布时间】:2014-02-02 20:55:42
【问题描述】:

我正在使用 Android 上的 OpenSL ES 在我的游戏引擎中实现音频播放。到目前为止,我只支持 Android 文件描述符数据定位器 (AndroidFD)。问题是,如果我使用 OpenSL ES 的包装类,音频播放将不会总是有效。

包装器:

AudioEngine.cpp

AudioEngine::AudioEngine()
    : _engine(NULL),
      _engineInterface(NULL),
      _outputMix(NULL)
{
    createEngine();
    createOutputMix();
}

AudioEngine::~AudioEngine()
{
    (*_outputMix)->Destroy(_outputMix);
    (*_engine)->Destroy(_engine);
}

Sound* AudioEngine::loadSound(const String& filename) const
{
    return NEW Sound(_engineInterface, _outputMix, filename);
}


// Private

void AudioEngine::createEngine()
{
    Uint32 result = slCreateEngine(&_engine, 0u, NULL, 0u, NULL, NULL);

    CHECK_OPENSLES_ERROR(result, "Platform::AudioEngine (OpenSLES)",
        "Failed to create the engine");

    result = (*_engine)->Realize(_engine, SL_BOOLEAN_FALSE);

    CHECK_OPENSLES_ERROR(result, "Platform::AudioEngine (OpenSLES)",
        "Failed to initialise the engine");

    result = (*_engine)->GetInterface(_engine, SL_IID_ENGINE, &_engineInterface);

    CHECK_OPENSLES_ERROR(result, "Platform::AudioEngine (OpenSLES)",
        "Failed to get the engine interface");
}

void AudioEngine::createOutputMix()
{
    Uint32 result = (*_engineInterface)->CreateOutputMix(_engineInterface, &_outputMix, 0u,
        NULL, NULL);

    CHECK_OPENSLES_ERROR(result, "Platform::AudioEngine (OpenSLES)",
        "Failed to create the output mix");

    result = (*_outputMix)->Realize(_outputMix, SL_BOOLEAN_FALSE);

    CHECK_OPENSLES_ERROR(result, "Platform::AudioEngine (OpenSLES)",
        "Failed to initialise the output mix");
}

声音.cpp

// Public

Sound::Sound(SLEngineItf engineInterface, SLObjectItf outputMix, const String& filename)
    : _engineInterface(engineInterface),
      _outputMix(outputMix),
      _player(NULL),
      _playerInterface(NULL)
{
    // Member (SLDataFormat_MIME)
    _dataSourceFormat.formatType = SL_DATAFORMAT_MIME;
    _dataSourceFormat.mimeType = NULL;
    _dataSourceFormat.containerType = SL_CONTAINERTYPE_UNSPECIFIED;

    // Member (SLDataLocator_AndroidFD)
    _dataSourceLocator.locatorType = SL_DATALOCATOR_ANDROIDFD;

    AAssetManager* assetManager = Application::assetManager();
    AAsset* asset = AAssetManager_open(assetManager, filename.data(), AASSET_MODE_UNKNOWN);

    _dataSourceLocator.fd = AAsset_openFileDescriptor(asset,
        reinterpret_cast<off_t*>(&_dataSourceLocator.offset),
        reinterpret_cast<off_t*>(&_dataSourceLocator.length));

    AAsset_close(asset);
    createPlayer();
}

Sound::~Sound()
{
    (*_player)->Destroy(_player);
}

void Sound::play() const
{
    const Uint32 result = (*_playerInterface)->SetPlayState(_playerInterface,
        SL_PLAYSTATE_PLAYING);

    CHECK_OPENSLES_ERROR(result, "Platform::Sound (OpenSLES)",
        "Failed to set the play state"); 
}


// Private

void Sound::createPlayer()
{
    SLDataSource dataSource =
    {
        &_dataSourceLocator,
        &_dataSourceFormat
    };

    SLDataLocator_OutputMix outputMixLocator =
    {
        SL_DATALOCATOR_OUTPUTMIX,
        _outputMix
    };

    SLDataSink dataSink =
    {
        &outputMixLocator,
        NULL
    };

    Uint32 result = (*_engineInterface)->CreateAudioPlayer(_engineInterface, &_player,
        &dataSource, &dataSink, 0u, NULL, NULL);

    CHECK_OPENSLES_ERROR(result, "Platform::Sound (OpenSLES)",
        "Failed to create a player");

    result = (*_player)->Realize(_player, SL_BOOLEAN_FALSE);

    CHECK_OPENSLES_ERROR(result, "Platform::Sound (OpenSLES)",
        "Failed to initialise the player");

    result = (*_player)->GetInterface(_player, SL_IID_PLAY, &_playerInterface);

    CHECK_OPENSLES_ERROR(result, "Platform::SoundInstance (OpenSLES)",
        "Failed to get the player interface");
}

游戏.cpp

Game::initialise()
{
    _audioEngine = NEW AudioEngine();
    _sound = _audioEngine->loadSound("music.ogg");
    _sound->play();
}

应用程序启动时,声音不会一直播放。如果我在 Game::initialise() 中编写以上所有 OpenSL ES 代码,声音将始终播放。我不明白为什么相同的代码在包装类中不起作用。

我在三星 Galaxy S III (GT-I9305)、Android 4.2.2、CyanogenMod 10.1.3-i9305 上运行该应用程序

【问题讨论】:

    标签: android c++ audio opensl


    【解决方案1】:

    您可能必须在播放声音时将 dataSource、outputMixLocator 和 dataSink 保持在范围内,因为它们是作为指针传递的。使它们成为成员变量,以使它们在对象的生命周期内保持活动状态。

    【讨论】:

      猜你喜欢
      • 2012-12-23
      • 2016-10-31
      • 1970-01-01
      • 1970-01-01
      • 2012-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多