Beispiel #1
0
static bool
openal_open(void *data, struct audio_format *audio_format,
	    GError **error)
{
	struct openal_data *od = data;

	od->format = openal_audio_format(audio_format);

	if (!od->format) {
		struct audio_format_string s;
		g_set_error(error, openal_output_quark(), 0,
			    "Unsupported audio format: %s",
			    audio_format_to_string(audio_format, &s));
		return false;
	}

	if (!openal_setup_context(od, error)) {
		return false;
	}

	alcMakeContextCurrent(od->context);
	alGenBuffers(NUM_BUFFERS, od->buffers);

	if (alGetError() != AL_NO_ERROR) {
		g_set_error(error, openal_output_quark(), 0,
			    "Failed to generate buffers");
		return false;
	}

	alGenSources(1, &od->source);

	if (alGetError() != AL_NO_ERROR) {
		g_set_error(error, openal_output_quark(), 0,
			    "Failed to generate source");
		alDeleteBuffers(NUM_BUFFERS, od->buffers);
		return false;
	}

	od->filled = 0;
	od->timer = timer_new(audio_format);
	od->frequency = audio_format->sample_rate;

	return true;
}
Beispiel #2
0
Core::Core(Camera* cam, QThread *coreThread) :
    tox(nullptr), camera(cam)
{
    videobuf = new uint8_t[videobufsize];
    videoBusyness=0;

    toxTimer = new QTimer(this);
    toxTimer->setSingleShot(true);
    connect(toxTimer, &QTimer::timeout, this, &Core::process);
    //connect(fileTimer, &QTimer::timeout, this, &Core::fileHeartbeat);
    connect(&Settings::getInstance(), &Settings::dhtServerListChanged, this, &Core::process);
    connect(this, SIGNAL(fileTransferFinished(ToxFile)), this, SLOT(onFileTransferFinished(ToxFile)));

    for (int i=0; i<TOXAV_MAX_CALLS;i++)
    {
        calls[i].sendAudioTimer = new QTimer();
        calls[i].sendVideoTimer = new QTimer();
        calls[i].sendAudioTimer->moveToThread(coreThread);
        calls[i].sendVideoTimer->moveToThread(coreThread);
        connect(calls[i].sendVideoTimer, &QTimer::timeout, [this,i](){sendCallVideo(i);});
    }

    // OpenAL init
    alOutDev = alcOpenDevice(nullptr);
    if (!alOutDev)
    {
        qWarning() << "Core: Cannot open output audio device";
    }
    else
    {
        alContext=alcCreateContext(alOutDev,nullptr);
        if (!alcMakeContextCurrent(alContext))
        {
            qWarning() << "Core: Cannot create output audio context";
            alcCloseDevice(alOutDev);
        }
        else
            alGenSources(1, &alMainSource);
    }
    alInDev = alcCaptureOpenDevice(NULL,av_DefaultSettings.audio_sample_rate, AL_FORMAT_MONO16,
                                   (av_DefaultSettings.audio_frame_duration * av_DefaultSettings.audio_sample_rate * 4) / 1000);
    if (!alInDev)
        qWarning() << "Core: Cannot open input audio device";
}
Beispiel #3
0
    AudioSystem::AudioSystem(LinearAllocator& alloc)
        : m_device(nullptr)
        , m_context(nullptr)
        , m_sounds()
        , m_channelPool()
        , m_channels()
        , m_masterVolume(1.0f)
        , m_muted(false)
    {
        m_device = alcOpenDevice(nullptr);
        AL_CHECK;

        if (m_device == nullptr)
        {
            log::Error("Could not open audio device.");
            return;
        }

        m_context = alcCreateContext(m_device, nullptr);
        AL_CHECK;

        if (m_context == nullptr)
        {
            log::Error("Could not create audio context.");
            return;
        }

        alcMakeContextCurrent(m_context);
        AL_CHECK;

        const size_t_32 allocSize = 1024;
        m_sounds.SetMemory(alloc.Allocate(allocSize, alignof(Sound)), allocSize);
        const size_t_32 channelPoolSize = GetArraySize<Channel>(MAX_CHANNELS);
        m_channelPool.SetMemory(alloc.AllocateArray<Channel>(MAX_CHANNELS), channelPoolSize);

        for (size_t_32 i = 0; i < MAX_CHANNELS; i++)
        {
            m_channels[i] = m_channelPool.Obtain();
        }

        SetMasterVolume(m_masterVolume);
        alListener3f(AL_POSITION, 0.0f, 0.0f, -2.0f);
        AL_CHECK;
    }
Beispiel #4
0
AudioManager::AudioManager():
    m_Initialized( false ),
    m_ThreadContinue( true ),
    m_UpdateMutex(),
    m_Music( &m_UpdateMutex )
{
    m_ALDevice = alcOpenDevice( NULL );
    if( m_ALDevice != NULL )
    {
        m_ALContext = alcCreateContext( m_ALDevice, NULL );
        if( m_ALContext != NULL )
        {
            alcMakeContextCurrent( m_ALContext );

            // listeners
            ALfloat position[ 3 ] = { 0.0f, 0.0f, 0.0f };
            ALfloat velocity[ 3 ] = { 0.0f, 0.0f, 0.0f };
            ALfloat orientation[ 6 ] = { 0.0f, 0.0f, -1.0f,  0.0f, 1.0f, 0.0f };
            alListenerfv( AL_POSITION, position );
            alListenerfv( AL_VELOCITY, velocity );
            alListenerfv( AL_ORIENTATION, orientation );
            m_Initialized = true;

            m_Buffer       = new char[ m_ChannelBufferSize ];
            m_UpdateThread = new boost::thread( boost::ref( *this ) );

            LOG_TRIVIAL( "AudioManager initialised." );
        }
        else
        {
            LOG_ERROR( "AudioManager failed to initialised. Could not create context for sound device." );
        }
    }
    else
    {
        LOG_ERROR( "AudioManager failed to initialised. There's no default sound device." );
    }



    // Load musics
    XmlMusicsFile musics( "./data/musics.xml" );
    musics.LoadMusics();
}
Beispiel #5
0
int main( int argc, char* argv[] ) {
	ALCdevice *dev;
	time_t start;
	time_t shouldend;

	start = time(NULL);
	shouldend = time(NULL);

	dev = alcOpenDevice( NULL );
	if( dev == NULL ) {
		return 1;
	}

	/* Initialize ALUT. */
	context_id = alcCreateContext( dev, NULL);
	if(context_id == NULL) {
		alcCloseDevice( dev );
		return 1;
	}

	alcMakeContextCurrent( context_id );

	fixup_function_pointers();

	if(argc == 1) {
		init(WAVEFILE);
	} else {
		init(argv[1]);
	}

	alSourcePlay(rightSid);

	while(shouldend - start < 20) {
		shouldend = time(NULL);

		iterate();
	}

	cleanup();

	alcCloseDevice( dev );

	return 0;
}
Beispiel #6
0
ALAudio::ALAudio(char const *const dev_name) {
	dev_.reset(alcOpenDevice(dev_name), &alcCloseDevice);
	BOOST_ASSERT(dev_);

	ctx_.reset(alcCreateContext(dev_.get(), NULL), &alcDestroyContext);
	BOOST_ASSERT(ctx_);

	alcMakeContextCurrent(ctx_.get());

	SET_CONTEXT(ctx_);

	bgm_src_ = create_source(true);
	bgs_src_ = create_source(true);
	me_src_ = create_source(false);

        if (not getenv("DEFAULT_SOUNDFONT")) {
          Output::Error("Default sound font not found.");
        }
}
CSound::~CSound()
{
	if (!sources.empty())
	{
		soundThread->interrupt();
		soundThread->join();
		delete soundThread;
		soundThread = 0;

		sources.clear(); // delete all sources
		sounds.clear();
		SoundBuffer::Deinitialise();
		ALCcontext *curcontext = alcGetCurrentContext();
		ALCdevice *curdevice = alcGetContextsDevice(curcontext);
		alcMakeContextCurrent(NULL);
		alcDestroyContext(curcontext);
		alcCloseDevice(curdevice);
	}
}
Beispiel #8
0
static void
_context_dealloc (PyContext *self)
{
    if (self->context)
    {
        ALCcontext *ctxt = alcGetCurrentContext ();
        
        /* Make sure, the context is not current. */
        if (ctxt == self->context)
            alcMakeContextCurrent (NULL);
        alcDestroyContext (self->context);
    }
    Py_XDECREF (self->device);
    Py_XDECREF (self->listener);
    self->listener = NULL;
    self->device = NULL;
    self->context = NULL;
    ((PyObject*)self)->ob_type->tp_free ((PyObject *) self);
}
Beispiel #9
0
bool InitOpenAL(void) {
    ALCdevice *Device = alcOpenDevice(NULL);
    if(!Device) {
        printf("Error while opening the device\n");
        exit(1);
    }

    ALCcontext *Context = alcCreateContext(Device, NULL);
    if(!Context) {
        printf("Error while creating context\n");
        exit(1);
    }

    if(!alcMakeContextCurrent(Context)) {
        printf("Error while activating context\n");
        exit(1);
    }
    return 0;
}
Beispiel #10
0
    void AudioWorld::continueSounds()
    {
#ifdef RE_USE_SOUND
        if (!m_Context)
            return;

        alcMakeContextCurrent(m_Context);

        for (Source& s : m_Sources)
        {
            ALint state;
            alGetSourcei(s.m_Handle, AL_SOURCE_STATE, &state);
            if (state == AL_PAUSED)
            {
                alSourcePlay(s.m_Handle);
            }
        }
#endif
    }
Beispiel #11
0
void AudioController::resume()
{
#ifndef __ANDROID__    
    alcMakeContextCurrent(_alcContext);
#endif
    std::list<AudioSource*>::iterator itr = _playingSources.begin();

    // For each source that is playing, resume it.
    AudioSource* source = NULL;
    while (itr != _playingSources.end())
    {
        source = *itr;
        if (source->getState() == AudioSource::PAUSED)
        {
            source->play();
        }
        itr++;
    }
}
Beispiel #12
0
AudioManagerImpl::~AudioManagerImpl()
{
	stopMusic();

	MidiDevice::shutdown();

	ALCcontext *context = alcGetCurrentContext();
	if (!context) return;


	for (ALuint source : mFreeSources)
		alDeleteSources(1, &source);
	mFreeSources.clear();

	ALCdevice *device = alcGetContextsDevice(context);
	alcMakeContextCurrent(nullptr);
	alcDestroyContext(context);
	alcCloseDevice(device);
}
Beispiel #13
0
void
init_al(void)
{
  ALCdevice *dev = alcOpenDevice(NULL);
  ALenum err = alcGetError(dev);
  if (err != ALC_NO_ERROR) {
    log_error("could not get the default al device");
  }

  ALCcontext *ctxt = alcCreateContext(dev, NULL);
  err = alcGetError(dev);
  if (err != ALC_NO_ERROR) {
    log_error("could not create al context");
  }

  if (alcMakeContextCurrent(ctxt) == ALC_FALSE) {
    log_error("could not make the al context current");
  }
}
Beispiel #14
0
DDAudio::DDAudio()
{
    gDevice = alcOpenDevice(NULL);
    gContext = alcCreateContext(gDevice, NULL);
    alcMakeContextCurrent(gContext);

    int error = alGetError();
    if(error != AL_NO_ERROR)
    {
        dsprintf("OpenAL setup error : %d", error);
        return;
    }

    // // Defaults for 2d sound
    // alListener3f(AL_POSITION, 0, 0, 0);
    // alListener3f(AL_VELOCITY, 0, 0, 0);
    // alListener3f(AL_ORIENTATION, 0, 0, -1);


    //
    // Reserve sound channels.
    //

    gChannels.clear();

    while(gChannels.size() < MAX_SOUND_CHANNELS)
    {
        unsigned int src;
        alGenSources(1, &src);
        error = alGetError();
        if(error == AL_NO_ERROR)
        {
            gChannels.push_back(src);
        }
        else
        {
            dsprintf("OpenAL sound channel error : %d\n", error);
            break;
        }
    }

    dsprintf("%d sound channels found.\n", (int)gChannels.size());
}
Beispiel #15
0
//
// AyuanX: Spec says OpenAL1.1 is thread safe already
//
bool OpenALStream::Start()
{
	ALDeviceList pDeviceList;
	if (pDeviceList.GetNumDevices())
	{
		char *defDevName = pDeviceList.GetDeviceName(pDeviceList.GetDefaultDevice());

		WARN_LOG(AUDIO, "Found OpenAL device %s", defDevName);

		ALCdevice *pDevice = alcOpenDevice(defDevName);
		if (pDevice)
		{
			ALCcontext *pContext = alcCreateContext(pDevice, nullptr);
			if (pContext)
			{
				// Used to determine an appropriate period size (2x period = total buffer size)
				//ALCint refresh;
				//alcGetIntegerv(pDevice, ALC_REFRESH, 1, &refresh);
				//period_size_in_millisec = 1000 / refresh;

				alcMakeContextCurrent(pContext);
				return SoundStream::Start();
			}
			else
			{
				alcCloseDevice(pDevice);
				PanicAlertT("OpenAL: can't create context for device %s", defDevName);
			}
		}
		else
		{
			PanicAlertT("OpenAL: can't open device %s", defDevName);
		}
	}
	else
	{
		PanicAlertT("OpenAL: can't find sound devices");
	}

	// Initialize DPL2 parameters

	return false;
}
Beispiel #16
0
static bool initOpenAL() {
  // device
  alDevice = alcOpenDevice(nullptr);
  if (!alDevice) {
    alError = "It was not possible to open audio device";
    return false;
  }
  
  // context
  alContext = alcCreateContext(alDevice, nullptr);
  if (!alContext) {
    alError = "It was not possible to create audio context";
    return false;
  }
  
  alcMakeContextCurrent(alContext);
  
  return true;
}
Beispiel #17
0
void OpenALStream::Stop()
{
	SoundStream::Stop();

	alSourceStop(uiSource);
	alSourcei(uiSource, AL_BUFFER, 0);

	// Clean up buffers and sources
	alDeleteSources(1, &uiSource);
	uiSource = 0;
	alDeleteBuffers(numBuffers, uiBuffers);

	ALCcontext *pContext = alcGetCurrentContext();
	ALCdevice *pDevice = alcGetContextsDevice(pContext);

	alcMakeContextCurrent(nullptr);
	alcDestroyContext(pContext);
	alcCloseDevice(pDevice);
}
Beispiel #18
0
void SoundManager::init()
{
    m_device = alcOpenDevice(NULL);
    if(!m_device) {
        g_logger.error("unable to open audio device");
        return;
    }

    m_context = alcCreateContext(m_device, NULL);
    if(!m_context) {
        g_logger.error(stdext::format("unable to create audio context: %s", alcGetString(m_device, alcGetError(m_device))));
        return;
    }

    if(alcMakeContextCurrent(m_context) != ALC_TRUE) {
        g_logger.error(stdext::format("unable to make context current: %s", alcGetString(m_device, alcGetError(m_device))));
        return;
    }
}
Beispiel #19
0
// close audio device
static void uninit(struct ao *ao, bool immed)
{
    ALCcontext *ctx = alcGetCurrentContext();
    ALCdevice *dev = alcGetContextsDevice(ctx);
    free(tmpbuf);
    if (!immed) {
        ALint state;
        alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
        while (state == AL_PLAYING) {
            mp_sleep_us(10000);
            alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
        }
    }
    reset(ao);
    alcMakeContextCurrent(NULL);
    alcDestroyContext(ctx);
    alcCloseDevice(dev);
    ao_data = NULL;
}
Beispiel #20
0
void sound_ShutdownLibrary(void)
{
    AUDIO_STREAM *stream;
    SAMPLE_LIST *aSample = active_samples, * tmpSample = NULL;

    if (!openal_initialized)
    {
        return;
    }
    debug(LOG_SOUND, "starting shutdown");

    // Stop all streams, sound_UpdateStreams() will deallocate all stopped streams
    for (stream = active_streams; stream != NULL; stream = stream->next)
    {
        sound_StopStream(stream);
    }
    sound_UpdateStreams();

    alcGetError(device);	// clear error codes

    /* On Linux since this caused some versions of OpenAL to hang on exit. - Per */
    debug(LOG_SOUND, "make default context NULL");
    alcMakeContextCurrent(NULL);
    sound_GetContextError(device);

    debug(LOG_SOUND, "destroy previous context");
    alcDestroyContext(context); // this gives a long delay on some impl.
    sound_GetContextError(device);

    debug(LOG_SOUND, "close device");
    if (alcCloseDevice(device) == ALC_FALSE)
    {
        debug(LOG_SOUND, "OpenAl could not close the audio device.");
    }

    while (aSample)
    {
        tmpSample = aSample->next;
        free(aSample);
        aSample = tmpSample;
    }
    active_samples = NULL;
}
Beispiel #21
0
void say_audio_context_ensure() {
  if (!say_audio_device) {
    say_audio_device = alcOpenDevice(NULL);
    if (!say_audio_device) {
      say_error_set("could not open audio device");
      return;
    }
  }

  if (!say_audio_context) {
    say_audio_context = alcCreateContext(say_audio_device, NULL);
    if (!say_audio_context) {
      say_error_set("could not create audio context");
      return;
    }

    alcMakeContextCurrent(say_audio_context);
  }
}
Beispiel #22
0
static int open_openal(out123_handle *ao)
{
	mpg123_openal_t* al = (mpg123_openal_t*)ao->userptr;

	al->device = alcOpenDevice(NULL);
	al->context = alcCreateContext(al->device, NULL);
	alcMakeContextCurrent(al->context);
	alGenSources(1, &al->source);

	al->rate = ao->rate;
	if(ao->format == MPG123_ENC_SIGNED_16 && ao->channels == 2) al->format = AL_FORMAT_STEREO16;
	else if(ao->format == MPG123_ENC_SIGNED_16 && ao->channels == 1) al->format = AL_FORMAT_MONO16;
	else if(ao->format == MPG123_ENC_UNSIGNED_8 && ao->channels == 2) al->format = AL_FORMAT_STEREO8;
	else if(ao->format == MPG123_ENC_UNSIGNED_8 && ao->channels == 1) al->format = AL_FORMAT_MONO8;
	else if(ao->format == MPG123_ENC_FLOAT_32 && ao->channels == 2) al->format = AL_FORMAT_STEREO_FLOAT32;
	else if(ao->format == MPG123_ENC_FLOAT_32 && ao->channels == 1) al->format = AL_FORMAT_MONO_FLOAT32;
	
	return 0;
}
Beispiel #23
0
ALCboolean CDECL wine_alcMakeContextCurrent(ALCcontext *context)
{
    EnterCriticalSection(&openal_cs);
    if(alcMakeContextCurrent(context) == ALC_FALSE)
    {
        WARN("Failed to make context %p current\n", context);
        LeaveCriticalSection(&openal_cs);
        return ALC_FALSE;
    }

    if(context && !loaded_procs)
    {
        loaded_procs = AL_TRUE;
        LoadProcs();
    }
    LeaveCriticalSection(&openal_cs);

    return ALC_TRUE;
}
Beispiel #24
0
static void al_free(void *data)
{
   al_t *al = (al_t*)data;
   if (al)
   {
      alSourceStop(al->source);
      alDeleteSources(1, &al->source);
      if (al->buffers)
      {
         alDeleteBuffers(al->num_buffers, al->buffers);
         free(al->buffers);
         free(al->res_buf);
      }
   }
   alcMakeContextCurrent(NULL);
   alcDestroyContext(al->ctx);
   alcCloseDevice(al->handle);
   free(al);
}
Beispiel #25
0
static int Initialize(void *hnd)
{
  ALCdevice *dev;
  ALCcontext *ctxt;
  ALCint attrs[3];
  // TODO: Check for failures (generally, not just in this file).
  dev = alcOpenDevice(NULL);
  attrs[0] = ALC_FREQUENCY;
  attrs[1] = RLX.Audio.SR_to_Khz[RLX.Audio.SamplingRate];
  attrs[2] = 0;
  ctxt = alcCreateContext(dev, (ALCint *)&attrs);
  alcMakeContextCurrent(ctxt);
  alDistanceModel(AL_INVERSE_DISTANCE);
  alDopplerFactor(0.f); // No doppler
  alDopplerVelocity(0.f); // No velocity

  RLX.Audio.Config|=RLXAUDIO_Use3D;
  return 0;
}
Beispiel #26
0
void sound_cleanup() {

    ALCcontext* pCurContext;
    ALCdevice* pCurDevice;

    // Get the current context.
    pCurContext = alcGetCurrentContext();

    // Get the device used by that context.
    pCurDevice = alcGetContextsDevice(pCurContext);

    // Reset the current context to NULL.
    alcMakeContextCurrent(NULL);

    // Release the context and the device.
    alcDestroyContext(pCurContext);
    alcCloseDevice(pCurDevice);

}
void clAudioSubsystem_OpenAL::Start()
{
	m_AudioThread = std::make_shared<std::thread>(
		[this]()
		{
			m_Device = alcOpenDevice( nullptr );
			m_Context = alcCreateContext( m_Device, nullptr );
			alcMakeContextCurrent( m_Context );

			if ( IsVerbose() ) DebugPrintVersion();

			m_IsInitialized = true;

			while ( !m_IsPendingExit )
			{
				std::this_thread::sleep_for(std::chrono::milliseconds(10));

				{
					auto sources = this->GetLockedSources();

					for (auto i : sources)
					{
						i->UpdateBuffers();
					}
				}
			}

			// A dirty workaround for a possible bug in OpenAL Soft
			// http://openal.org/pipermail/openal/2015-January/000312.html
#if !defined(_WIN32)
			alcDestroyContext( m_Context );
			alcCloseDevice( m_Device );
#endif

			m_IsInitialized = false;

		}
	);

	// wait
	while ( !m_IsInitialized );
}
Beispiel #28
0
	Audio::Audio()
		: finish(false)
	{
		// Passing zero for default device.
		device = alcOpenDevice(0);

		if(device == 0)
			throw love::Exception("Could not open device.");

		context = alcCreateContext(device, 0);

		if(context == 0)
			throw love::Exception("Could not create context.");

		alcMakeContextCurrent(context);

		if(alcGetError(device) != ALC_NO_ERROR)
			throw love::Exception("Could not make context current.");
		
		/*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
		const ALCchar * devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
		while (*devices) {
			std::string device(devices);
			devices += device.size() + 1;
			if (device.find("Mic") != std::string::npos || device.find("mic") != std::string::npos) {
				captureName = device;
			}
		}
		
		capture = alcCaptureOpenDevice(captureName.c_str(), 8000, AL_FORMAT_MONO16, 262144); // about 32 seconds
		
		if (!capture) {
			// We're not going to prevent LOVE from running without a microphone, but we should warn, at least
			std::cerr << "Warning, couldn't open capture device! No audio input!" << std::endl;
		}*/

		// pool must be allocated after AL context.
		pool = new Pool();

		thread = new pthread_t;
		pthread_create(thread, NULL, (void* (*)(void*))Audio::run, (void*)this);
	}
Beispiel #29
0
ALboolean ALFWInitOpenAL()
{
	ALDeviceList *pDeviceList = NULL;
	ALCcontext *pContext = NULL;
	ALCdevice *pDevice = NULL;
	ALint i;
	ALboolean bReturn = AL_FALSE;

	pDeviceList = new ALDeviceList();
	if ((pDeviceList) && (pDeviceList->GetNumDevices()))
	{
		ALFWprintf("\nSelect OpenAL Device:\n");
		for (i = 0; i < pDeviceList->GetNumDevices(); i++) 
			ALFWprintf("%d. %s%s\n", i + 1, pDeviceList->GetDeviceName(i), i == pDeviceList->GetDefaultDevice() ? "(DEFAULT)" : "");
	
		do {
//			ALchar ch = _getch();
			ALchar ch = '1' ;
			i = atoi(&ch);
		} while ((i < 1) || (i > pDeviceList->GetNumDevices()));

		pDevice = alcOpenDevice(pDeviceList->GetDeviceName(i - 1));
		if (pDevice)
		{
			pContext = alcCreateContext(pDevice, NULL);
			if (pContext)
			{
				ALFWprintf("\nOpened %s Device\n", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
				alcMakeContextCurrent(pContext);
				bReturn = AL_TRUE;
			}
			else
			{
				alcCloseDevice(pDevice);
			}
		}

		delete pDeviceList;
	}

	return bReturn;
}
Beispiel #30
0
OpenALDevice::OpenALDevice(DeviceSpecs specs, int buffersize, std::string name) :
	m_playing(false), m_buffersize(buffersize)
{
	// cannot determine how many channels or which format OpenAL uses, but
	// it at least is able to play 16 bit stereo audio
	specs.format = FORMAT_S16;

	if(name.empty())
		m_device = alcOpenDevice(nullptr);
	else
		m_device = alcOpenDevice(name.c_str());

	if(!m_device)
		AUD_THROW(DeviceException, "The audio device couldn't be opened with OpenAL.");

	// at least try to set the frequency
	ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 };
	ALCint* attributes = attribs;
	if(specs.rate == RATE_INVALID)
		attributes = nullptr;

	m_context = alcCreateContext(m_device, attributes);
	alcMakeContextCurrent(m_context);

	alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);

	// check for specific formats and channel counts to be played back
	if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
		specs.format = FORMAT_FLOAT32;

	m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;

	if((!m_useMC && specs.channels > CHANNELS_STEREO) ||
			specs.channels == CHANNELS_STEREO_LFE ||
			specs.channels == CHANNELS_SURROUND5)
		specs.channels = CHANNELS_STEREO;

	alGetError();
	alcGetError(m_device);

	m_specs = specs;
}