mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Initial Mercurial commit.
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Audio.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
Audio::Audio()
|
||||
{
|
||||
// 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.");
|
||||
|
||||
// pool must be allocated after AL context.
|
||||
pool = new Pool();
|
||||
|
||||
thread = SDL_CreateThread(Audio::run, (void*)this);
|
||||
}
|
||||
|
||||
Audio::~Audio()
|
||||
{
|
||||
SDL_KillThread(thread);
|
||||
|
||||
delete pool;
|
||||
|
||||
alcMakeContextCurrent(0);
|
||||
alcDestroyContext(context);
|
||||
alcCloseDevice(device);
|
||||
}
|
||||
|
||||
int Audio::run(void * d)
|
||||
{
|
||||
Audio * instance = (Audio*)d;
|
||||
|
||||
while(true)
|
||||
{
|
||||
instance->pool->update();
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char * Audio::getName() const
|
||||
{
|
||||
return "love.audio.openal";
|
||||
}
|
||||
|
||||
love::audio::Sound * Audio::newSound(love::sound::SoundData * data)
|
||||
{
|
||||
return new Sound(pool, data);
|
||||
}
|
||||
|
||||
love::audio::Music * Audio::newMusic(love::sound::Decoder * decoder)
|
||||
{
|
||||
return new Music(pool, decoder);
|
||||
}
|
||||
|
||||
love::audio::Source * Audio::newSource()
|
||||
{
|
||||
return new Source(pool);
|
||||
}
|
||||
|
||||
int Audio::getNumSources() const
|
||||
{
|
||||
return pool->getNumSources();
|
||||
}
|
||||
|
||||
int Audio::getMaxSources() const
|
||||
{
|
||||
return pool->getMaxSources();
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Source * source)
|
||||
{
|
||||
source->play();
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Sound * sound)
|
||||
{
|
||||
Source * source = new Source(pool, sound);
|
||||
play(source);
|
||||
source->release();
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Music * music)
|
||||
{
|
||||
Source * source = new Source(pool, music->clone());
|
||||
play(source);
|
||||
source->release();
|
||||
}
|
||||
|
||||
void Audio::stop(love::audio::Source * source)
|
||||
{
|
||||
source->stop();
|
||||
}
|
||||
|
||||
void Audio::stop()
|
||||
{
|
||||
pool->stop();
|
||||
}
|
||||
|
||||
void Audio::pause(love::audio::Source * source)
|
||||
{
|
||||
source->pause();
|
||||
}
|
||||
|
||||
void Audio::pause()
|
||||
{
|
||||
pool->pause();
|
||||
}
|
||||
|
||||
void Audio::resume(love::audio::Source * source)
|
||||
{
|
||||
source->resume();
|
||||
}
|
||||
|
||||
void Audio::resume()
|
||||
{
|
||||
pool->resume();
|
||||
}
|
||||
|
||||
void Audio::rewind(love::audio::Source * source)
|
||||
{
|
||||
source->rewind();
|
||||
}
|
||||
|
||||
void Audio::rewind()
|
||||
{
|
||||
pool->rewind();
|
||||
}
|
||||
|
||||
void Audio::setVolume(float volume)
|
||||
{
|
||||
alListenerf(AL_GAIN, volume);
|
||||
}
|
||||
|
||||
float Audio::getVolume() const
|
||||
{
|
||||
ALfloat volume;
|
||||
alGetListenerf(AL_GAIN, &volume);
|
||||
return volume;
|
||||
}
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_OPENAL_AUDIO_H
|
||||
#define LOVE_AUDIO_OPENAL_AUDIO_H
|
||||
|
||||
// STD
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// SDL
|
||||
#include <SDL.h>
|
||||
|
||||
// OpenAL
|
||||
#include <AL/alc.h>
|
||||
#include <AL/al.h>
|
||||
|
||||
// LOVE
|
||||
#include <audio/Audio.h>
|
||||
#include <common/config.h>
|
||||
#include <common/constants.h>
|
||||
#include <sound/SoundData.h>
|
||||
|
||||
#include "Sound.h"
|
||||
#include "Music.h"
|
||||
#include "Source.h"
|
||||
#include "Pool.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
class Audio : public love::audio::Audio
|
||||
{
|
||||
private:
|
||||
|
||||
// The OpenAL device.
|
||||
ALCdevice * device;
|
||||
|
||||
// The OpenAL context.
|
||||
ALCcontext * context;
|
||||
|
||||
SDL_Thread * thread;
|
||||
|
||||
// The Pool.
|
||||
Pool * pool;
|
||||
|
||||
static int run(void * unused);
|
||||
|
||||
public:
|
||||
|
||||
Audio();
|
||||
~Audio();
|
||||
|
||||
// Implements Module.
|
||||
const char * getName() const;
|
||||
|
||||
// Implements Audio.
|
||||
love::audio::Sound * newSound(love::sound::SoundData * data);
|
||||
love::audio::Music * newMusic(love::sound::Decoder * decoder);
|
||||
love::audio::Source * newSource();
|
||||
int getNumSources() const;
|
||||
int getMaxSources() const;
|
||||
void play(love::audio::Source * source);
|
||||
void play(love::audio::Sound * sound);
|
||||
void play(love::audio::Music * music);
|
||||
void play();
|
||||
void stop(love::audio::Source * source);
|
||||
void stop();
|
||||
void pause(love::audio::Source * source);
|
||||
void pause();
|
||||
void resume(love::audio::Source * source);
|
||||
void resume();
|
||||
void rewind(love::audio::Source * source);
|
||||
void rewind();
|
||||
void setVolume(float volume);
|
||||
float getVolume() const;
|
||||
|
||||
}; // Audio
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_OPENAL_AUDIO_H
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Music.h"
|
||||
|
||||
// STD
|
||||
#include <iostream>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
Music::Music(Pool * pool, love::sound::Decoder * decoder)
|
||||
: pool(pool), decoder(decoder), source(0)
|
||||
{
|
||||
decoder->retain();
|
||||
alGenBuffers(NUM_BUFFERS, buffers);
|
||||
}
|
||||
|
||||
Music::~Music()
|
||||
{
|
||||
decoder->release();
|
||||
alDeleteBuffers(NUM_BUFFERS, buffers);
|
||||
}
|
||||
|
||||
love::audio::Music * Music::clone()
|
||||
{
|
||||
return new Music(pool, decoder->clone());
|
||||
}
|
||||
|
||||
void Music::play(love::audio::Source * s)
|
||||
{
|
||||
source = pool->find(s);
|
||||
|
||||
if(source)
|
||||
{
|
||||
for(int i = 0; i < NUM_BUFFERS; i++)
|
||||
{
|
||||
if(!stream(buffers[i]))
|
||||
{
|
||||
std::cout << "Could not stream music." << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
alSourceQueueBuffers(source, NUM_BUFFERS, buffers);
|
||||
}
|
||||
}
|
||||
|
||||
void Music::update(love::audio::Source * s)
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
// Number of processed buffers.
|
||||
ALint processed;
|
||||
|
||||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
||||
|
||||
while(processed--)
|
||||
{
|
||||
ALuint buffer;
|
||||
|
||||
// Get a free buffer.
|
||||
alSourceUnqueueBuffers(source, 1, &buffer);
|
||||
|
||||
if(stream(buffer))
|
||||
alSourceQueueBuffers(source, 1, &buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Music::stop(love::audio::Source * s)
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
ALuint bufs[NUM_BUFFERS];
|
||||
alSourceStop(source);
|
||||
alSourceUnqueueBuffers(source, NUM_BUFFERS, bufs);
|
||||
source = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Music::rewind(love::audio::Source * s)
|
||||
{
|
||||
// Stop source, unqueue buffers.
|
||||
stop(s);
|
||||
|
||||
// Rewind data pointer.
|
||||
decoder->rewind();
|
||||
|
||||
// Requeue buffers.
|
||||
play(s);
|
||||
}
|
||||
|
||||
bool Music::stream(ALuint buffer)
|
||||
{
|
||||
// Get more sound data.
|
||||
int decoded = decoder->decode();
|
||||
|
||||
int fmt = pool->getFormat(decoder->getChannels(), decoder->getBits());
|
||||
|
||||
if(fmt == 0)
|
||||
return false;
|
||||
|
||||
if(decoded > 0)
|
||||
{
|
||||
alBufferData(buffer, fmt, decoder->getBuffer(),
|
||||
decoder->getSize(), decoder->getSampleRate());
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_OPENAL_MUSIC_H
|
||||
#define LOVE_AUDIO_OPENAL_MUSIC_H
|
||||
|
||||
// LOVE
|
||||
#include <audio/Music.h>
|
||||
#include <sound/Decoder.h>
|
||||
#include "Pool.h"
|
||||
|
||||
// OpenAL
|
||||
#include <AL/alc.h>
|
||||
#include <AL/al.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
class Audio;
|
||||
|
||||
class Music : public love::audio::Music
|
||||
{
|
||||
private:
|
||||
static const unsigned int NUM_BUFFERS = 32;
|
||||
ALuint buffers[NUM_BUFFERS];
|
||||
Pool * pool;
|
||||
love::sound::Decoder * decoder;
|
||||
ALuint source;
|
||||
public:
|
||||
Music(Pool * pool, love::sound::Decoder * decoder);
|
||||
virtual ~Music();
|
||||
|
||||
|
||||
// Implements Audible.
|
||||
void play(love::audio::Source * source);
|
||||
void update(love::audio::Source * source);
|
||||
void stop(love::audio::Source * source);
|
||||
void rewind(love::audio::Source * source);
|
||||
|
||||
// Implements Music.
|
||||
love::audio::Music * clone();
|
||||
|
||||
private:
|
||||
bool stream(ALuint buffer);
|
||||
}; // Sound
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_OPENAL_MUSIC_H
|
||||
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Pool.h"
|
||||
|
||||
#define MUTEX_ASSERT(fn, sval) \
|
||||
if(fn != sval) \
|
||||
{ \
|
||||
std::cout << "Mutex lock/unlock failure. " << SDL_GetError() << std::endl; \
|
||||
exit(-1); \
|
||||
} \
|
||||
|
||||
#define LOCK(m) MUTEX_ASSERT(SDL_mutexP(m), 0)
|
||||
#define UNLOCK(m) MUTEX_ASSERT(SDL_mutexV(m), 0);
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
Pool::Pool()
|
||||
{
|
||||
// Generate sources.
|
||||
alGenSources(NUM_SOURCES, sources);
|
||||
|
||||
// Create the mutex.
|
||||
mutex = SDL_CreateMutex();
|
||||
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
throw love::Exception("Could not generate sources.");
|
||||
|
||||
// Make all sources available initially.
|
||||
for(int i = 0; i < NUM_SOURCES; i++)
|
||||
available.push(sources[i]);
|
||||
}
|
||||
|
||||
Pool::~Pool()
|
||||
{
|
||||
SDL_DestroyMutex(mutex);
|
||||
|
||||
std::map<love::audio::Source *, ALuint>::iterator i = playing.begin();
|
||||
|
||||
while(i != playing.end())
|
||||
{
|
||||
i->first->stop();
|
||||
i->first->release();
|
||||
i++;
|
||||
}
|
||||
|
||||
// Free all sources.
|
||||
alDeleteSources(NUM_SOURCES, sources);
|
||||
}
|
||||
|
||||
ALenum Pool::getFormat(int channels, int bits) const
|
||||
{
|
||||
if(channels == 1 && bits == 8)
|
||||
return AL_FORMAT_MONO8;
|
||||
else if(channels == 1 && bits == 16)
|
||||
return AL_FORMAT_MONO16;
|
||||
else if(channels == 2 && bits == 8)
|
||||
return AL_FORMAT_STEREO8;
|
||||
else if(channels == 2 && bits == 16)
|
||||
return AL_FORMAT_STEREO16;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Pool::isAvailable() const
|
||||
{
|
||||
bool has = false;
|
||||
LOCK(mutex);
|
||||
has = !available.empty();
|
||||
UNLOCK(mutex);
|
||||
return has;
|
||||
}
|
||||
|
||||
ALuint Pool::claim(love::audio::Source * source)
|
||||
{
|
||||
ALuint s = 0;
|
||||
LOCK(mutex);
|
||||
if(!available.empty())
|
||||
{
|
||||
// Get the first available source.
|
||||
s = available.front();
|
||||
|
||||
// Remove it.
|
||||
available.pop();
|
||||
|
||||
// Insert into map of playing sources.
|
||||
playing.insert(std::pair<love::audio::Source *, ALuint>(source, s));
|
||||
|
||||
// Retain the source.
|
||||
source->retain();
|
||||
}
|
||||
UNLOCK(mutex);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void Pool::release(love::audio::Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
ALuint s = findi(source);
|
||||
|
||||
if(s != 0)
|
||||
{
|
||||
available.push(s);
|
||||
playing.erase(source);
|
||||
source->release();
|
||||
}
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
ALuint Pool::find(const love::audio::Source * source) const
|
||||
{
|
||||
ALuint r = 0;
|
||||
LOCK(mutex);
|
||||
r = findi(source);
|
||||
UNLOCK(mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool Pool::isPlaying(love::audio::Source * s)
|
||||
{
|
||||
bool p = false;
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
{
|
||||
if(i->first == s)
|
||||
p = true;
|
||||
}
|
||||
UNLOCK(mutex);
|
||||
return p;
|
||||
}
|
||||
|
||||
void Pool::update()
|
||||
{
|
||||
LOCK(mutex);
|
||||
|
||||
std::map<love::audio::Source *, ALuint>::iterator i = playing.begin();
|
||||
|
||||
while(i != playing.end())
|
||||
{
|
||||
if(i->first->isFinished())
|
||||
{
|
||||
// Stop the source.
|
||||
i->first->stop();
|
||||
|
||||
// Make it available.
|
||||
available.push(i->second);
|
||||
|
||||
// Remove if from the playing list.
|
||||
playing.erase(i++);
|
||||
}
|
||||
else
|
||||
{
|
||||
i->first->update();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
int Pool::getNumSources() const
|
||||
{
|
||||
return playing.size();
|
||||
}
|
||||
|
||||
int Pool::getMaxSources() const
|
||||
{
|
||||
return NUM_SOURCES;
|
||||
}
|
||||
|
||||
void Pool::stop()
|
||||
{
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->stop();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::pause()
|
||||
{
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->pause();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::resume()
|
||||
{
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->resume();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::rewind()
|
||||
{
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->rewind();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
ALuint Pool::findi(const love::audio::Source * source) const
|
||||
{
|
||||
std::map<love::audio::Source *, ALuint>::const_iterator i = playing.find((love::audio::Source *)source);
|
||||
|
||||
if(i != playing.end())
|
||||
return i->second;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_OPENAL_POOL_H
|
||||
#define LOVE_AUDIO_OPENAL_POOL_H
|
||||
|
||||
// STD
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// SDL
|
||||
#include <SDL.h>
|
||||
|
||||
// OpenAL
|
||||
#include <AL/alc.h>
|
||||
#include <AL/al.h>
|
||||
|
||||
// LOVE
|
||||
#include <audio/Source.h>
|
||||
#include <common/Exception.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
class Pool
|
||||
{
|
||||
private:
|
||||
|
||||
// Number of OpenAL sources.
|
||||
static const int NUM_SOURCES = 16;
|
||||
|
||||
// OpenAL sources
|
||||
ALuint sources[NUM_SOURCES];
|
||||
|
||||
// A queue of available sources.
|
||||
std::queue<ALuint> available;
|
||||
|
||||
// A map of playing sources.
|
||||
std::map<love::audio::Source *, ALuint> playing;
|
||||
|
||||
// Only one thread can access this object at the same time. This mutex will
|
||||
// make sure of that.
|
||||
SDL_mutex * mutex;
|
||||
|
||||
public:
|
||||
|
||||
Pool();
|
||||
~Pool();
|
||||
|
||||
/**
|
||||
* Gets the OpenAL format identifier based on number of
|
||||
* channels and bits.
|
||||
* @param channels Either 1 (mono) or 2 (stereo).
|
||||
* @param bits Either 8-bit samples, or 16-bit samples.
|
||||
* @return One of AL_FORMAT_*, or 0 if unsupported format.
|
||||
**/
|
||||
ALenum getFormat(int channels, int bits) const;
|
||||
|
||||
/**
|
||||
* Checks whether an OpenAL source is available.
|
||||
* @return True if at least one is available, false otherwise.
|
||||
**/
|
||||
bool isAvailable() const;
|
||||
|
||||
/**
|
||||
* Checks whether a Source is currently in the playing list.
|
||||
**/
|
||||
bool isPlaying(love::audio::Source * s);
|
||||
|
||||
/**
|
||||
* Returns an available OpenAL source identifier, or 0 if
|
||||
* none is available.
|
||||
* @return An OpenAL source ID, or 0 if unavailable.
|
||||
**/
|
||||
ALuint claim(love::audio::Source * source);
|
||||
|
||||
/**
|
||||
* Makes the specified OpenAL source available for use.
|
||||
* @param source The OpenAL source.
|
||||
**/
|
||||
void release(love::audio::Source * source);
|
||||
|
||||
ALuint find(const love::audio::Source * source) const;
|
||||
|
||||
void update();
|
||||
|
||||
int getNumSources() const;
|
||||
int getMaxSources() const;
|
||||
|
||||
void stop();
|
||||
void pause();
|
||||
void resume();
|
||||
void rewind();
|
||||
|
||||
private:
|
||||
|
||||
ALuint findi(const love::audio::Source * source) const;
|
||||
}; // Pool
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_OPENAL_POOL_H
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Sound.h"
|
||||
|
||||
#include <common/Exception.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
Sound::Sound(Pool * pool, love::sound::SoundData * data)
|
||||
: pool(pool), buffer(0), source(source)
|
||||
{
|
||||
|
||||
// Generate the buffer.
|
||||
alGenBuffers(1, &buffer);
|
||||
|
||||
int fmt = pool->getFormat(data->getChannels(), data->getBits());
|
||||
|
||||
if(fmt == 0)
|
||||
throw love::Exception("Unsopported audio format.");
|
||||
|
||||
alBufferData(buffer, fmt, data->getData(), data->getSize(), data->getSampleRate());
|
||||
|
||||
// Note: we're done with the sound data
|
||||
// at this point. No need to retain.
|
||||
}
|
||||
|
||||
Sound::~Sound()
|
||||
{
|
||||
if(buffer)
|
||||
alDeleteBuffers(1, &buffer);
|
||||
}
|
||||
|
||||
void Sound::play(love::audio::Source * s)
|
||||
{
|
||||
// Set the buffer for the sound.
|
||||
source = pool->find(s);
|
||||
|
||||
if(source)
|
||||
alSourcei(source, AL_BUFFER, buffer);
|
||||
}
|
||||
|
||||
void Sound::update(love::audio::Source * s)
|
||||
{
|
||||
// No need.
|
||||
}
|
||||
|
||||
void Sound::stop(love::audio::Source * s)
|
||||
{
|
||||
// Also no need.
|
||||
}
|
||||
|
||||
void Sound::rewind(love::audio::Source * s)
|
||||
{
|
||||
if(source)
|
||||
alSourceRewind(source);
|
||||
}
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_OPENAL_SOUND_H
|
||||
#define LOVE_AUDIO_OPENAL_SOUND_H
|
||||
|
||||
// LOVE
|
||||
#include <sound/SoundData.h>
|
||||
#include <audio/Sound.h>
|
||||
#include "Pool.h"
|
||||
|
||||
// OpenAL
|
||||
#include <AL/alc.h>
|
||||
#include <AL/al.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
// Forward declarations.
|
||||
class Audio;
|
||||
|
||||
class Sound : public love::audio::Sound
|
||||
{
|
||||
private:
|
||||
|
||||
Pool * pool;
|
||||
|
||||
// Sounds only need one buffer.
|
||||
ALuint buffer;
|
||||
|
||||
ALuint source;
|
||||
|
||||
public:
|
||||
Sound(Pool * pool, love::sound::SoundData * data);
|
||||
virtual ~Sound();
|
||||
|
||||
// Implements Audible.
|
||||
void play(love::audio::Source * s);
|
||||
void update(love::audio::Source * s);
|
||||
void stop(love::audio::Source * s);
|
||||
void rewind(love::audio::Source * s);
|
||||
|
||||
}; // Sound
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_OPENAL_SOUND_H
|
||||
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Source.h"
|
||||
|
||||
// STD
|
||||
#include <iostream>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
|
||||
Source::Source(Pool * pool)
|
||||
: pool(pool), source(0), pitch(1.0f), volume(1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
Source::Source(Pool * pool, Audible * audible)
|
||||
: pool(pool), source(0), pitch(1.0f), volume(1.0f)
|
||||
{
|
||||
setAudible(audible);
|
||||
}
|
||||
|
||||
Source::~Source()
|
||||
{
|
||||
}
|
||||
|
||||
void Source::play()
|
||||
{
|
||||
if(source != 0)
|
||||
return; // Already playing.
|
||||
|
||||
if(pool->isAvailable())
|
||||
source = pool->claim(this);
|
||||
|
||||
if(source != 0)
|
||||
{
|
||||
audible->play(this);
|
||||
|
||||
// Set these properties. These may have changed while we've
|
||||
// been without an AL source.
|
||||
alSourcef(source, AL_PITCH, pitch);
|
||||
alSourcef(source, AL_GAIN, volume);
|
||||
|
||||
alSourcePlay(source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Source::stop()
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
alSourceStop(source);
|
||||
audible->stop(this);
|
||||
source = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Source::pause()
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
alSourcePause(source);
|
||||
}
|
||||
}
|
||||
|
||||
void Source::resume()
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
alSourcePlay(source);
|
||||
}
|
||||
}
|
||||
|
||||
void Source::rewind()
|
||||
{
|
||||
if(audible != 0)
|
||||
audible->rewind(this);
|
||||
}
|
||||
|
||||
bool Source::isFinished() const
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
ALenum state;
|
||||
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
||||
return (state == AL_STOPPED);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Source::update()
|
||||
{
|
||||
if(audible != 0)
|
||||
audible->update(this);
|
||||
}
|
||||
|
||||
void Source::setPitch(float pitch)
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
alSourcef(source, AL_PITCH, pitch);
|
||||
}
|
||||
|
||||
this->pitch = pitch;
|
||||
}
|
||||
|
||||
float Source::getPitch() const
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
ALfloat f;
|
||||
alGetSourcef(source, AL_PITCH, &f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// In case the Source isn't playing.
|
||||
return pitch;
|
||||
}
|
||||
|
||||
void Source::setVolume(float volume)
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
alSourcef(source, AL_GAIN, volume);
|
||||
}
|
||||
|
||||
this->volume = volume;
|
||||
}
|
||||
|
||||
float Source::getVolume() const
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
ALfloat f;
|
||||
alGetSourcef(source, AL_GAIN, &f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// In case the Source isn't playing.
|
||||
return volume;
|
||||
}
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_OPENAL_SOURCE_H
|
||||
#define LOVE_AUDIO_OPENAL_SOURCE_H
|
||||
|
||||
// LOVE
|
||||
#include <common/Object.h>
|
||||
#include <audio/Source.h>
|
||||
#include "Pool.h"
|
||||
|
||||
// OpenAL
|
||||
#include <AL/alc.h>
|
||||
#include <AL/al.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
class Audio;
|
||||
|
||||
class Source : public love::audio::Source
|
||||
{
|
||||
private:
|
||||
|
||||
Pool * pool;
|
||||
ALuint source;
|
||||
|
||||
float pitch;
|
||||
float volume;
|
||||
|
||||
public:
|
||||
Source(Pool * pool);
|
||||
Source(Pool * pool, Audible * audible);
|
||||
virtual ~Source();
|
||||
|
||||
void play();
|
||||
void stop();
|
||||
void pause();
|
||||
void resume();
|
||||
void rewind();
|
||||
bool isFinished() const;
|
||||
void update();
|
||||
|
||||
void setPitch(float pitch);
|
||||
float getPitch() const;
|
||||
|
||||
void setVolume(float volume);
|
||||
float getVolume() const;
|
||||
|
||||
}; // Source
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_OPENAL_SOURCE_H
|
||||
Reference in New Issue
Block a user