Merged love.audio changes.

This commit is contained in:
rude
2010-01-31 13:02:15 +01:00
51 changed files with 894 additions and 1693 deletions
-48
View File
@@ -1,48 +0,0 @@
/**
* 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_AUDIBLE_H
#define LOVE_AUDIO_AUDIBLE_H
// LOVE
#include <common/Object.h>
namespace love
{
namespace audio
{
class Source;
class Audible : public Object
{
public:
virtual ~Audible(){};
virtual void play(Source * source) = 0;
virtual void update(Source * source) = 0;
virtual void stop(Source * source) = 0;
virtual void rewind(Source * source) = 0;
}; // Audible
} // audio
} // love
#endif // LOVE_AUDIO_AUDIBLE_H
+8 -42
View File
@@ -23,11 +23,14 @@
#include <common/Module.h>
#include "Source.h"
#include "Sound.h"
#include "Music.h"
namespace love
{
namespace sound
{
class Decoder;
class SoundData;
}
namespace audio
{
/**
@@ -42,26 +45,9 @@ namespace audio
**/
virtual ~Audio(){};
/**
* Creates a new Sound with the specified SoundData.
* @param data The SoundData from which to create the sound.
* @return A new Sound if successful, zero otherwise.
**/
virtual Sound * newSound(love::sound::SoundData * data) = 0;
/**
* Creates a new Music (stream) using the specified SoundData.
* @param decoder The object to use to decode the sound stream.
**/
virtual Music * newMusic(love::sound::Decoder * decoder) = 0;
/**
* Creates a new Source.
* @returns A new Source.
**/
virtual Source * newSource(Sound * sound) = 0;
virtual Source * newSource(Music * music) = 0;
virtual Source * newSource(love::sound::Decoder * decoder) = 0;
virtual Source * newSource(love::sound::SoundData * soundData) = 0;
/**
* Gets the current number of simulatenous playing sources.
* @return The current number of simulatenous playing sources.
@@ -80,26 +66,6 @@ namespace audio
**/
virtual void play(Source * source) = 0;
/**
* Plays one Sound on the specified Source. We need separate
* Sound and Music play functions because Music must be cloned,
* whereas Sound needs not be.
*
* @param sound The Sound to play.
* @param source The Source on which to play the Sound.
**/
virtual void play(Sound * sound) = 0;
/**
* Plays one Music on the specified Source. We need separate
* Sound and Music play functions because Music must be cloned,
* whereas Sound needs not be.
*
* @param music The Music to play.
* @param source The Source on which to play the Music.
**/
virtual void play(Music * music) = 0;
/**
* Stops playback on the specified source.
* @param source The source on which to stop the playback.
-63
View File
@@ -1,63 +0,0 @@
/**
* 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_MUSIC_H
#define LOVE_AUDIO_MUSIC_H
// LOVE
#include "Audible.h"
#include <sound/Decoder.h>
namespace love
{
namespace audio
{
/**
* A Music object represents a stream of sound samples which are gradually
* acquired somehow. Compare with Sounds, which have all the needed sound
* samples pre-decoded.
*
* Typically, you would want to use love::sound::Decoder to decode samples
* from some encoded format, like OGG or MP3, however, Music can come from
* other sources as well.
**/
class Music : public Audible
{
public:
/**
* Destructor.
**/
virtual ~Music(){};
/**
* Creates a clone of the music stream. Music objects are gradually
* decoded, so if the client wants to play the same Music object, we can't
* use the same object. We must clone the entire stream.
* @return A clone of this object, but rewound to the start.
**/
virtual Music * clone() = 0;
}; // Music
} // audio
} // love
#endif // LOVE_AUDIO_MUSIC_H
-42
View File
@@ -1,42 +0,0 @@
/**
* 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_SOUND_H
#define LOVE_AUDIO_SOUND_H
// LOVE
#include <sound/SoundData.h>
#include "Audible.h"
namespace love
{
namespace audio
{
class Sound : public Audible
{
private:
public:
virtual ~Sound(){};
}; // Sound
} // audio
} // love
#endif // LOVE_AUDIO_SOUND_H
+15 -30
View File
@@ -24,47 +24,32 @@ namespace love
{
namespace audio
{
Source::Source()
: audible(0), looping(false)
Source::Source(Type type)
: type(type)
{
}
Source::~Source()
{
if(audible != 0)
{
audible->stop(this);
audible->release();
}
}
void Source::setAudible(Audible * audible)
{
// If this source already has an audible, remove it.
if(this->audible != 0)
{
this->audible->stop(this);
this->audible->release();
}
this->audible = audible;
audible->retain();
}
Audible * Source::getAudible() const
{
return audible;
}
void Source::setLooping(bool looping)
bool Source::getConstant(const char * in, Type & out)
{
this->looping = looping;
return types.find(in, out);
}
bool Source::isLooping() const
{
return looping;
bool Source::getConstant(Type in, const char *& out)
{
return types.find(in, out);
}
StringMap<Source::Type, Source::TYPE_MAX_ENUM>::Entry Source::typeEntries[] =
{
{"static", Source::TYPE_STATIC},
{"stream", Source::TYPE_STREAM},
};
StringMap<Source::Type, Source::TYPE_MAX_ENUM> Source::types(Source::typeEntries, sizeof(Source::typeEntries));
} // audio
} // love
+27 -9
View File
@@ -23,7 +23,7 @@
// LOVE
#include <common/Object.h>
#include "Audible.h"
#include <common/StringMap.h>
namespace love
{
@@ -31,14 +31,23 @@ namespace audio
{
class Source : public Object
{
protected:
Audible * audible;
bool looping;
public:
Source();
enum Type
{
TYPE_STATIC = 1,
TYPE_STREAM,
TYPE_MAX_ENUM
}; // Type
protected:
Type type;
public:
Source(Type type);
virtual ~Source();
void setAudible(Audible * audible);
Audible * getAudible() const;
virtual Source * copy() = 0;
virtual void play() = 0;
virtual void stop() = 0;
@@ -46,6 +55,7 @@ namespace audio
virtual void resume() = 0;
virtual void rewind() = 0;
virtual bool isStopped() const = 0;
virtual bool isFinished() const = 0;
virtual void update() = 0;
virtual void setPitch(float pitch) = 0;
@@ -62,8 +72,16 @@ namespace audio
virtual void setDirection(float * v) = 0;
virtual void getDirection(float * v) const = 0;
void setLooping(bool looping);
bool isLooping() const;
virtual void setLooping(bool looping) = 0;
virtual bool isLooping() const = 0;
static bool getConstant(const char * in, Type & out);
static bool getConstant(Type in, const char *& out);
private:
static StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[];
static StringMap<Type, TYPE_MAX_ENUM> types;
}; // Source
+2 -20
View File
@@ -39,22 +39,12 @@ namespace null
return "love.audio.null";
}
love::audio::Sound * Audio::newSound(love::sound::SoundData * data)
{
return new Sound(data);
}
love::audio::Music * Audio::newMusic(love::sound::Decoder * decoder)
{
return new Music(decoder);
}
love::audio::Source * Audio::newSource(love::audio::Sound * sound)
love::audio::Source * Audio::newSource(love::sound::Decoder * decoder)
{
return new Source();
}
love::audio::Source * Audio::newSource(love::audio::Music * music)
love::audio::Source * Audio::newSource(love::sound::SoundData * soundData)
{
return new Source();
}
@@ -73,14 +63,6 @@ namespace null
{
}
void Audio::play(love::audio::Sound * sound)
{
}
void Audio::play(love::audio::Music * music)
{
}
void Audio::play()
{
}
+3 -9
View File
@@ -24,8 +24,6 @@
// LOVE
#include <audio/Audio.h>
#include "Sound.h"
#include "Music.h"
#include "Source.h"
namespace love
@@ -41,21 +39,17 @@ namespace null
public:
Audio();
~Audio();
virtual ~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(love::audio::Sound * sound);
love::audio::Source * newSource(love::audio::Music * music);
love::audio::Source * newSource(love::sound::Decoder * decoder);
love::audio::Source * newSource(love::sound::SoundData * soundData);
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();
-63
View File
@@ -1,63 +0,0 @@
/**
* 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"
namespace love
{
namespace audio
{
namespace null
{
Music::Music(love::sound::Decoder * decoder)
: decoder(decoder)
{
decoder->retain();
}
Music::~Music()
{
decoder->release();
}
love::audio::Music * Music::clone()
{
return new Music(decoder->clone());
}
void Music::play(love::audio::Source * s)
{
}
void Music::update(love::audio::Source * s)
{
}
void Music::stop(love::audio::Source * s)
{
}
void Music::rewind(love::audio::Source * s)
{
}
} // null
} // audio
} // love
-57
View File
@@ -1,57 +0,0 @@
/**
* 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_NULL_MUSIC_H
#define LOVE_AUDIO_NULL_MUSIC_H
// LOVE
#include <audio/Music.h>
#include <sound/Decoder.h>
namespace love
{
namespace audio
{
namespace null
{
class Music : public love::audio::Music
{
private:
love::sound::Decoder * decoder;
public:
Music(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();
}; // Music
} // null
} // audio
} // love
#endif // LOVE_AUDIO_NULL_MUSIC_H
-55
View File
@@ -1,55 +0,0 @@
/**
* 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"
namespace love
{
namespace audio
{
namespace null
{
Sound::Sound(love::sound::SoundData * data)
{
}
Sound::~Sound()
{
}
void Sound::play(love::audio::Source * s)
{
}
void Sound::update(love::audio::Source * s)
{
}
void Sound::stop(love::audio::Source * s)
{
}
void Sound::rewind(love::audio::Source * s)
{
}
} // null
} // audio
} // love
-54
View File
@@ -1,54 +0,0 @@
/**
* 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_NULL_SOUND_H
#define LOVE_AUDIO_NULL_SOUND_H
// LOVE
#include <sound/SoundData.h>
#include <audio/Sound.h>
namespace love
{
namespace audio
{
namespace null
{
class Sound : public love::audio::Sound
{
private:
public:
Sound(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
} // null
} // audio
} // love
#endif // LOVE_AUDIO_NULL_SOUND_H
+22 -5
View File
@@ -28,18 +28,20 @@ namespace null
{
Source::Source()
: love::audio::Source(Source::TYPE_STATIC)
{
}
Source::Source(Audible * audible)
{
setAudible(audible);
}
Source::~Source()
{
}
love::audio::Source * Source::copy()
{
this->retain();
return this;
}
void Source::play()
{
}
@@ -65,6 +67,11 @@ namespace null
return true;
}
bool Source::isFinished() const
{
return true;
}
void Source::update()
{
}
@@ -113,6 +120,16 @@ namespace null
{
}
void Source::setLooping(bool looping)
{
this->looping = looping;
}
bool Source::isLooping() const
{
return looping;
}
} // null
} // audio
} // love
+23 -22
View File
@@ -36,33 +36,34 @@ namespace null
private:
float pitch;
float volume;
float volume;
bool looping;
public:
Source();
Source(Audible * audible);
virtual ~Source();
void play();
void stop();
void pause();
void resume();
void rewind();
bool isStopped() const;
void update();
void setPitch(float pitch);
float getPitch() const;
void setVolume(float volume);
float getVolume() const;
void setPosition(float * v);
void getPosition(float * v) const;
void setVelocity(float * v);
void getVelocity(float * v) const;
void setDirection(float * v);
void getDirection(float * v) const;
virtual love::audio::Source * copy();
virtual void play();
virtual void stop();
virtual void pause();
virtual void resume();
virtual void rewind();
virtual bool isStopped() const;
virtual bool isFinished() const;
virtual void update();
virtual void setPitch(float pitch);
virtual float getPitch() const;
virtual void setVolume(float volume);
virtual float getVolume() const;
virtual void setPosition(float * v);
virtual void getPosition(float * v) const;
virtual void setVelocity(float * v);
virtual void getVelocity(float * v) const;
virtual void setDirection(float * v);
virtual void getDirection(float * v) const;
void setLooping(bool looping);
bool isLooping() const;
}; // Source
+4 -30
View File
@@ -82,24 +82,14 @@ namespace openal
return "love.audio.openal";
}
love::audio::Sound * Audio::newSound(love::sound::SoundData * data)
love::audio::Source * Audio::newSource(love::sound::Decoder * decoder)
{
return new Sound(pool, data);
return new Source(pool, decoder);
}
love::audio::Music * Audio::newMusic(love::sound::Decoder * decoder)
love::audio::Source * Audio::newSource(love::sound::SoundData * soundData)
{
return new Music(pool, decoder);
}
love::audio::Source * Audio::newSource(love::audio::Sound * sound)
{
return new Source(pool, sound);
}
love::audio::Source * Audio::newSource(love::audio::Music * music)
{
return new Source(pool, music->clone());
return new Source(pool, soundData);
}
int Audio::getNumSources() const
@@ -117,22 +107,6 @@ namespace openal
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)
{
love::audio::Music *cloned = music->clone();
Source * source = new Source(pool, cloned);
play(source);
cloned->release();
source->release();
}
void Audio::stop(love::audio::Source * source)
{
source->stop();
+2 -8
View File
@@ -35,8 +35,6 @@
#include <common/config.h>
#include <sound/SoundData.h>
#include "Sound.h"
#include "Music.h"
#include "Source.h"
#include "Pool.h"
@@ -86,15 +84,11 @@ namespace openal
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(love::audio::Sound * sound);
love::audio::Source * newSource(love::audio::Music * music);
love::audio::Source * newSource(love::sound::Decoder * decoder);
love::audio::Source * newSource(love::sound::SoundData * soundData);
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();
-134
View File
@@ -1,134 +0,0 @@
/**
* 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(s, 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(s, 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;
rewind(s);
}
}
void Music::rewind(love::audio::Source * s)
{
decoder->rewind();
}
bool Music::stream(love::audio::Source * source, ALuint buffer)
{
if(source->isLooping() && decoder->isFinished())
decoder->rewind();
// 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
-79
View File
@@ -1,79 +0,0 @@
/**
* 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 <common/config.h>
#include <sound/Decoder.h>
#include "Pool.h"
// OpenAL
#ifdef LOVE_MACOSX
#include <OpenAL/alc.h>
#include <OpenAL/al.h>
#else
#include <AL/alc.h>
#include <AL/al.h>
#endif
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(love::audio::Source * source, ALuint buffer);
}; // Sound
} // openal
} // audio
} // love
#endif // LOVE_AUDIO_OPENAL_MUSIC_H
+123 -60
View File
@@ -20,6 +20,8 @@
#include "Pool.h"
#include "Source.h"
#define MUTEX_ASSERT(fn, sval) \
if(fn != sval) \
{ \
@@ -62,20 +64,6 @@ namespace openal
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;
@@ -85,42 +73,11 @@ namespace openal
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));
source->retain();
}
UNLOCK(mutex);
return s;
}
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 Pool::isPlaying(Source * s)
{
bool p = false;
LOCK(mutex);
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
{
if(i->first == s)
p = true;
@@ -133,13 +90,13 @@ namespace openal
{
LOCK(mutex);
std::map<love::audio::Source *, ALuint>::iterator i = playing.begin();
std::map<Source *, ALuint>::iterator i = playing.begin();
while(i != playing.end())
{
if(i->first->isStopped())
{
i->first->stop();
i->first->stopAtomic();
i->first->release();
available.push(i->second);
playing.erase(i++);
@@ -164,12 +121,56 @@ namespace openal
return NUM_SOURCES;
}
bool Pool::play(Source * source, ALuint & out)
{
bool ok;
out = 0;
LOCK(mutex);
bool alreadyPlaying = findSource(source, out);
if(!alreadyPlaying)
{
// Try to play.
if(!available.empty())
{
// Get the first available source.
out = available.front();
// Remove it.
available.pop();
// Insert into map of playing sources.
playing.insert(std::pair<Source *, ALuint>(source, out));
source->retain();
source->playAtomic();
ok = true;
}
else
{
ok = false;
}
}
else
{
ok = true;
}
UNLOCK(mutex);
return ok;
}
void Pool::stop()
{
LOCK(mutex);
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
{
i->first->stop();
i->first->stopAtomic();
available.push(i->second);
}
@@ -178,31 +179,65 @@ namespace openal
UNLOCK(mutex);
}
void Pool::stop(Source * source)
{
LOCK(mutex);
removeSource(source);
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();
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
i->first->pauseAtomic();
UNLOCK(mutex);
}
void Pool::pause(Source * source)
{
LOCK(mutex);
ALuint out;
if(findSource(source, out))
source->pauseAtomic();
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();
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
i->first->resumeAtomic();
UNLOCK(mutex);
}
void Pool::resume(Source * source)
{
LOCK(mutex);
ALuint out;
if(findSource(source, out))
source->resumeAtomic();
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();
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
i->first->rewindAtomic();
UNLOCK(mutex);
}
void Pool::release(love::audio::Source * source)
void Pool::rewind(Source * source)
{
LOCK(mutex);
ALuint out;
if(findSource(source, out))
source->rewindAtomic();
UNLOCK(mutex);
}
void Pool::release(Source * source)
{
ALuint s = findi(source);
@@ -213,9 +248,9 @@ namespace openal
}
}
ALuint Pool::findi(const love::audio::Source * source) const
ALuint Pool::findi(const Source * source) const
{
std::map<love::audio::Source *, ALuint>::const_iterator i = playing.find((love::audio::Source *)source);
std::map<Source *, ALuint>::const_iterator i = playing.find((Source *)source);
if(i != playing.end())
return i->second;
@@ -223,6 +258,34 @@ namespace openal
return 0;
}
bool Pool::findSource(Source * source, ALuint & out)
{
std::map<Source *, ALuint>::const_iterator i = playing.find((Source *)source);
bool found = i != playing.end();
if(found)
out = i->second;
return found;
}
bool Pool::removeSource(Source * source)
{
std::map<Source *, ALuint>::const_iterator i = playing.find((Source *)source);
if(i != playing.end())
{
source->stopAtomic();
source->release();
available.push(i->second);
playing.erase(i++);
return true;
}
return false;
}
} // openal
} // audio
} // love
+15 -23
View File
@@ -31,7 +31,6 @@
#include <SDL.h>
// LOVE
#include <audio/Source.h>
#include <common/config.h>
#include <common/Exception.h>
@@ -50,6 +49,9 @@ namespace audio
{
namespace openal
{
class Source;
class Pool
{
private:
@@ -64,7 +66,7 @@ namespace openal
std::queue<ALuint> available;
// A map of playing sources.
std::map<love::audio::Source *, ALuint> playing;
std::map<Source *, ALuint> playing;
// Only one thread can access this object at the same time. This mutex will
// make sure of that.
@@ -75,15 +77,6 @@ namespace openal
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.
@@ -93,26 +86,22 @@ namespace openal
/**
* 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);
ALuint find(const love::audio::Source * source) const;
bool isPlaying(Source * s);
void update();
int getNumSources() const;
int getMaxSources() const;
bool play(Source * source, ALuint & out);
void stop();
void stop(Source * source);
void pause();
void pause(Source * source);
void resume();
void resume(Source * source);
void rewind();
void rewind(Source * source);
private:
@@ -120,9 +109,12 @@ namespace openal
* Makes the specified OpenAL source available for use.
* @param source The OpenAL source.
**/
void release(love::audio::Source * source);
void release(Source * source);
ALuint findi(const love::audio::Source * source) const;
ALuint findi(const Source * source) const;
bool findSource(Source * source, ALuint & out);
bool removeSource(Source * source);
}; // Pool
} // openal
-87
View File
@@ -1,87 +0,0 @@
/**
* 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("Unsupported 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);
alSourcei(source, AL_LOOPING, s->isLooping() ? AL_TRUE : AL_FALSE);
}
}
void Sound::update(love::audio::Source * s)
{
// Looping mode could have changed.
alSourcei(source, AL_LOOPING, s->isLooping() ? AL_TRUE : AL_FALSE);
}
void Sound::stop(love::audio::Source * s)
{
if(source)
alSourceStop(source);
}
void Sound::rewind(love::audio::Source * s)
{
if(source)
alSourceRewind(source);
}
} // openal
} // audio
} // love
-77
View File
@@ -1,77 +0,0 @@
/**
* 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 <common/config.h>
#include "Pool.h"
// OpenAL
#ifdef LOVE_MACOSX
#include <OpenAL/alc.h>
#include <OpenAL/al.h>
#else
#include <AL/alc.h>
#include <AL/al.h>
#endif
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
+212 -56
View File
@@ -20,6 +20,8 @@
#include "Source.h"
#include "Pool.h"
// STD
#include <iostream>
@@ -30,107 +32,116 @@ namespace audio
namespace openal
{
Source::Source(Pool * pool)
: pool(pool), source(0), pitch(1.0f), volume(1.0f)
static int acc = 0;
Source::Source(Pool * pool, love::sound::SoundData * soundData)
: love::audio::Source(Source::TYPE_STATIC), pool(pool), pitch(1.0f),
volume(1.0f), looping(false), decoder(0), valid(false)
{
alGenBuffers(1, buffers);
ALenum fmt = getFormat(soundData->getChannels(), soundData->getBits());
alBufferData(buffers[0], fmt, soundData->getData(), soundData->getSize(), soundData->getSampleRate());
}
Source::Source(Pool * pool, Audible * audible)
: pool(pool), source(0), pitch(1.0f), volume(1.0f)
Source::Source(Pool * pool, love::sound::Decoder * decoder)
: love::audio::Source(Source::TYPE_STREAM), pool(pool), pitch(1.0f),
volume(1.0f), looping(false), decoder(decoder), valid(false)
{
setAudible(audible);
decoder->retain();
alGenBuffers(MAX_BUFFERS, buffers);
}
Source::~Source()
{
stop();
alDeleteBuffers((type == TYPE_STATIC) ? 1 : MAX_BUFFERS, buffers);
}
love::audio::Source * Source::copy()
{
return 0;
}
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);
}
valid = pool->play(this, source);
}
void Source::stop()
{
if(source)
{
alSourceStop(source);
audible->stop(this);
source = 0;
}
pool->stop(this);
}
void Source::pause()
{
if(source)
{
alSourcePause(source);
}
pool->pause();
}
void Source::resume()
{
if(source)
{
alSourcePlay(source);
}
pool->resume();
}
void Source::rewind()
{
if(audible != 0)
audible->rewind(this);
pool->rewind();
}
bool Source::isStopped() const
{
if(source)
if(valid)
{
ALenum state;
alGetSourcei(source, AL_SOURCE_STATE, &state);
return (state == AL_STOPPED);
}
return true;
return true;
}
bool Source::isFinished() const
{
return type == TYPE_STATIC ? isStopped() : isStopped() && !isLooping() && decoder->isFinished();
}
void Source::update()
{
if(audible != 0)
audible->update(this);
if(valid && type == TYPE_STATIC)
{
// Looping mode could have changed.
alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
}
else if(valid && type == TYPE_STREAM)
{
// 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(streamAtomic(buffer, decoder) > 0)
alSourceQueueBuffers(source, 1, &buffer);
}
}
}
void Source::setPitch(float pitch)
{
if(source)
{
if(valid)
alSourcef(source, AL_PITCH, pitch);
}
this->pitch = pitch;
}
float Source::getPitch() const
{
if(source)
if(valid)
{
ALfloat f;
alGetSourcef(source, AL_PITCH, &f);
@@ -143,7 +154,7 @@ namespace openal
void Source::setVolume(float volume)
{
if(source)
if(valid)
{
alSourcef(source, AL_GAIN, volume);
}
@@ -153,7 +164,7 @@ namespace openal
float Source::getVolume() const
{
if(source)
if(valid)
{
ALfloat f;
alGetSourcef(source, AL_GAIN, &f);
@@ -166,40 +177,185 @@ namespace openal
void Source::setPosition(float * v)
{
if(source)
if(valid)
alSourcefv(source, AL_POSITION, v);
}
void Source::getPosition(float * v) const
{
if(source)
if(valid)
alGetSourcefv(source, AL_POSITION, v);
}
void Source::setVelocity(float * v)
{
if(source)
if(valid)
alSourcefv(source, AL_VELOCITY, v);
}
void Source::getVelocity(float * v) const
{
if(source)
if(valid)
alGetSourcefv(source, AL_VELOCITY, v);
}
void Source::setDirection(float * v)
{
if(source)
if(valid)
alSourcefv(source, AL_DIRECTION, v);
}
void Source::getDirection(float * v) const
{
if(source)
if(valid)
alGetSourcefv(source, AL_DIRECTION, v);
}
void Source::setLooping(bool looping)
{
this->looping = looping;
}
bool Source::isLooping() const
{
return looping;
}
void Source::playAtomic()
{
if(type == TYPE_STATIC)
{
alSourcei(source, AL_BUFFER, buffers[0]);
alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
}
else if(type == TYPE_STREAM)
{
int usedBuffers = 0;
for(int i = 0; i < MAX_BUFFERS; i++)
{
int decoded = streamAtomic(buffers[i], decoder);
++usedBuffers;
if(decoded < decoder->getSize())
break;
}
if(usedBuffers > 0)
alSourceQueueBuffers(source, usedBuffers, buffers);
}
// 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::stopAtomic()
{
if(valid)
{
if(type == TYPE_STATIC)
{
alSourceStop(source);
}
else if(type == TYPE_STREAM)
{
alSourceStop(source);
int queued = 0;
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
while(queued--)
{
ALuint buffer;
alSourceUnqueueBuffers(source, 1, &buffer);
}
}
reset(source);
}
rewindAtomic();
valid = false;
}
void Source::pauseAtomic()
{
if(valid)
{
alSourcePause(source);
}
}
void Source::resumeAtomic()
{
if(valid)
{
alSourcePlay(source);
}
}
void Source::rewindAtomic()
{
if(valid && type == TYPE_STATIC)
{
alSourceRewind(source);
}
else if(valid && type == TYPE_STREAM)
{
decoder->rewind();
}
}
void Source::reset(ALenum source)
{
alSourcei(source, AL_BUFFER, AL_NONE);
}
ALenum Source::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;
}
int Source::streamAtomic(ALuint buffer, love::sound::Decoder * d)
{
//if(isLooping() && d->isFinished())
// d->rewind();
// Get more sound data.
int decoded = d->decode();
int fmt = getFormat(d->getChannels(), d->getBits());
//printf("Decoded %i ( %i )", decoded, d->getSize());
if(decoded > 0 && fmt != 0)
{
alBufferData(buffer, fmt, d->getBuffer(), decoded, d->getSampleRate());
acc++;
//printf(" [%i] ", acc);
}
if(decoded < d->getSize() && isLooping())
{
printf(" Rewinding at %i.\n", acc);
d->rewind();
acc = 0;
}
return decoded;
}
} // openal
} // audio
} // love
+51 -21
View File
@@ -25,7 +25,8 @@
#include <common/config.h>
#include <common/Object.h>
#include <audio/Source.h>
#include "Pool.h"
#include <sound/SoundData.h>
#include <sound/Decoder.h>
// OpenAL
#ifdef LOVE_MACOSX
@@ -43,6 +44,7 @@ namespace audio
namespace openal
{
class Audio;
class Pool;
class Source : public love::audio::Source
{
@@ -50,35 +52,63 @@ namespace openal
Pool * pool;
ALuint source;
bool valid;
static const unsigned int MAX_BUFFERS = 32;
ALuint buffers[MAX_BUFFERS];
float pitch;
float volume;
float volume;
bool looping;
love::sound::Decoder * decoder;
public:
Source(Pool * pool);
Source(Pool * pool, Audible * audible);
Source(Pool * pool, love::sound::SoundData * soundData);
Source(Pool * pool, love::sound::Decoder * decoder);
virtual ~Source();
void play();
void stop();
void pause();
void resume();
void rewind();
bool isStopped() const;
void update();
virtual love::audio::Source * copy();
virtual void play();
virtual void stop();
virtual void pause();
virtual void resume();
virtual void rewind();
virtual bool isStopped() const;
virtual bool isFinished() const;
virtual void update();
virtual void setPitch(float pitch);
virtual float getPitch() const;
virtual void setVolume(float volume);
virtual float getVolume() const;
virtual void setPosition(float * v);
virtual void getPosition(float * v) const;
virtual void setVelocity(float * v);
virtual void getVelocity(float * v) const;
virtual void setDirection(float * v);
virtual void getDirection(float * v) const;
void setLooping(bool looping);
bool isLooping() const;
void setPitch(float pitch);
float getPitch() const;
void playAtomic();
void stopAtomic();
void pauseAtomic();
void resumeAtomic();
void rewindAtomic();
void setVolume(float volume);
float getVolume() const;
private:
void setPosition(float * v);
void getPosition(float * v) const;
void setVelocity(float * v);
void getVelocity(float * v) const;
void setDirection(float * v);
void getDirection(float * v) const;
void reset(ALenum source);
/**
* 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;
int streamAtomic(ALuint buffer, love::sound::Decoder * d);
}; // Source
+24 -71
View File
@@ -24,6 +24,8 @@
#include "openal/Audio.h"
#include "null/Audio.h"
#include <scripts/audio.lua.h>
namespace love
{
namespace audio
@@ -36,81 +38,31 @@ namespace audio
return 1;
}
int w_newSound(lua_State * L)
{
// Convert to File, if necessary.
if(lua_isstring(L, 1))
luax_convobj(L, 1, "filesystem", "newFile");
// Convert to SoundData, if necessary.
if(luax_istype(L, 1, FILESYSTEM_FILE_T))
luax_convobj(L, 1, "sound", "newSoundData");
love::sound::SoundData * data = luax_checktype<love::sound::SoundData>(L, 1, "SoundData", SOUND_SOUND_DATA_T);
Sound * t = instance->newSound(data);
luax_newtype(L, "Sound", AUDIO_SOUND_T, (void*)t);
return 1;
}
int w_newMusic(lua_State * L)
{
// Convert to Decoder, if necessary.
if(!luax_istype(L, 1, SOUND_DECODER_T))
luax_convobj(L, 1, "sound", "newDecoder");
love::sound::Decoder * decoder = luax_checktype<love::sound::Decoder>(L, 1, "Decoder", SOUND_DECODER_T);
Music * t = instance->newMusic(decoder);
luax_newtype(L, "Music", AUDIO_MUSIC_T, (void*)t);
return 1;
}
int w_newSource(lua_State * L)
int w_newSource1(lua_State * L)
{
Source * t = 0;
if(luax_istype(L, 1, AUDIO_SOUND_T))
if(luax_istype(L, 1, SOUND_SOUND_DATA_T))
t = instance->newSource(luax_totype<love::sound::SoundData>(L, 1, "SoundData", SOUND_SOUND_DATA_T));
else if(luax_istype(L, 1, SOUND_DECODER_T))
t = instance->newSource(luax_totype<love::sound::Decoder>(L, 1, "Decoder", SOUND_DECODER_T));
if(t)
{
Sound * s = luax_checksound(L, 1);
t = instance->newSource(s);
}
else if(luax_istype(L, 1, AUDIO_MUSIC_T))
{
Music * m = luax_checkmusic(L, 1);
t = instance->newSource(m);
luax_newtype(L, "Source", AUDIO_SOURCE_T, (void*)t);
return 1;
}
if(!t)
else
return luaL_error(L, "No matching overload");
luax_newtype(L, "Source", AUDIO_SOURCE_T, (void*)t);
return 1;
return 0;
}
int w_play(lua_State * L)
{
int argn = lua_gettop(L);
if(luax_istype(L, 1, AUDIO_SOUND_T))
{
Sound * s = luax_checksound(L, 1);
instance->play(s);
return 0;
}
else if(luax_istype(L, 1, AUDIO_MUSIC_T))
{
Music * m = luax_checkmusic(L, 1);
instance->play(m);
return 0;
}
else if(luax_istype(L, 1, AUDIO_SOURCE_T))
{
Source * s = luax_checksource(L, 1);
instance->play(s);
return 0;
}
return luaL_error(L, "No matching overload");
Source * s = luax_checksource(L, 1);
instance->play(s);
return 0;
}
int w_stop(lua_State * L)
@@ -252,9 +204,7 @@ namespace audio
// List of functions to wrap.
static const luaL_Reg functions[] = {
{ "getNumSources", w_getNumSources },
{ "newSound", w_newSound },
{ "newMusic", w_newMusic },
{ "newSource", w_newSource },
{ "newSource1", w_newSource1 },
{ "play", w_play },
{ "stop", w_stop },
{ "pause", w_pause },
@@ -273,8 +223,6 @@ namespace audio
static const lua_CFunction types[] = {
luaopen_source,
luaopen_music,
luaopen_sound,
0
};
@@ -316,7 +264,12 @@ namespace audio
w.functions = functions;
w.types = types;
return luax_register_module(L, w);
luax_register_module(L, w);
if (luaL_loadbuffer(L, (const char *)audio_lua, sizeof(audio_lua), "audio.lua") == 0)
lua_call(L, 0, 0);
return 0;
}
} // audio
+3 -5
View File
@@ -22,9 +22,9 @@
#define LOVE_AUDIO_WRAP_AUDIO_H
// LOVE
#include <common/config.h>
#include <common/runtime.h>
#include "Audio.h"
#include "wrap_Sound.h"
#include "wrap_Music.h"
#include "wrap_Source.h"
namespace love
@@ -32,9 +32,7 @@ namespace love
namespace audio
{
int w_getNumSources(lua_State * L);
int w_newSound(lua_State * L);
int w_newMusic(lua_State * L);
int w_newSource(lua_State * L);
int w_newSource1(lua_State * L);
int w_play(lua_State * L);
int w_stop(lua_State * L);
int w_pause(lua_State * L);
-42
View File
@@ -1,42 +0,0 @@
/**
* 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 "wrap_Music.h"
namespace love
{
namespace audio
{
Music * luax_checkmusic(lua_State * L, int idx)
{
return luax_checktype<Music>(L, idx, "Music", AUDIO_MUSIC_T);
}
static const luaL_Reg functions[] = {
{ 0, 0 }
};
int luaopen_music(lua_State * L)
{
return luax_register_type(L, "Music", functions);
}
} // audio
} // love
-37
View File
@@ -1,37 +0,0 @@
/**
* 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_WRAP_MUSIC_H
#define LOVE_AUDIO_WRAP_MUSIC_H
#include <common/runtime.h>
#include "Music.h"
namespace love
{
namespace audio
{
Music * luax_checkmusic(lua_State * L, int idx);
int luaopen_music(lua_State * L);
} // audio
} // love
#endif // LOVE_AUDIO_WRAP_MUSIC_H
-42
View File
@@ -1,42 +0,0 @@
/**
* 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 "wrap_Sound.h"
namespace love
{
namespace audio
{
Sound * luax_checksound(lua_State * L, int idx)
{
return luax_checktype<Sound>(L, idx, "Sound", AUDIO_SOUND_T);
}
static const luaL_Reg functions[] = {
{ 0, 0 }
};
int luaopen_sound(lua_State * L)
{
return luax_register_type(L, "Sound", functions);
}
} // audio
} // love
-37
View File
@@ -1,37 +0,0 @@
/**
* 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_WRAP_SOUND_H
#define LOVE_AUDIO_WRAP_SOUND_H
#include <common/runtime.h>
#include "Sound.h"
namespace love
{
namespace audio
{
Sound * luax_checksound(lua_State * L, int idx);
int luaopen_sound(lua_State * L);
} // audio
} // love
#endif // LOVE_AUDIO_WRAP_SOUND_H
+8
View File
@@ -139,6 +139,13 @@ namespace audio
return 1;
}
int w_Source_isStopped(lua_State * L)
{
Source * t = luax_checksource(L, 1);
luax_pushboolean(L, t->isStopped());
return 1;
}
static const luaL_Reg functions[] = {
{ "setPitch", w_Source_setPitch },
{ "getPitch", w_Source_getPitch },
@@ -146,6 +153,7 @@ namespace audio
{ "getVolume", w_Source_getVolume },
{ "setLooping", w_Source_setLooping },
{ "isLooping", w_Source_isLooping },
{ "isStopped", w_Source_isStopped },
{ 0, 0 }
};
+1
View File
@@ -41,6 +41,7 @@ namespace audio
int w_Source_getDirection(lua_State * L);
int w_Source_setLooping(lua_State * L);
int w_Source_isLooping(lua_State * L);
int w_Source_isStopped(lua_State * L);
int luaopen_source(lua_State * L);
} // audio
+2 -2
View File
@@ -40,7 +40,7 @@ namespace sound
* Indicates how many bytes of raw data should be generated at each
* call to Decode.
**/
static const int DEFAULT_BUFFER_SIZE = 1024;
static const int DEFAULT_BUFFER_SIZE = 2048;
/**
* Indicates the quality of the sound.
@@ -55,7 +55,7 @@ namespace sound
/**
* 16 bit audio is the default.
**/
static const int DEFAULT_T = 16;
static const int DEFAULT_BITS = 16;
/**
* Creates a deep of itself. The sound stream can (and should) be
+5 -1
View File
@@ -60,7 +60,11 @@ namespace lullaby
bool ModPlugDecoder::accepts(const std::string & ext)
{
static const std::string supported[] = {
"it", "xm", "mod", "wav", ""
"699", "abc", "amf", "ams", "dbm", "dmf",
"dsm", "far", "it", "j2b", "mdl", "med",
"mid", "mod", "mt2", "mtm", "okt", "pat",
"psm", "s3m", "stm", "ult", "umx", "wav",
"xm", ""
};
for(int i = 0; !(supported[i].empty()); i++)
+1 -1
View File
@@ -44,7 +44,7 @@ namespace lullaby
public:
ModPlugDecoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
~ModPlugDecoder();
virtual ~ModPlugDecoder();
static bool accepts(const std::string & ext);
+72 -33
View File
@@ -34,9 +34,12 @@ namespace lullaby
bool Mpg123Decoder::inited = false;
Mpg123Decoder::Mpg123Decoder(Data * data, const std::string & ext, int bufferSize, int sampleRate)
: Decoder(data, ext, bufferSize, sampleRate), handle(0), islooping(false)
: Decoder(data, ext, bufferSize, sampleRate), handle(0)
{
data_size = data->getSize();
data_offset = 0;
int ret;
if(!inited)
@@ -57,21 +60,11 @@ namespace lullaby
ret = mpg123_format(handle, sampleRate, MPG123_STEREO, MPG123_ENC_SIGNED_16);
if (ret != MPG123_OK)
throw love::Exception("Could not set output format.");
size_t numbytes = 0;
ret = mpg123_decode(handle, (unsigned char*)data->getData(), data->getSize(), NULL, 0, &numbytes);
if(ret == MPG123_NEW_FORMAT)
{
long rate;
int channels;
int encoding;
mpg123_getformat(handle, &rate, &channels, &encoding);
}
else if(ret != 0)
{
throw love::Exception(mpg123_strerror(handle));
}
ret = feed(16384);
if (ret != MPG123_OK && ret != MPG123_DONE)
throw love::Exception("Could not feed!");
}
Mpg123Decoder::~Mpg123Decoder()
@@ -108,26 +101,51 @@ namespace lullaby
int Mpg123Decoder::decode()
{
size_t numbytes;
int r = mpg123_read(handle, (unsigned char*) buffer, bufferSize, &numbytes);
if (r == MPG123_DONE || r != MPG123_OK)
int size = 0;
bool done = false;
while(size < bufferSize && !done && !eof)
{
if ( r == MPG123_NEED_MORE && islooping )
{
islooping = false;
size_t numbytes = 0;
mpg123_decode(handle, (unsigned char*) data->getData(), data->getSize(), (unsigned char*) buffer, bufferSize, &numbytes);
}
else
size_t numbytes = 0;
int r = mpg123_read(handle, (unsigned char*) buffer + size, bufferSize - size, &numbytes);
switch(r)
{
case MPG123_NEW_FORMAT:
continue;
case MPG123_NEED_MORE:
{
int v = feed(8192);
switch(v)
{
case MPG123_OK:
continue;
case MPG123_DONE:
if(numbytes == 0)
eof = true;
break;
default:
done = true;
}
continue;
}
case MPG123_OK:
size += numbytes;
continue;
case MPG123_DONE:
// Apparently, mpg123_read does not return MPG123_DONE, but
// let's keep it here anyway.
eof = true;
numbytes = 0;
default:
done = true;
break;
}
}
return numbytes;
return size;
}
bool Mpg123Decoder::seek(float s)
@@ -139,11 +157,16 @@ namespace lullaby
bool Mpg123Decoder::rewind()
{
if(mpg123_seek(handle, 0, SEEK_SET) >= 0)
return false;
islooping = true;
eof = false;
return true;
off_t offset;
if(mpg123_feedseek(handle, 0, SEEK_SET, &offset) >= 0)
{
data_offset = offset;
return true;
}
else
return false;
}
bool Mpg123Decoder::isSeekable()
@@ -160,7 +183,23 @@ namespace lullaby
{
return 16;
}
int Mpg123Decoder::feed(int bytes)
{
int remaining = data_size - data_offset;
if(remaining <= 0)
return MPG123_DONE;
int feed_bytes = remaining < bytes ? remaining : bytes;
int r = mpg123_feed(handle, (unsigned char*)data->getData() + data_offset, feed_bytes);
if(r == MPG123_OK || r == MPG123_DONE)
data_offset += feed_bytes;
return r;
}
} // lullaby
} // sound
+8 -2
View File
@@ -43,13 +43,15 @@ namespace lullaby
private:
mpg123_handle * handle;
bool islooping;
static bool inited;
int data_offset;
int data_size;
public:
Mpg123Decoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
~Mpg123Decoder();
virtual ~Mpg123Decoder();
static bool accepts(const std::string & ext);
static void quit();
@@ -62,6 +64,10 @@ namespace lullaby
int getChannels() const;
int getBits() const;
private:
int feed(int bytes);
}; // Decoder
} // lullaby
+2 -2
View File
@@ -55,9 +55,9 @@ namespace lullaby
// Find a suitable decoder here, and return it.
if(ModPlugDecoder::accepts(ext))
decoder = new ModPlugDecoder(data, ext, bufferSize, sampleRate);
else if (Mpg123Decoder::accepts(ext))
else if(Mpg123Decoder::accepts(ext))
decoder = new Mpg123Decoder(data, ext, bufferSize, sampleRate);
else if (VorbisDecoder::accepts(ext))
else if(VorbisDecoder::accepts(ext))
decoder = new VorbisDecoder(data, ext, bufferSize, sampleRate);
/*else if (FLACDecoder::accepts(ext))
decoder = new FLACDecoder(data, ext, bufferSize, sampleRate);*/
+10 -31
View File
@@ -182,42 +182,20 @@ namespace lullaby
int VorbisDecoder::decode()
{
int bits = this->getBits();
int size = 0;
int section;
int result;
if(bits == 16)
bits = 2;
else
bits = 1;
while(size < bufferSize)
{
result = ov_read(&handle, (char*) buffer + size, bufferSize - size, endian, bits, 1, &section);
int result = ov_read(&handle, (char*) buffer + size, bufferSize - size, endian, (getBits() == 16 ? 2 : 1), 1, 0);
if(result > 0)
size += result;
else if(result < 0)
{
switch(result)
{
case OV_EREAD:
throw love::Exception("Vorbis read: Read from media");
case OV_ENOTVORBIS:
throw love::Exception("Vorbis read: Not Vorbis data");
case OV_EVERSION:
throw love::Exception("Vorbis read: Vorbis version mismatch");
case OV_EBADHEADER:
throw love::Exception("Vorbis read: Invalid Vorbis header");
case OV_EFAULT:
throw love::Exception("Vorbis read: Internal logic fault (bug or heap/stack corruption)");
default:
throw love::Exception("Vorbis read: Unknown error");
}
}
else
if(result == OV_HOLE)
continue;
else if(result <= OV_EREAD)
return -1;
else if(result == 0)
break;
else if(result > 0)
size += result;
}
if(oggFile.dataSize - oggFile.dataRead == 0)
@@ -256,7 +234,8 @@ namespace lullaby
bool VorbisDecoder::rewind()
{
eof = false;
return this->seek(0);
ov_pcm_seek(&handle, 0);
return true;
}
bool VorbisDecoder::isSeekable()
+1 -1
View File
@@ -56,7 +56,7 @@ namespace lullaby
public:
VorbisDecoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
~VorbisDecoder();
virtual ~VorbisDecoder();
static bool accepts(const std::string & ext);
+1 -1
View File
@@ -37,7 +37,7 @@ namespace sound
{
int samples = luaL_checkint(L, 1);
int sampleRate = luaL_optint(L, 2, Decoder::DEFAULT_SAMPLE_RATE);
int bits = luaL_optint(L, 3, Decoder::DEFAULT_T);
int bits = luaL_optint(L, 3, Decoder::DEFAULT_BITS);
int channels = luaL_optint(L, 4, Decoder::DEFAULT_CHANNELS);
try