Sound_Renderer_SLES::Sound_Renderer_SLES()
    : engineObject(NULL),
    engineEngine(NULL),
    outputMixObject(NULL)
  {
    // create engine
    if(slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL) != SL_RESULT_SUCCESS)
      throw Sound_Init_Failure();

    // realize the engine
    if((*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS)
      throw Sound_Init_Failure();

    // get the engine interface, which is needed in order to create other objects
    if((*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine) != SL_RESULT_SUCCESS)
      throw Sound_Init_Failure();

    // create output mix
    if((*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL) != SL_RESULT_SUCCESS)
      throw Sound_Init_Failure();

    // realize the output mix
    if((*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS)
      throw Sound_Init_Failure();
  }
  Sound::Sound()
    : m_bgm(0),
    m_bgm_source(0)
  {
    // Ensure Core is initialized
    get_Core();

#ifndef DISABLE_AL
    if(!alutInit(0, 0))
      throw Sound_Init_Failure();

    // Check for Vorbis extension functionality; seems to always fail :(
#ifdef _MACOSX
    alIsExtensionPresent(const_cast<ALubyte *>(reinterpret_cast<const ALubyte *>("AL_EXT_vorbis")));
#else
    alIsExtensionPresent("AL_EXT_vorbis");
#endif
    //cerr << "Valid Audio Formats: " << alutGetMIMETypes(ALUT_LOADER_BUFFER) << endl;

    ALfloat listener_position[] = {0.0f, 0.0f, 0.0f};
    ALfloat listener_velocity[] = {0.0f, 0.0f, 0.0f};
    ALfloat listener_forward_and_up[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};

    alListenerfv(AL_POSITION, listener_position);
    alListenerfv(AL_VELOCITY, listener_velocity);
    alListenerfv(AL_ORIENTATION, listener_forward_and_up);
#endif
  }
  Sound_Renderer_AL::Sound_Renderer_AL()
    : m_device(0),
    m_context(0),
    m_bgm(0),
    m_bgm_source(0)
  {
#ifndef _MACOSX
#ifdef _WINDOWS
    m_openal32 = LoadLibrary("OpenAL32.dll");
#else
    m_openal32 = LoadLibrary("libopenal.so");
#endif
    if(!m_openal32) {
      std::cerr << "Loading OpenAL32.dll failed." << std::endl;

      throw Sound_Init_Failure();
    }

    g_alBufferData = (alBufferData_fcn)GetProcAddress(m_openal32, "alBufferData");
    g_alcCloseDevice = (alcCloseDevice_fcn)GetProcAddress(m_openal32, "alcCloseDevice");
    g_alcCreateContext = (alcCreateContext_fcn)GetProcAddress(m_openal32, "alcCreateContext");
    g_alcDestroyContext = (alcDestroyContext_fcn)GetProcAddress(m_openal32, "alcDestroyContext");
    g_alIsExtensionPresent = (alIsExtensionPresent_fcn)GetProcAddress(m_openal32, "alIsExtensionPresent");
    g_alcMakeContextCurrent = (alcMakeContextCurrent_fcn)GetProcAddress(m_openal32, "alcMakeContextCurrent");
    g_alcOpenDevice = (alcOpenDevice_fcn)GetProcAddress(m_openal32, "alcOpenDevice");
    g_alDeleteBuffers = (alDeleteBuffers_fcn)GetProcAddress(m_openal32, "alDeleteBuffers");
    g_alDeleteSources = (alDeleteSources_fcn)GetProcAddress(m_openal32, "alDeleteSources");
    g_alGenBuffers = (alGenBuffers_fcn)GetProcAddress(m_openal32, "alGenBuffers");
    g_alGetError = (alGetError_fcn)GetProcAddress(m_openal32, "alGetError");
    g_alGetListenerf = (alGetListenerf_fcn)GetProcAddress(m_openal32, "alGetListenerf");
    g_alGetListenerfv = (alGetListenerfv_fcn)GetProcAddress(m_openal32, "alGetListenerfv");
    g_alGetSourcef = (alGetSourcef_fcn)GetProcAddress(m_openal32, "alGetSourcef");
    g_alGetSourcefv = (alGetSourcefv_fcn)GetProcAddress(m_openal32, "alGetSourcefv");
    g_alGetSourcei = (alGetSourcei_fcn)GetProcAddress(m_openal32, "alGetSourcei");
    g_alGenSources = (alGenSources_fcn)GetProcAddress(m_openal32, "alGenSources");
    g_alListenerf = (alListenerf_fcn)GetProcAddress(m_openal32, "alListenerf");
    g_alListenerfv = (alListenerfv_fcn)GetProcAddress(m_openal32, "alListenerfv");
    g_alSourcef = (alSourcef_fcn)GetProcAddress(m_openal32, "alSourcef");
    g_alSourcefv = (alSourcefv_fcn)GetProcAddress(m_openal32, "alSourcefv");
    g_alSourcei = (alSourcei_fcn)GetProcAddress(m_openal32, "alSourcei");
    g_alSourcePause = (alSourcePause_fcn)GetProcAddress(m_openal32, "alSourcePause");
    g_alSourcePlay = (alSourcePlay_fcn)GetProcAddress(m_openal32, "alSourcePlay");
    g_alSourceStop = (alSourceStop_fcn)GetProcAddress(m_openal32, "alSourceStop");
    if(!g_alBufferData || !g_alcCloseDevice || !g_alcCreateContext || !g_alcDestroyContext ||
       !g_alIsExtensionPresent || !g_alcMakeContextCurrent || !g_alcOpenDevice || !g_alDeleteBuffers ||
       !g_alDeleteSources || !g_alGenBuffers || !g_alGetError || !g_alGetListenerf ||
       !g_alGetListenerfv || !g_alGetSourcef || !g_alGetSourcefv || !g_alGetSourcei ||
       !g_alGenSources || !g_alListenerf || !g_alListenerfv || !g_alSourcef ||
       !g_alSourcefv || !g_alSourcei || !g_alSourcePause || !g_alSourcePlay ||
       !g_alSourceStop)
    {
      std::cerr << "Loading OpenAL32.dll failed." << std::endl;

      zero_handles();
      FreeLibrary(m_openal32);

      throw Sound_Init_Failure();
    }
    
#ifdef _WINDOWS
    m_libvorbisfile = LoadLibrary("libvorbisfile.dll");
#else
    m_libvorbisfile = LoadLibrary("libvorbisfile.so");
#endif
    if(!m_libvorbisfile) {
      std::cerr << "Loading libvorbisfile.dll failed." << std::endl;

      zero_handles();
      FreeLibrary(m_openal32);

      throw Sound_Init_Failure();
    }

    g_ov_clear = (ov_clear_fcn)GetProcAddress(m_libvorbisfile, "ov_clear");
    g_ov_info = (ov_info_fcn)GetProcAddress(m_libvorbisfile, "ov_info");
    g_ov_fopen = (ov_fopen_fcn)GetProcAddress(m_libvorbisfile, "ov_fopen");
    g_ov_pcm_total = (ov_pcm_total_fcn)GetProcAddress(m_libvorbisfile, "ov_pcm_total");
    g_ov_read = (ov_read_fcn)GetProcAddress(m_libvorbisfile, "ov_read");
    if(!g_ov_clear || !g_ov_info || !g_ov_fopen || !g_ov_pcm_total || !g_ov_read) {
      std::cerr << "Loading libvorbisfile.dll failed." << std::endl;

      zero_handles();
      FreeLibrary(m_libvorbisfile);
      FreeLibrary(m_openal32);

      throw Sound_Init_Failure();
    }
#else
    g_alBufferData = (alBufferData_fcn)::alBufferData;
    g_alcCloseDevice = (alcCloseDevice_fcn)::alcCloseDevice;
    g_alcCreateContext = (alcCreateContext_fcn)::alcCreateContext;
    g_alcDestroyContext = (alcDestroyContext_fcn)::alcDestroyContext;
    g_alIsExtensionPresent = (alIsExtensionPresent_fcn)::alIsExtensionPresent;
    g_alcMakeContextCurrent = (alcMakeContextCurrent_fcn)::alcMakeContextCurrent;
    g_alcOpenDevice = (alcOpenDevice_fcn)::alcOpenDevice;
    g_alDeleteBuffers = (alDeleteBuffers_fcn)::alDeleteBuffers;
    g_alDeleteSources = (alDeleteSources_fcn)::alDeleteSources;
    g_alGenBuffers = (alGenBuffers_fcn)::alGenBuffers;
    g_alGetError = (alGetError_fcn)::alGetError;
    g_alGetListenerf = (alGetListenerf_fcn)::alGetListenerf;
    g_alGetListenerfv = (alGetListenerfv_fcn)::alGetListenerfv;
    g_alGetSourcef = (alGetSourcef_fcn)::alGetSourcef;
    g_alGetSourcefv = (alGetSourcefv_fcn)::alGetSourcefv;
    g_alGetSourcei = (alGetSourcei_fcn)::alGetSourcei;
    g_alGenSources = (alGenSources_fcn)::alGenSources;
    g_alListenerf = (alListenerf_fcn)::alListenerf;
    g_alListenerfv = (alListenerfv_fcn)::alListenerfv;
    g_alSourcef = (alSourcef_fcn)::alSourcef;
    g_alSourcefv = (alSourcefv_fcn)::alSourcefv;
    g_alSourcei = (alSourcei_fcn)::alSourcei;
    g_alSourcePause = (alSourcePause_fcn)::alSourcePause;
    g_alSourcePlay = (alSourcePlay_fcn)::alSourcePlay;
    g_alSourceStop = (alSourceStop_fcn)::alSourceStop;

    g_ov_clear = (ov_clear_fcn)::ov_clear;
    g_ov_info = (ov_info_fcn)::ov_info;
    g_ov_fopen = (ov_fopen_fcn)::ov_fopen;
    g_ov_pcm_total = (ov_pcm_total_fcn)::ov_pcm_total;
    g_ov_read = (ov_read_fcn)::ov_read;
#endif

    m_device = alcOpenDevice()(0);
    if(!m_device) {
      zero_handles();
      FreeLibrary(m_libvorbisfile);
      FreeLibrary(m_openal32);

      throw Sound_Init_Failure();
    }

    m_context = alcCreateContext()(m_device, 0);
    if(!m_context) {
      alcCloseDevice()(m_device);

      zero_handles();
      FreeLibrary(m_libvorbisfile);
      FreeLibrary(m_openal32);

      throw Sound_Init_Failure();
    }

    if(!alcMakeContextCurrent()(m_context)) {
      alcDestroyContext()(m_context);
      alcCloseDevice()(m_device);

      zero_handles();
      FreeLibrary(m_libvorbisfile);
      FreeLibrary(m_openal32);

      throw Sound_Init_Failure();
    }

    // Check for Vorbis extension functionality; seems to always fail :(
    alIsExtensionPresent()("AL_EXT_vorbis");
    //cerr << "Valid Audio Formats: " << alutGetMIMETypes(ALUT_LOADER_BUFFER) << std::endl;

    ALfloat listener_position[] = {0.0f, 0.0f, 0.0f};
    ALfloat listener_velocity[] = {0.0f, 0.0f, 0.0f};
    ALfloat listener_forward_and_up[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};

    alListenerfv()(AL_POSITION, listener_position);
    alListenerfv()(AL_VELOCITY, listener_velocity);
    alListenerfv()(AL_ORIENTATION, listener_forward_and_up);
  }