2014-02-02 3 views
1

Я реализую воспроизведение звука в своем игровом движке с помощью OpenSL ES на Android. Пока я поддерживаю только локаторы данных дескриптора файлов Android (AndroidFD). Проблема в том, что воспроизведение звука не всегда будет работать, если я использую классы-оболочки для OpenSL ES.Почему 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"); 
} 

Sound.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"); 
} 

Game.cpp

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

При запуске приложения, звук выиграл» Всегда играйте. Если я напишу весь код OpenSL ES внутри игры :: initialise(), звук всегда будет воспроизводиться. Я не могу понять, почему тот же код не будет работать внутри классов-оболочек.

Я побежал приложение на Samsung Galaxy S III (GT-I9305), Android 4.2.2, CyanogenMod 10.1.3-i9305

ответ

0

Вы, вероятно, придется держать DataSource, outputMixLocator и dataSink в области видимости, звук воспроизводятся, поскольку они передаются как указатели. Сделайте их переменными-членами, чтобы сохранить их в течение всего жизненного цикла объекта.

 Смежные вопросы

  • Нет связанных вопросов^_^