imported Löve GLES branch (changeset 1ba9037e558b)

This commit is contained in:
Martin Felis
2013-12-05 18:05:13 +01:00
parent 41b2db04a7
commit 2644d1ee18
615 changed files with 150300 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
/**
* Copyright (c) 2006-2013 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 Audio 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 Audio distribution.
**/
#include "Audio.h"
namespace love
{
namespace audio
{
StringMap<Audio::DistanceModel, Audio::DISTANCE_MAX_ENUM>::Entry Audio::distanceModelEntries[] =
{
{"none", Audio::DISTANCE_NONE},
{"inverse", Audio::DISTANCE_INVERSE},
{"inverse clamped", Audio::DISTANCE_INVERSE_CLAMPED},
{"linear", Audio::DISTANCE_LINEAR},
{"linear clamped", Audio::DISTANCE_LINEAR_CLAMPED},
{"exponent", Audio::DISTANCE_EXPONENT},
{"exponent clamped", Audio::DISTANCE_EXPONENT_CLAMPED}
};
StringMap<Audio::DistanceModel, Audio::DISTANCE_MAX_ENUM> Audio::distanceModels(Audio::distanceModelEntries, sizeof(Audio::distanceModelEntries));
bool Audio::getConstant(const char *in, DistanceModel &out)
{
return distanceModels.find(in, out);
}
bool Audio::getConstant(DistanceModel in, const char *&out)
{
return distanceModels.find(in, out);
}
} // audio
} // love
+239
View File
@@ -0,0 +1,239 @@
/**
* Copyright (c) 2006-2013 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 = 0; 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_AUDIO_H
#define LOVE_AUDIO_AUDIO_H
#include "common/Module.h"
#include "common/StringMap.h"
#include "Source.h"
namespace love
{
namespace sound
{
class Decoder;
class SoundData;
} // sound
namespace audio
{
/**
* The Audio module is responsible for playing back raw sound samples.
**/
class Audio : public Module
{
public:
/**
* Attenuation by distance.
*/
enum DistanceModel
{
DISTANCE_NONE = 1,
DISTANCE_INVERSE,
DISTANCE_INVERSE_CLAMPED,
DISTANCE_LINEAR,
DISTANCE_LINEAR_CLAMPED,
DISTANCE_EXPONENT,
DISTANCE_EXPONENT_CLAMPED,
DISTANCE_MAX_ENUM
};
static bool getConstant(const char *in, DistanceModel &out);
static bool getConstant(DistanceModel in, const char *&out);
/**
* Destructor.
**/
virtual ~Audio() {};
virtual Source *newSource(love::sound::Decoder *decoder) = 0;
virtual Source *newSource(love::sound::SoundData *soundData) = 0;
/**
* Gets the current number of simultaneous playing sources.
* @return The current number of simultaneous playing sources.
**/
virtual int getSourceCount() const = 0;
/**
* Gets the maximum supported number of simultaneous playing sources.
* @return The maximum supported number of simultaneous playing sources.
**/
virtual int getMaxSources() const = 0;
/**
* Play the specified Source.
* @param source The Source to play.
**/
virtual void play(Source *source) = 0;
/**
* Stops playback on the specified source.
* @param source The source on which to stop the playback.
**/
virtual void stop(Source *source) = 0;
/**
* Stops all playing audio.
**/
virtual void stop() = 0;
/**
* Pauses playback on the specified source.
* @param source The source on which to pause the playback.
**/
virtual void pause(Source *source) = 0;
/**
* Pauses all audio.
**/
virtual void pause() = 0;
/**
* Resumes playback on the specified source.
* @param source The source on which to resume the playback.
**/
virtual void resume(Source *source) = 0;
/**
* Resumes all audio.
**/
virtual void resume() = 0;
/**
* Rewinds the specified source. Whatever is playing on this
* source gets rewound to the start.
* @param source The source to rewind.
**/
virtual void rewind(Source *source) = 0;
/**
* Rewinds all playing audio.
**/
virtual void rewind() = 0;
/**
* Sets the master volume, where 0.0f is min (off) and 1.0f is max.
* @param volume The new master volume.
**/
virtual void setVolume(float volume) = 0;
/**
* Gets the master volume.
* @return The current master volume.
**/
virtual float getVolume() const = 0;
/**
* Gets the position of the listener.
* @param v A float array of size 3 containing (x,y,z) in that order.
**/
virtual void getPosition(float *v) const = 0;
/**
* Sets the position of the listener.
* @param v A float array of size 3 containing [x,y,z] in that order.
**/
virtual void setPosition(float *v) = 0;
/**
* Gets the orientation of the listener.
* @param v A float array of size 6 containing [x,y,z] for the forward
* vector, followed by [x,y,z] for the up vector.
**/
virtual void getOrientation(float *v) const = 0;
/**
* Sets the orientation of the listener.
* @param v A float array of size 6 containing [x,y,z] for the forward
* vector, followed by [x,y,z] for the up vector.
**/
virtual void setOrientation(float *v) = 0;
/**
* Gets the velocity of the listener.
* @param v A float array of size 3 containing [x,y,z] in that order.
**/
virtual void getVelocity(float *v) const = 0;
/**
* Sets the velocity of the listener.
* @param v A float array of size 3 containing [x,y,z] in that order.
**/
virtual void setVelocity(float *v) = 0;
/**
* Begins recording audio input from the microphone.
**/
virtual void record() = 0;
/**
* Gets a section of recorded audio.
* Per OpenAL, the measurement begins from the start of the
* audio data in memory, which is after the last time this function
* was called. If this function has not been called yet this recording
* session, it just grabs from the beginning.
* @return All the recorded SoundData thus far.
**/
virtual love::sound::SoundData *getRecordedData() = 0;
/**
* Stops recording and, if passed true, returns all the recorded audio
* not already gotten by getRecordedData.
* @param returnData Whether to return recorded audio.
* @return if returnData, all the recorded audio yet to be gotten,
* otherwise NULL.
**/
virtual love::sound::SoundData *stopRecording(bool returnData) = 0;
/**
* Checks whether LOVE is able to record audio input.
* @return hasMic Whether LOVE has a microphone enabled.
**/
virtual bool canRecord() = 0;
/**
* Gets the distance model used for attenuation.
* @return Distance model.
*/
virtual DistanceModel getDistanceModel() const = 0;
/**
* Sets the distance model used for attenuation.
* @param distanceModel Distance model.
*/
virtual void setDistanceModel(DistanceModel distanceModel) = 0;
private:
static StringMap<DistanceModel, DISTANCE_MAX_ENUM>::Entry distanceModelEntries[];
static StringMap<DistanceModel, DISTANCE_MAX_ENUM> distanceModels;
}; // Audio
} // audio
} // love
#endif // LOVE_AUDIO_AUDIO_H
+74
View File
@@ -0,0 +1,74 @@
/**
* Copyright (c) 2006-2013 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"
namespace love
{
namespace audio
{
Source::Source(Type type)
: type(type)
{
}
Source::~Source()
{
}
bool Source::getConstant(const char *in, Type &out)
{
return types.find(in, out);
}
bool Source::getConstant(Type in, const char *&out)
{
return types.find(in, out);
}
bool Source::getConstant(const char *in, Unit &out)
{
return units.find(in, out);
}
bool Source::getConstant(Unit in, const char *&out)
{
return units.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));
StringMap<Source::Unit, Source::UNIT_MAX_ENUM>::Entry Source::unitEntries[] =
{
{"seconds", Source::UNIT_SECONDS},
{"samples", Source::UNIT_SAMPLES},
};
StringMap<Source::Unit, Source::UNIT_MAX_ENUM> Source::units(Source::unitEntries, sizeof(Source::unitEntries));
} // audio
} // love
+127
View File
@@ -0,0 +1,127 @@
/**
* Copyright (c) 2006-2013 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_SOURCE_H
#define LOVE_AUDIO_SOURCE_H
// LOVE
#include "common/Object.h"
#include "common/StringMap.h"
namespace love
{
namespace audio
{
class Source : public Object
{
public:
enum Type
{
TYPE_STATIC = 1,
TYPE_STREAM,
TYPE_MAX_ENUM
}; // Type
enum Unit
{
UNIT_SECONDS = 1,
UNIT_SAMPLES,
UNIT_MAX_ENUM
};
Source(Type type);
virtual ~Source();
virtual Source *copy() = 0;
virtual void play() = 0;
virtual void stop() = 0;
virtual void pause() = 0;
virtual void resume() = 0;
virtual void rewind() = 0;
virtual bool isStopped() const = 0;
virtual bool isPaused() const = 0;
virtual bool isFinished() const = 0;
virtual bool update() = 0;
virtual void setPitch(float pitch) = 0;
virtual float getPitch() const = 0;
virtual void setVolume(float volume) = 0;
virtual float getVolume() const = 0;
virtual void seek(float offset, Unit unit) = 0;
virtual float tell(Unit unit) = 0;
// all float * v must be of size 3
virtual void setPosition(float *v) = 0;
virtual void getPosition(float *v) const = 0;
virtual void setVelocity(float *v) = 0;
virtual void getVelocity(float *v) const = 0;
virtual void setDirection(float *v) = 0;
virtual void getDirection(float *v) const = 0;
virtual void setCone(float innerAngle, float outerAngle, float outerVolume) = 0;
virtual void getCone(float &innerAngle, float &outerAngle, float &outerVolume) const = 0;
virtual void setRelative(bool enable) = 0;
virtual bool isRelative() const = 0;
virtual void setLooping(bool looping) = 0;
virtual bool isLooping() const = 0;
virtual bool isStatic() const = 0;
virtual void setMinVolume(float volume) = 0;
virtual float getMinVolume() const = 0;
virtual void setMaxVolume(float volume) = 0;
virtual float getMaxVolume() const = 0;
virtual void setReferenceDistance(float distance) = 0;
virtual float getReferenceDistance() const = 0;
virtual void setRolloffFactor(float factor) = 0;
virtual float getRolloffFactor() const = 0;
virtual void setMaxDistance(float distance) = 0;
virtual float getMaxDistance() const = 0;
virtual int getChannels() const = 0;
static bool getConstant(const char *in, Type &out);
static bool getConstant(Type in, const char *&out);
static bool getConstant(const char *in, Unit &out);
static bool getConstant(Unit in, const char *&out);
protected:
Type type;
private:
static StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[];
static StringMap<Type, TYPE_MAX_ENUM> types;
static StringMap<Unit, UNIT_MAX_ENUM>::Entry unitEntries[];
static StringMap<Unit, UNIT_MAX_ENUM> units;
}; // Source
} // audio
} // love
#endif // LOVE_AUDIO_SOURCE_H
+169
View File
@@ -0,0 +1,169 @@
/**
* Copyright (c) 2006-2013 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 null
{
Audio::Audio()
: distanceModel(DISTANCE_NONE)
{
}
Audio::~Audio()
{
}
const char *Audio::getName() const
{
return "love.audio.null";
}
love::audio::Source *Audio::newSource(love::sound::Decoder *)
{
return new Source();
}
love::audio::Source *Audio::newSource(love::sound::SoundData *)
{
return new Source();
}
int Audio::getSourceCount() const
{
return 0;
}
int Audio::getMaxSources() const
{
return 0;
}
void Audio::play(love::audio::Source *)
{
}
void Audio::play()
{
}
void Audio::stop(love::audio::Source *)
{
}
void Audio::stop()
{
}
void Audio::pause(love::audio::Source *)
{
}
void Audio::pause()
{
}
void Audio::resume(love::audio::Source *)
{
}
void Audio::resume()
{
}
void Audio::rewind(love::audio::Source *)
{
}
void Audio::rewind()
{
}
void Audio::setVolume(float volume)
{
this->volume = volume;
}
float Audio::getVolume() const
{
return volume;
}
void Audio::getPosition(float *) const
{
}
void Audio::setPosition(float *)
{
}
void Audio::getOrientation(float *) const
{
}
void Audio::setOrientation(float *)
{
}
void Audio::getVelocity(float *) const
{
}
void Audio::setVelocity(float *)
{
}
void Audio::record()
{
}
love::sound::SoundData *Audio::getRecordedData()
{
return NULL;
}
love::sound::SoundData *Audio::stopRecording(bool)
{
return NULL;
}
bool Audio::canRecord()
{
return false;
}
Audio::DistanceModel Audio::getDistanceModel() const
{
return this->distanceModel;
}
void Audio::setDistanceModel(DistanceModel distanceModel)
{
this->distanceModel = distanceModel;
}
} // null
} // audio
} // love
+89
View File
@@ -0,0 +1,89 @@
/**
* Copyright (c) 2006-2013 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_AUDIO_H
#define LOVE_AUDIO_NULL_AUDIO_H
// LOVE
#include "audio/Audio.h"
#include "Source.h"
namespace love
{
namespace audio
{
namespace null
{
class Audio : public love::audio::Audio
{
public:
Audio();
virtual ~Audio();
// Implements Module.
const char *getName() const;
// Implements Audio.
love::audio::Source *newSource(love::sound::Decoder *decoder);
love::audio::Source *newSource(love::sound::SoundData *soundData);
int getSourceCount() const;
int getMaxSources() const;
void play(love::audio::Source *source);
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;
void getPosition(float *v) const;
void setPosition(float *v);
void getOrientation(float *v) const;
void setOrientation(float *v);
void getVelocity(float *v) const;
void setVelocity(float *v);
void record();
love::sound::SoundData *getRecordedData();
love::sound::SoundData *stopRecording(bool returnData);
bool canRecord();
DistanceModel getDistanceModel() const;
void setDistanceModel(DistanceModel distanceModel);
private:
float volume;
DistanceModel distanceModel;
}; // Audio
} // null
} // audio
} // love
#endif // LOVE_AUDIO_NULL_AUDIO_H
+234
View File
@@ -0,0 +1,234 @@
/**
* Copyright (c) 2006-2013 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"
namespace love
{
namespace audio
{
namespace null
{
Source::Source()
: love::audio::Source(Source::TYPE_STATIC)
{
}
Source::~Source()
{
}
love::audio::Source *Source::copy()
{
this->retain();
return this;
}
void Source::play()
{
}
void Source::stop()
{
}
void Source::pause()
{
}
void Source::resume()
{
}
void Source::rewind()
{
}
bool Source::isStopped() const
{
return true;
}
bool Source::isPaused() const
{
return false;
}
bool Source::isFinished() const
{
return true;
}
bool Source::update()
{
return false;
}
void Source::setPitch(float pitch)
{
this->pitch = pitch;
}
float Source::getPitch() const
{
return pitch;
}
void Source::setVolume(float volume)
{
this->volume = volume;
}
float Source::getVolume() const
{
return volume;
}
void Source::seek(float, Source::Unit)
{
}
float Source::tell(Source::Unit)
{
return 0.0f;
}
void Source::setPosition(float *)
{
}
void Source::getPosition(float *) const
{
}
void Source::setVelocity(float *)
{
}
void Source::getVelocity(float *) const
{
}
void Source::setDirection(float *)
{
}
void Source::getDirection(float *) const
{
}
void Source::setCone(float innerAngle, float outerAngle, float outerVolume)
{
coneInnerAngle = innerAngle;
coneOuterAngle = outerAngle;
coneOuterVolume = outerVolume;
}
void Source::getCone(float &innerAngle, float &outerAngle, float &outerVolume) const
{
innerAngle = coneInnerAngle;
outerAngle = coneOuterAngle;
outerVolume = coneOuterVolume;
}
void Source::setRelative(bool enable)
{
relative = enable;
}
bool Source::isRelative() const
{
return relative;
}
void Source::setLooping(bool looping)
{
this->looping = looping;
}
bool Source::isLooping() const
{
return looping;
}
bool Source::isStatic() const
{
return (type == TYPE_STATIC);
}
void Source::setMinVolume(float volume)
{
this->minVolume = volume;
}
float Source::getMinVolume() const
{
return this->minVolume;
}
void Source::setMaxVolume(float volume)
{
this->maxVolume = volume;
}
float Source::getMaxVolume() const
{
return this->maxVolume;
}
void Source::setReferenceDistance(float distance)
{
this->referenceDistance = distance;
}
float Source::getReferenceDistance() const
{
return this->referenceDistance;
}
void Source::setRolloffFactor(float factor)
{
this->rolloffFactor = factor;
}
float Source::getRolloffFactor() const
{
return this->rolloffFactor;
}
void Source::setMaxDistance(float distance)
{
this->maxDistance = distance;
}
float Source::getMaxDistance() const
{
return this->maxDistance;
}
int Source::getChannels() const
{
return 2;
}
} // null
} // audio
} // love
+103
View File
@@ -0,0 +1,103 @@
/**
* Copyright (c) 2006-2013 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_SOURCE_H
#define LOVE_AUDIO_NULL_SOURCE_H
// LOVE
#include "common/Object.h"
#include "audio/Source.h"
namespace love
{
namespace audio
{
namespace null
{
class Source : public love::audio::Source
{
public:
Source();
virtual ~Source();
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 isPaused() const;
virtual bool isFinished() const;
virtual bool update();
virtual void setPitch(float pitch);
virtual float getPitch() const;
virtual void setVolume(float volume);
virtual float getVolume() const;
virtual void seek(float offset, Unit unit);
virtual float tell(Unit unit);
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;
virtual void setCone(float innerAngle, float outerAngle, float outerVolume);
virtual void getCone(float &innerAngle, float &outerAngle, float &outerVolume) const;
virtual void setRelative(bool enable);
virtual bool isRelative() const;
void setLooping(bool looping);
bool isLooping() const;
bool isStatic() const;
virtual void setMinVolume(float volume);
virtual float getMinVolume() const;
virtual void setMaxVolume(float volume);
virtual float getMaxVolume() const;
virtual void setReferenceDistance(float distance);
virtual float getReferenceDistance() const;
virtual void setRolloffFactor(float factor);
virtual float getRolloffFactor() const;
virtual void setMaxDistance(float distance);
virtual float getMaxDistance() const;
virtual int getChannels() const;
private:
float pitch;
float volume;
float coneInnerAngle;
float coneOuterAngle;
float coneOuterVolume;
bool relative;
bool looping;
float minVolume;
float maxVolume;
float referenceDistance;
float rolloffFactor;
float maxDistance;
}; // Source
} // null
} // audio
} // love
#endif // LOVE_AUDIO_NULL_SOURCE_H
+328
View File
@@ -0,0 +1,328 @@
/**
* Copyright (c) 2006-2013 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"
#include "common/delay.h"
#include "sound/Decoder.h"
#include <cstdlib>
namespace love
{
namespace audio
{
namespace openal
{
Audio::PoolThread::PoolThread(Pool *pool)
: pool(pool)
, finish(false)
{
mutex = thread::newMutex();
}
Audio::PoolThread::~PoolThread()
{
delete mutex;
}
void Audio::PoolThread::threadFunction()
{
while (true)
{
{
thread::Lock lock(mutex);
if (finish)
{
return;
}
}
pool->update();
delay(5);
}
}
void Audio::PoolThread::setFinish()
{
thread::Lock lock(mutex);
finish = true;
}
Audio::Audio()
: distanceModel(DISTANCE_INVERSE_CLAMPED)
{
// Passing zero for default device.
device = alcOpenDevice(0);
if (device == 0)
throw love::Exception("Could not open device.");
context = alcCreateContext(device, 0);
if (context == 0)
throw love::Exception("Could not create context.");
alcMakeContextCurrent(context);
if (alcGetError(device) != ALC_NO_ERROR)
throw love::Exception("Could not make context current.");
/*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
const ALCchar * devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
while (*devices)
{
std::string device(devices);
devices += device.size() + 1;
if (device.find("Mic") != std::string::npos || device.find("mic") != std::string::npos)
{
captureName = device;
}
}
capture = alcCaptureOpenDevice(captureName.c_str(), 8000, AL_FORMAT_MONO16, 262144); // about 32 seconds
if (!capture)
{
// We're not going to prevent LOVE from running without a microphone, but we should warn, at least
std::cerr << "Warning, couldn't open capture device! No audio input!" << std::endl;
}*/
// pool must be allocated after AL context.
pool = new Pool();
poolThread = new PoolThread(pool);
poolThread->start();
}
Audio::~Audio()
{
poolThread->setFinish();
poolThread->wait();
delete poolThread;
delete pool;
alcMakeContextCurrent(0);
alcDestroyContext(context);
//if (capture) alcCaptureCloseDevice(capture);
alcCloseDevice(device);
}
const char *Audio::getName() const
{
return "love.audio.openal";
}
love::audio::Source *Audio::newSource(love::sound::Decoder *decoder)
{
return new Source(pool, decoder);
}
love::audio::Source *Audio::newSource(love::sound::SoundData *soundData)
{
return new Source(pool, soundData);
}
int Audio::getSourceCount() const
{
return pool->getSourceCount();
}
int Audio::getMaxSources() const
{
return pool->getMaxSources();
}
void Audio::play(love::audio::Source *source)
{
source->play();
}
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;
}
void Audio::getPosition(float *v) const
{
alGetListenerfv(AL_POSITION, v);
}
void Audio::setPosition(float *v)
{
alListenerfv(AL_POSITION, v);
}
void Audio::getOrientation(float *v) const
{
alGetListenerfv(AL_ORIENTATION, v);
}
void Audio::setOrientation(float *v)
{
alListenerfv(AL_ORIENTATION, v);
}
void Audio::getVelocity(float *v) const
{
alGetListenerfv(AL_VELOCITY, v);
}
void Audio::setVelocity(float *v)
{
alListenerfv(AL_VELOCITY, v);
}
void Audio::record()
{
if (!canRecord()) return;
alcCaptureStart(capture);
}
love::sound::SoundData *Audio::getRecordedData()
{
if (!canRecord())
return NULL;
int samplerate = 8000;
ALCint samples;
alcGetIntegerv(capture, ALC_CAPTURE_SAMPLES, 4, &samples);
void *data = malloc(samples * (2/sizeof(char)));
alcCaptureSamples(capture, data, samples);
love::sound::SoundData *sd = new love::sound::SoundData(data, samples, samplerate, 16, 1);
free(data);
return sd;
}
love::sound::SoundData *Audio::stopRecording(bool returnData)
{
if (!canRecord())
return NULL;
love::sound::SoundData *sd = NULL;
if (returnData)
{
sd = getRecordedData();
}
alcCaptureStop(capture);
return sd;
}
bool Audio::canRecord()
{
return (capture != NULL);
}
Audio::DistanceModel Audio::getDistanceModel() const
{
return this->distanceModel;
}
void Audio::setDistanceModel(DistanceModel distanceModel)
{
this->distanceModel = distanceModel;
switch (distanceModel)
{
case DISTANCE_NONE:
alDistanceModel(AL_NONE);
break;
case DISTANCE_INVERSE:
alDistanceModel(AL_INVERSE_DISTANCE);
break;
case DISTANCE_INVERSE_CLAMPED:
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
break;
case DISTANCE_LINEAR:
alDistanceModel(AL_LINEAR_DISTANCE);
break;
case DISTANCE_LINEAR_CLAMPED:
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
break;
case DISTANCE_EXPONENT:
alDistanceModel(AL_EXPONENT_DISTANCE);
break;
case DISTANCE_EXPONENT_CLAMPED:
alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
break;
default:
break;
}
}
} // openal
} // audio
} // love
+142
View File
@@ -0,0 +1,142 @@
/**
* Copyright (c) 2006-2013 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>
// LOVE
#include "audio/Audio.h"
#include "common/config.h"
#include "sound/SoundData.h"
#include "Source.h"
#include "Pool.h"
#include "thread/threads.h"
// OpenAL
#ifdef LOVE_MACOSX
#include <OpenAL-Soft/alc.h>
#include <OpenAL-Soft/al.h>
#else
#include <AL/alc.h>
#include <AL/al.h>
#endif
namespace love
{
namespace audio
{
namespace openal
{
class Audio : public love::audio::Audio
{
public:
Audio();
~Audio();
// Implements Module.
const char *getName() const;
// Implements Audio.
love::audio::Source *newSource(love::sound::Decoder *decoder);
love::audio::Source *newSource(love::sound::SoundData *soundData);
int getSourceCount() const;
int getMaxSources() const;
void play(love::audio::Source *source);
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;
void getPosition(float *v) const;
void setPosition(float *v);
void getOrientation(float *v) const;
void setOrientation(float *v);
void getVelocity(float *v) const;
void setVelocity(float *v);
void record();
love::sound::SoundData *getRecordedData();
love::sound::SoundData *stopRecording(bool returnData);
bool canRecord();
DistanceModel getDistanceModel() const;
void setDistanceModel(DistanceModel distanceModel);
private:
// The OpenAL device.
ALCdevice *device;
// The OpenAL capture device (microphone).
ALCdevice *capture;
// The OpenAL context.
ALCcontext *context;
// The Pool.
Pool *pool;
class PoolThread: public thread::Threadable
{
protected:
Pool *pool;
// Set this to true when the thread should finish.
// Main thread will write to this value, and PoolThread
// will read from it.
volatile bool finish;
// finish lock
thread::Mutex *mutex;
public:
PoolThread(Pool *pool);
~PoolThread();
void setFinish();
void threadFunction();
};
PoolThread *poolThread;
DistanceModel distanceModel;
}; // Audio
} // openal
} // audio
} // love
#endif // LOVE_AUDIO_OPENAL_AUDIO_H
+293
View File
@@ -0,0 +1,293 @@
/**
* Copyright (c) 2006-2013 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"
#include "Source.h"
namespace love
{
namespace audio
{
namespace openal
{
Pool::Pool()
{
// Generate sources.
alGenSources(NUM_SOURCES, sources);
// Create the mutex.
mutex = thread::newMutex();
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++)
{
#ifdef AL_DIRECT_CHANNELS_SOFT
// Bypassing virtualization of speakers for multi-channel sources in OpenAL Soft.
alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
#endif
available.push(sources[i]);
}
}
Pool::~Pool()
{
stop();
delete mutex;
// Free all sources.
alDeleteSources(NUM_SOURCES, sources);
}
bool Pool::isAvailable() const
{
bool has = false;
{
thread::Lock lock(mutex);
has = !available.empty();
}
return has;
}
bool Pool::isPlaying(Source *s)
{
bool p = false;
{
thread::Lock lock(mutex);
for (auto i = playing.begin(); i != playing.end(); i++)
{
if (i->first == s)
p = true;
}
}
return p;
}
void Pool::update()
{
thread::Lock lock(mutex);
std::map<Source *, ALuint>::iterator i = playing.begin();
while (i != playing.end())
{
if (!i->first->update())
{
i->first->stopAtomic();
i->first->rewindAtomic();
i->first->release();
available.push(i->second);
playing.erase(i++);
}
else
i++;
}
}
int Pool::getSourceCount() const
{
return playing.size();
}
int Pool::getMaxSources() const
{
return NUM_SOURCES;
}
bool Pool::play(Source *source, ALuint &out)
{
thread::Lock lock(mutex);
bool ok = true;
out = 0;
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;
}
return ok;
}
void Pool::stop()
{
thread::Lock lock(mutex);
for (auto i = playing.begin(); i != playing.end(); i++)
{
i->first->stopAtomic();
i->first->release();
available.push(i->second);
}
playing.clear();
}
void Pool::stop(Source *source)
{
thread::Lock lock(mutex);
removeSource(source);
}
void Pool::pause()
{
thread::Lock lock(mutex);
for (auto i = playing.begin(); i != playing.end(); i++)
i->first->pauseAtomic();
}
void Pool::pause(Source *source)
{
thread::Lock lock(mutex);
ALuint out;
if (findSource(source, out))
source->pauseAtomic();
}
void Pool::resume()
{
thread::Lock lock(mutex);
for (auto i = playing.begin(); i != playing.end(); i++)
i->first->resumeAtomic();
}
void Pool::resume(Source *source)
{
thread::Lock lock(mutex);
ALuint out;
if (findSource(source, out))
source->resumeAtomic();
}
void Pool::rewind()
{
thread::Lock lock(mutex);
for (auto i = playing.begin(); i != playing.end(); i++)
i->first->rewindAtomic();
}
// For those times we don't need it backed.
void Pool::softRewind(Source *source)
{
thread::Lock lock(mutex);
source->rewindAtomic();
}
void Pool::rewind(Source *source)
{
thread::Lock lock(mutex);
source->rewindAtomic();
}
void Pool::release(Source *source)
{
ALuint s = findi(source);
if (s != 0)
{
available.push(s);
playing.erase(source);
}
}
void Pool::seek(Source *source, float offset, void *unit)
{
thread::Lock lock(mutex);
return source->seekAtomic(offset, unit);
}
float Pool::tell(Source *source, void *unit)
{
thread::Lock lock(mutex);
return source->tellAtomic(unit);
}
ALuint Pool::findi(const Source *source) const
{
std::map<Source *, ALuint>::const_iterator i = playing.find((Source *)source);
if (i != playing.end())
return i->second;
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>::iterator i = playing.find((Source *)source);
if (i != playing.end())
{
source->stopAtomic();
available.push(i->second);
playing.erase(i++);
source->release();
return true;
}
return false;
}
} // openal
} // audio
} // love
+124
View File
@@ -0,0 +1,124 @@
/**
* Copyright (c) 2006-2013 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>
// LOVE
#include "common/config.h"
#include "common/Exception.h"
#include "thread/threads.h"
// OpenAL
#ifdef LOVE_MACOSX
#include <OpenAL-Soft/alc.h>
#include <OpenAL-Soft/al.h>
#else
#include <AL/alc.h>
#include <AL/al.h>
#include <AL/alext.h>
#endif
namespace love
{
namespace audio
{
namespace openal
{
class Source;
class Pool
{
public:
Pool();
~Pool();
/**
* 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(Source *s);
void update();
int getSourceCount() 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);
void softRewind(Source *source);
void seek(Source *source, float offset, void *unit);
float tell(Source *source, void *unit);
private:
/**
* Makes the specified OpenAL source available for use.
* @param source The OpenAL source.
**/
void release(Source *source);
ALuint findi(const Source *source) const;
bool findSource(Source *source, ALuint &out);
bool removeSource(Source *source);
// Number of OpenAL sources.
static const int NUM_SOURCES = 64;
// OpenAL sources
ALuint sources[NUM_SOURCES];
// A queue of available sources.
std::queue<ALuint> available;
// A map of playing sources.
std::map<Source *, ALuint> playing;
// Only one thread can access this object at the same time. This mutex will
// make sure of that.
thread::Mutex *mutex;
}; // Pool
} // openal
} // audio
} // love
#endif // LOVE_AUDIO_OPENAL_POOL_H
@@ -0,0 +1,766 @@
/**
* Copyright (c) 2006-2013 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"
#include "Pool.h"
#include "common/math.h"
// STD
#include <iostream>
#include <float.h>
namespace love
{
namespace audio
{
namespace openal
{
Source::Source(Pool *pool, love::sound::SoundData *soundData)
: love::audio::Source(Source::TYPE_STATIC)
, pool(pool)
, valid(false)
, pitch(1.0f)
, volume(1.0f)
, relative(false)
, looping(false)
, paused(false)
, minVolume(0.0f)
, maxVolume(1.0f)
, referenceDistance(1.0f)
, rolloffFactor(1.0f)
, maxDistance(FLT_MAX)
, cone()
, offsetSamples(0)
, offsetSeconds(0)
, channels(soundData->getChannels())
, decoder(0)
, toLoop(0)
{
alGenBuffers(1, buffers);
ALenum fmt = getFormat(soundData->getChannels(), soundData->getBitDepth());
alBufferData(buffers[0], fmt, soundData->getData(), soundData->getSize(), soundData->getSampleRate());
static float z[3] = {0, 0, 0};
setFloatv(position, z);
setFloatv(velocity, z);
setFloatv(direction, z);
}
Source::Source(Pool *pool, love::sound::Decoder *decoder)
: love::audio::Source(Source::TYPE_STREAM)
, pool(pool)
, valid(false)
, pitch(1.0f)
, volume(1.0f)
, relative(false)
, looping(false)
, paused(false)
, minVolume(0.0f)
, maxVolume(1.0f)
, referenceDistance(1.0f)
, rolloffFactor(1.0f)
, maxDistance(FLT_MAX)
, cone()
, offsetSamples(0)
, offsetSeconds(0)
, channels(decoder->getChannels())
, decoder(decoder)
, toLoop(0)
{
decoder->retain();
alGenBuffers(MAX_BUFFERS, buffers);
static float z[3] = {0, 0, 0};
setFloatv(position, z);
setFloatv(velocity, z);
setFloatv(direction, z);
}
Source::~Source()
{
if (valid)
pool->stop(this);
alDeleteBuffers((type == TYPE_STATIC) ? 1 : MAX_BUFFERS, buffers);
if (decoder)
decoder->release();
}
love::audio::Source *Source::copy()
{
return 0;
}
void Source::play()
{
if (valid && paused)
{
pool->resume(this);
return;
}
valid = pool->play(this, source);
}
void Source::stop()
{
if (!isStopped())
{
pool->stop(this);
pool->softRewind(this);
}
}
void Source::pause()
{
pool->pause(this);
}
void Source::resume()
{
pool->resume(this);
}
void Source::rewind()
{
pool->rewind(this);
}
bool Source::isStopped() const
{
if (valid)
{
ALenum state;
alGetSourcei(source, AL_SOURCE_STATE, &state);
return (state == AL_STOPPED);
}
return true;
}
bool Source::isPaused() const
{
if (valid)
{
ALenum state;
alGetSourcei(source, AL_SOURCE_STATE, &state);
return (state == AL_PAUSED);
}
return false;
}
bool Source::isFinished() const
{
return type == TYPE_STATIC ? isStopped() : isStopped() && !isLooping() && decoder->isFinished();
}
bool Source::update()
{
if (!valid)
return false;
if (type == TYPE_STATIC)
{
// Looping mode could have changed.
alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
return !isStopped();
}
else if (type == TYPE_STREAM && (isLooping() || !isFinished()))
{
// Number of processed buffers.
ALint processed = 0;
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
while (processed--)
{
ALuint buffer;
float curOffsetSamples, curOffsetSecs;
alGetSourcef(source, AL_SAMPLE_OFFSET, &curOffsetSamples);
ALint b;
alGetSourcei(source, AL_BUFFER, &b);
int freq;
alGetBufferi(b, AL_FREQUENCY, &freq);
curOffsetSecs = curOffsetSamples / freq;
// Get a free buffer.
alSourceUnqueueBuffers(source, 1, &buffer);
float newOffsetSamples, newOffsetSecs;
alGetSourcef(source, AL_SAMPLE_OFFSET, &newOffsetSamples);
newOffsetSecs = newOffsetSamples / freq;
offsetSamples += (curOffsetSamples - newOffsetSamples);
offsetSeconds += (curOffsetSecs - newOffsetSecs);
streamAtomic(buffer, decoder);
alSourceQueueBuffers(source, 1, &buffer);
}
return true;
}
return false;
}
void Source::setPitch(float pitch)
{
if (valid)
alSourcef(source, AL_PITCH, pitch);
this->pitch = pitch;
}
float Source::getPitch() const
{
if (valid)
{
ALfloat f;
alGetSourcef(source, AL_PITCH, &f);
return f;
}
// In case the Source isn't playing.
return pitch;
}
void Source::setVolume(float volume)
{
if (valid)
{
alSourcef(source, AL_GAIN, volume);
}
this->volume = volume;
}
float Source::getVolume() const
{
if (valid)
{
ALfloat f;
alGetSourcef(source, AL_GAIN, &f);
return f;
}
// In case the Source isn't playing.
return volume;
}
void Source::seekAtomic(float offset, void *unit)
{
if (valid)
{
switch (*((Source::Unit *) unit))
{
case Source::UNIT_SAMPLES:
if (type == TYPE_STREAM)
{
offsetSamples = offset;
ALint buffer;
alGetSourcei(source, AL_BUFFER, &buffer);
int freq;
alGetBufferi(buffer, AL_FREQUENCY, &freq);
offset /= freq;
offsetSeconds = offset;
decoder->seek(offset);
}
else
{
alSourcef(source, AL_SAMPLE_OFFSET, offset);
}
break;
case Source::UNIT_SECONDS:
default:
if (type == TYPE_STREAM)
{
offsetSeconds = offset;
decoder->seek(offset);
ALint buffer;
alGetSourcei(source, AL_BUFFER, &buffer);
int freq;
alGetBufferi(buffer, AL_FREQUENCY, &freq);
offsetSamples = offset*freq;
}
else
{
alSourcef(source, AL_SEC_OFFSET, offset);
}
break;
}
if (type == TYPE_STREAM)
{
bool waspaused = paused;
// Because we still have old data
// from before the seek in the buffers
// let's empty them.
stopAtomic();
playAtomic();
if (waspaused)
pauseAtomic();
}
}
}
void Source::seek(float offset, Source::Unit unit)
{
return pool->seek(this, offset, &unit);
}
float Source::tellAtomic(void *unit) const
{
if (valid)
{
float offset;
switch (*((Source::Unit *) unit))
{
case Source::UNIT_SAMPLES:
alGetSourcef(source, AL_SAMPLE_OFFSET, &offset);
if (type == TYPE_STREAM) offset += offsetSamples;
break;
case Source::UNIT_SECONDS:
default:
alGetSourcef(source, AL_SAMPLE_OFFSET, &offset);
ALint buffer;
alGetSourcei(source, AL_BUFFER, &buffer);
int freq;
alGetBufferi(buffer, AL_FREQUENCY, &freq);
offset /= freq;
if (type == TYPE_STREAM) offset += offsetSeconds;
break;
}
return offset;
}
return 0.0f;
}
float Source::tell(Source::Unit unit)
{
return pool->tell(this, &unit);
}
void Source::setPosition(float *v)
{
if (valid)
alSourcefv(source, AL_POSITION, v);
setFloatv(position, v);
}
void Source::getPosition(float *v) const
{
if (valid)
alGetSourcefv(source, AL_POSITION, v);
else
setFloatv(v, position);
}
void Source::setVelocity(float *v)
{
if (valid)
alSourcefv(source, AL_VELOCITY, v);
setFloatv(velocity, v);
}
void Source::getVelocity(float *v) const
{
if (valid)
alGetSourcefv(source, AL_VELOCITY, v);
else
setFloatv(v, velocity);
}
void Source::setDirection(float *v)
{
if (valid)
alSourcefv(source, AL_DIRECTION, v);
else
setFloatv(direction, v);
}
void Source::getDirection(float *v) const
{
if (valid)
alGetSourcefv(source, AL_DIRECTION, v);
else
setFloatv(v, direction);
}
void Source::setCone(float innerAngle, float outerAngle, float outerVolume)
{
cone.innerAngle = LOVE_TODEG(innerAngle);
cone.outerAngle = LOVE_TODEG(outerAngle);
cone.outerVolume = outerVolume;
if (valid)
{
alSourcei(source, AL_CONE_INNER_ANGLE, cone.innerAngle);
alSourcei(source, AL_CONE_OUTER_ANGLE, cone.outerAngle);
alSourcef(source, AL_CONE_OUTER_GAIN, cone.outerVolume);
}
}
void Source::getCone(float &innerAngle, float &outerAngle, float &outerVolume) const
{
innerAngle = LOVE_TORAD(cone.innerAngle);
outerAngle = LOVE_TORAD(cone.outerAngle);
outerVolume = cone.outerVolume;
}
void Source::setRelative(bool enable)
{
if (valid)
alSourcei(source, AL_SOURCE_RELATIVE, relative ? AL_TRUE : AL_FALSE);
relative = enable;
}
bool Source::isRelative() const
{
return relative;
}
void Source::setLooping(bool looping)
{
if (valid && type == TYPE_STATIC)
alSourcei(source, AL_LOOPING, looping ? AL_TRUE : AL_FALSE);
this->looping = looping;
}
bool Source::isLooping() const
{
return looping;
}
void Source::playAtomic()
{
if (type == TYPE_STATIC)
{
alSourcei(source, AL_BUFFER, buffers[0]);
}
else if (type == TYPE_STREAM)
{
int usedBuffers = 0;
for (unsigned int i = 0; i < MAX_BUFFERS; i++)
{
streamAtomic(buffers[i], decoder);
++usedBuffers;
if (decoder->isFinished())
break;
}
if (usedBuffers > 0)
alSourceQueueBuffers(source, usedBuffers, buffers);
}
// This Source may now be associated with an OpenAL source that still has
// the properties of another love Source. Let's reset it to the settings
// of the new one.
reset();
alSourcePlay(source);
valid = true; //if it fails it will be set to false again
//but this prevents a horrible, horrible bug
}
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);
}
}
alSourcei(source, AL_BUFFER, AL_NONE);
}
toLoop = 0;
valid = false;
}
void Source::pauseAtomic()
{
if (valid)
{
alSourcePause(source);
paused = true;
}
}
void Source::resumeAtomic()
{
if (valid && paused)
{
alSourcePlay(source);
paused = false;
}
}
void Source::rewindAtomic()
{
if (valid && type == TYPE_STATIC)
{
alSourceRewind(source);
if (!paused)
alSourcePlay(source);
}
else if (valid && type == TYPE_STREAM)
{
bool waspaused = paused;
decoder->rewind();
// Because we still have old data
// from before the seek in the buffers
// let's empty them.
stopAtomic();
playAtomic();
if (waspaused)
pauseAtomic();
offsetSamples = 0;
offsetSeconds = 0;
}
else if (type == TYPE_STREAM)
{
decoder->rewind();
offsetSamples = 0;
offsetSeconds = 0;
}
}
void Source::reset()
{
alSourcefv(source, AL_POSITION, position);
alSourcefv(source, AL_VELOCITY, velocity);
alSourcefv(source, AL_DIRECTION, direction);
alSourcef(source, AL_PITCH, pitch);
alSourcef(source, AL_GAIN, volume);
alSourcef(source, AL_MIN_GAIN, minVolume);
alSourcef(source, AL_MAX_GAIN, maxVolume);
alSourcef(source, AL_REFERENCE_DISTANCE, referenceDistance);
alSourcef(source, AL_ROLLOFF_FACTOR, rolloffFactor);
alSourcef(source, AL_MAX_DISTANCE, maxDistance);
alSourcei(source, AL_LOOPING, isStatic() && isLooping() ? AL_TRUE : AL_FALSE);
alSourcei(source, AL_SOURCE_RELATIVE, relative ? AL_TRUE : AL_FALSE);
alSourcei(source, AL_CONE_INNER_ANGLE, cone.innerAngle);
alSourcei(source, AL_CONE_OUTER_ANGLE, cone.outerAngle);
alSourcef(source, AL_CONE_OUTER_GAIN, cone.outerVolume);
}
void Source::setFloatv(float *dst, const float *src) const
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
}
ALenum Source::getFormat(int channels, int bitDepth) const
{
if (channels == 1 && bitDepth == 8)
return AL_FORMAT_MONO8;
else if (channels == 1 && bitDepth == 16)
return AL_FORMAT_MONO16;
else if (channels == 2 && bitDepth == 8)
return AL_FORMAT_STEREO8;
else if (channels == 2 && bitDepth == 16)
return AL_FORMAT_STEREO16;
else
return 0;
}
int Source::streamAtomic(ALuint buffer, love::sound::Decoder *d)
{
// Get more sound data.
int decoded = d->decode();
int fmt = getFormat(d->getChannels(), d->getBitDepth());
if (fmt != 0)
alBufferData(buffer, fmt, d->getBuffer(), decoded, d->getSampleRate());
if (decoder->isFinished() && isLooping())
{
int queued, processed;
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
if (queued > processed)
toLoop = queued-processed;
else
toLoop = MAX_BUFFERS-processed;
d->rewind();
}
if (toLoop > 0)
{
if (--toLoop == 0)
{
offsetSamples = 0;
offsetSeconds = 0;
}
}
return decoded;
}
bool Source::isStatic() const
{
return (type == TYPE_STATIC);
}
void Source::setMinVolume(float volume)
{
if (valid)
{
alSourcef(source, AL_MIN_GAIN, volume);
}
this->minVolume = volume;
}
float Source::getMinVolume() const
{
if (valid)
{
ALfloat f;
alGetSourcef(source, AL_MIN_GAIN, &f);
return f;
}
// In case the Source isn't playing.
return this->minVolume;
}
void Source::setMaxVolume(float volume)
{
if (valid)
{
alSourcef(source, AL_MAX_GAIN, volume);
}
this->maxVolume = volume;
}
float Source::getMaxVolume() const
{
if (valid)
{
ALfloat f;
alGetSourcef(source, AL_MAX_GAIN, &f);
return f;
}
// In case the Source isn't playing.
return this->maxVolume;
}
void Source::setReferenceDistance(float distance)
{
if (valid)
{
alSourcef(source, AL_REFERENCE_DISTANCE, distance);
}
this->referenceDistance = distance;
}
float Source::getReferenceDistance() const
{
if (valid)
{
ALfloat f;
alGetSourcef(source, AL_REFERENCE_DISTANCE, &f);
return f;
}
// In case the Source isn't playing.
return this->referenceDistance;
}
void Source::setRolloffFactor(float factor)
{
if (valid)
{
alSourcef(source, AL_ROLLOFF_FACTOR, factor);
}
this->rolloffFactor = factor;
}
float Source::getRolloffFactor() const
{
if (valid)
{
ALfloat f;
alGetSourcef(source, AL_ROLLOFF_FACTOR, &f);
return f;
}
// In case the Source isn't playing.
return this->rolloffFactor;
}
void Source::setMaxDistance(float distance)
{
if (valid)
{
alSourcef(source, AL_MAX_DISTANCE, distance);
}
this->maxDistance = distance;
}
float Source::getMaxDistance() const
{
if (valid)
{
ALfloat f;
alGetSourcef(source, AL_MAX_DISTANCE, &f);
return f;
}
// In case the Source isn't playing.
return this->maxDistance;
}
int Source::getChannels() const
{
return channels;
}
} // openal
} // audio
} // love
+171
View File
@@ -0,0 +1,171 @@
/**
* Copyright (c) 2006-2013 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/config.h"
#include "common/Object.h"
#include "audio/Source.h"
#include "sound/SoundData.h"
#include "sound/Decoder.h"
// OpenAL
#ifdef LOVE_MACOSX
#include <OpenAL-Soft/alc.h>
#include <OpenAL-Soft/al.h>
#else
#include <AL/alc.h>
#include <AL/al.h>
#endif
namespace love
{
namespace audio
{
namespace openal
{
class Audio;
class Pool;
class Source : public love::audio::Source
{
public:
Source(Pool *pool, love::sound::SoundData *soundData);
Source(Pool *pool, love::sound::Decoder *decoder);
virtual ~Source();
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 isPaused() const;
virtual bool isFinished() const;
virtual bool update();
virtual void setPitch(float pitch);
virtual float getPitch() const;
virtual void setVolume(float volume);
virtual float getVolume() const;
virtual void seekAtomic(float offset, void *unit);
virtual void seek(float offset, Unit unit);
virtual float tellAtomic(void *unit) const;
virtual float tell(Unit unit);
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;
virtual void setCone(float innerAngle, float outerAngle, float outerVolume);
virtual void getCone(float &innerAngle, float &outerAngle, float &outerVolume) const;
virtual void setRelative(bool enable);
virtual bool isRelative() const;
void setLooping(bool looping);
bool isLooping() const;
bool isStatic() const;
virtual void setMinVolume(float volume);
virtual float getMinVolume() const;
virtual void setMaxVolume(float volume);
virtual float getMaxVolume() const;
virtual void setReferenceDistance(float distance);
virtual float getReferenceDistance() const;
virtual void setRolloffFactor(float factor);
virtual float getRolloffFactor() const;
virtual void setMaxDistance(float distance);
virtual float getMaxDistance() const;
virtual int getChannels() const;
void playAtomic();
void stopAtomic();
void pauseAtomic();
void resumeAtomic();
void rewindAtomic();
private:
void reset();
void setFloatv(float *dst, const float *src) const;
/**
* Gets the OpenAL format identifier based on number of
* channels and bits.
* @param channels Either 1 (mono) or 2 (stereo).
* @param bitDepth Either 8-bit samples, or 16-bit samples.
* @return One of AL_FORMAT_*, or 0 if unsupported format.
**/
ALenum getFormat(int channels, int bitDepth) const;
int streamAtomic(ALuint buffer, love::sound::Decoder *d);
Pool *pool;
ALuint source;
bool valid;
static const unsigned int MAX_BUFFERS = 32;
ALuint buffers[MAX_BUFFERS];
float pitch;
float volume;
float position[3];
float velocity[3];
float direction[3];
bool relative;
bool looping;
bool paused;
float minVolume;
float maxVolume;
float referenceDistance;
float rolloffFactor;
float maxDistance;
struct Cone
{
int innerAngle; // degrees
int outerAngle; // degrees
float outerVolume;
Cone()
: innerAngle(360)
, outerAngle(360)
, outerVolume(0.0f)
{}
} cone;
float offsetSamples;
float offsetSeconds;
int channels;
love::sound::Decoder *decoder;
unsigned int toLoop;
}; // Source
} // openal
} // audio
} // love
#endif // LOVE_AUDIO_OPENAL_SOURCE_H
+351
View File
@@ -0,0 +1,351 @@
/**
* Copyright (c) 2006-2013 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.
**/
// LOVE
#include "wrap_Audio.h"
#include "openal/Audio.h"
#include "null/Audio.h"
#include "common/runtime.h"
namespace love
{
namespace audio
{
static Audio *instance = 0;
int w_getSourceCount(lua_State *L)
{
lua_pushinteger(L, instance->getSourceCount());
return 1;
}
int w_newSource(lua_State *L)
{
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T))
luax_convobj(L, 1, "filesystem", "newFileData");
if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
luax_convobj(L, 1, "sound", "newDecoder");
Source::Type stype = Source::TYPE_STREAM;
const char *stypestr = lua_isnoneornil(L, 2) ? 0 : lua_tostring(L, 2);
if (stypestr && !Source::getConstant(stypestr, stype))
return luaL_error(L, "Invalid source type: %s", stypestr);
if (stype == Source::TYPE_STATIC && luax_istype(L, 1, SOUND_DECODER_T))
luax_convobj(L, 1, "sound", "newSoundData");
Source *t = 0;
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)
{
luax_pushtype(L, "Source", AUDIO_SOURCE_T, t);
return 1;
}
else
return luax_typerror(L, 1, "Decoder or SoundData");
}
int w_play(lua_State *L)
{
Source *s = luax_checksource(L, 1);
instance->play(s);
return 0;
}
int w_stop(lua_State *L)
{
if (lua_gettop(L) == 0)
{
instance->stop();
}
else
{
Source *s = luax_checksource(L, 1);
s->stop();
}
return 0;
}
int w_pause(lua_State *L)
{
if (lua_gettop(L) == 0)
{
instance->pause();
}
else
{
Source *s = luax_checksource(L, 1);
s->pause();
}
return 0;
}
int w_resume(lua_State *L)
{
if (lua_gettop(L) == 0)
{
instance->resume();
}
else
{
Source *s = luax_checksource(L, 1);
s->resume();
}
return 0;
}
int w_rewind(lua_State *L)
{
if (lua_gettop(L) == 0)
{
instance->rewind();
}
else
{
Source *s = luax_checksource(L, 1);
s->rewind();
}
return 0;
}
int w_setVolume(lua_State *L)
{
float v = (float)luaL_checknumber(L, 1);
instance->setVolume(v);
return 0;
}
int w_getVolume(lua_State *L)
{
lua_pushnumber(L, instance->getVolume());
return 1;
}
int w_setPosition(lua_State *L)
{
float v[3];
v[0] = (float)luaL_checknumber(L, 1);
v[1] = (float)luaL_checknumber(L, 2);
v[2] = (float)luaL_optnumber(L, 3, 0);
instance->setPosition(v);
return 0;
}
int w_getPosition(lua_State *L)
{
float v[3];
instance->getPosition(v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
return 3;
}
int w_setOrientation(lua_State *L)
{
float v[6];
v[0] = (float)luaL_checknumber(L, 1);
v[1] = (float)luaL_checknumber(L, 2);
v[2] = (float)luaL_checknumber(L, 3);
v[3] = (float)luaL_checknumber(L, 4);
v[4] = (float)luaL_checknumber(L, 5);
v[5] = (float)luaL_checknumber(L, 6);
instance->setOrientation(v);
return 0;
}
int w_getOrientation(lua_State *L)
{
float v[6];
instance->getOrientation(v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
lua_pushnumber(L, v[3]);
lua_pushnumber(L, v[4]);
lua_pushnumber(L, v[5]);
return 6;
}
int w_setVelocity(lua_State *L)
{
float v[3];
v[0] = (float)luaL_checknumber(L, 1);
v[1] = (float)luaL_checknumber(L, 2);
v[2] = (float)luaL_optnumber(L, 3, 0);
instance->setVelocity(v);
return 0;
}
int w_getVelocity(lua_State *L)
{
float v[3];
instance->getVelocity(v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
return 3;
}
int w_record(lua_State *)
{
instance->record();
return 0;
}
int w_getRecordedData(lua_State *L)
{
love::sound::SoundData *sd = instance->getRecordedData();
if (!sd)
lua_pushnil(L);
else
luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
return 1;
}
int w_stopRecording(lua_State *L)
{
if (luax_optboolean(L, 1, true))
{
love::sound::SoundData *sd = instance->stopRecording(true);
if (!sd) lua_pushnil(L);
else luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
return 1;
}
instance->stopRecording(false);
return 0;
}
int w_canRecord(lua_State *L)
{
luax_pushboolean(L, instance->canRecord());
return 1;
}
int w_setDistanceModel(lua_State *L)
{
const char *modelStr = luaL_checkstring(L, 1);
Audio::DistanceModel distanceModel;
if (!Audio::getConstant(modelStr, distanceModel))
return luaL_error(L, "Invalid distance model: %s", modelStr);
instance->setDistanceModel(distanceModel);
return 0;
}
int w_getDistanceModel(lua_State *L)
{
Audio::DistanceModel distanceModel = instance->getDistanceModel();
const char *modelStr;
if (!Audio::getConstant(distanceModel, modelStr))
return 0;
lua_pushstring(L, modelStr);
return 1;
}
// List of functions to wrap.
static const luaL_Reg functions[] =
{
{ "getSourceCount", w_getSourceCount },
{ "newSource", w_newSource },
{ "play", w_play },
{ "stop", w_stop },
{ "pause", w_pause },
{ "resume", w_resume },
{ "rewind", w_rewind },
{ "setVolume", w_setVolume },
{ "getVolume", w_getVolume },
{ "setPosition", w_setPosition },
{ "getPosition", w_getPosition },
{ "setOrientation", w_setOrientation },
{ "getOrientation", w_getOrientation },
{ "setVelocity", w_setVelocity },
{ "getVelocity", w_getVelocity },
/*{ "record", w_record },
{ "getRecordedData", w_getRecordedData },
{ "stopRecording", w_stopRecording },*/
{ "setDistanceModel", w_setDistanceModel },
{ "getDistanceModel", w_getDistanceModel },
{ 0, 0 }
};
static const lua_CFunction types[] =
{
luaopen_source,
0
};
extern "C" int luaopen_love_audio(lua_State *L)
{
if (instance == 0)
{
// Try OpenAL first.
try
{
instance = new love::audio::openal::Audio();
}
catch(love::Exception &e)
{
std::cout << e.what() << std::endl;
}
}
else
instance->retain();
if (instance == 0)
{
// Fall back to nullaudio.
try
{
instance = new love::audio::null::Audio();
}
catch(love::Exception &e)
{
std::cout << e.what() << std::endl;
}
}
if (instance == 0)
return luaL_error(L, "Could not open any audio module.");
WrappedModule w;
w.module = instance;
w.name = "audio";
w.flags = MODULE_T;
w.functions = functions;
w.types = types;
int n = luax_register_module(L, w);
return n;
}
} // audio
} // love
+61
View File
@@ -0,0 +1,61 @@
/**
* Copyright (c) 2006-2013 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_AUDIO_H
#define LOVE_AUDIO_WRAP_AUDIO_H
// LOVE
#include "common/config.h"
#include "common/runtime.h"
#include "Audio.h"
#include "wrap_Source.h"
namespace love
{
namespace audio
{
int w_getSourceCount(lua_State *L);
int w_newSource(lua_State *L);
int w_play(lua_State *L);
int w_stop(lua_State *L);
int w_pause(lua_State *L);
int w_resume(lua_State *L);
int w_rewind(lua_State *L);
int w_setVolume(lua_State *L);
int w_getVolume(lua_State *L);
int w_setPosition(lua_State *L);
int w_getPosition(lua_State *L);
int w_setOrientation(lua_State *L);
int w_getOrientation(lua_State *L);
int w_setVelocity(lua_State *L);
int w_getVelocity(lua_State *L);
int w_record(lua_State *L);
int w_getRecordedData(lua_State *L);
int w_stopRecording(lua_State *L);
int w_canRecord(lua_State *L);
int w_setDistanceModel(lua_State *L);
int w_getDistanceModel(lua_State *L);
extern "C" LOVE_EXPORT int luaopen_love_audio(lua_State *L);
} // audio
} // love
#endif // LOVE_AUDIO_WRAP_AUDIO_H
+385
View File
@@ -0,0 +1,385 @@
/**
* Copyright (c) 2006-2013 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_Source.h"
namespace love
{
namespace audio
{
Source *luax_checksource(lua_State *L, int idx)
{
return luax_checktype<Source>(L, idx, "Source", AUDIO_SOURCE_T);
}
int w_Source_play(lua_State *L)
{
Source *t = luax_checksource(L, 1);
t->play();
return 0;
}
int w_Source_stop(lua_State *L)
{
Source *t = luax_checksource(L, 1);
t->stop();
return 0;
}
int w_Source_pause(lua_State *L)
{
Source *t = luax_checksource(L, 1);
t->pause();
return 0;
}
int w_Source_resume(lua_State *L)
{
Source *t = luax_checksource(L, 1);
t->resume();
return 0;
}
int w_Source_rewind(lua_State *L)
{
Source *t = luax_checksource(L, 1);
t->rewind();
return 0;
}
int w_Source_setPitch(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float p = (float)luaL_checknumber(L, 2);
t->setPitch(p);
return 0;
}
int w_Source_getPitch(lua_State *L)
{
Source *t = luax_checksource(L, 1);
lua_pushnumber(L, t->getPitch());
return 1;
}
int w_Source_setVolume(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float p = (float)luaL_checknumber(L, 2);
t->setVolume(p);
return 0;
}
int w_Source_getVolume(lua_State *L)
{
Source *t = luax_checksource(L, 1);
lua_pushnumber(L, t->getVolume());
return 1;
}
int w_Source_seek(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float offset = (float)luaL_checknumber(L, 2);
if (offset < 0)
return luaL_argerror(L, 2, "can't seek to a negative position");
Source::Unit u = Source::UNIT_SECONDS;
const char *unit = lua_isnoneornil(L, 3) ? 0 : lua_tostring(L, 3);
if (unit && !t->getConstant(unit, u))
return luaL_error(L, "Invalid Source time unit: %s", unit);
t->seek(offset, u);
return 0;
}
int w_Source_tell(lua_State *L)
{
Source *t = luax_checksource(L, 1);
Source::Unit u = Source::UNIT_SECONDS;
const char *unit = lua_isnoneornil(L, 2) ? 0 : lua_tostring(L, 2);
if (unit && !t->getConstant(unit, u))
return luaL_error(L, "Invalid Source time unit: %s", unit);
lua_pushnumber(L, t->tell(u));
return 1;
}
int w_Source_setPosition(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float v[3];
v[0] = (float)luaL_checknumber(L, 2);
v[1] = (float)luaL_checknumber(L, 3);
v[2] = (float)luaL_optnumber(L, 4, 0);
t->setPosition(v);
return 0;
}
int w_Source_getPosition(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float v[3];
t->getPosition(v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
return 3;
}
int w_Source_setVelocity(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float v[3];
v[0] = (float)luaL_checknumber(L, 2);
v[1] = (float)luaL_checknumber(L, 3);
v[2] = (float)luaL_optnumber(L, 4, 0);
t->setVelocity(v);
return 0;
}
int w_Source_getVelocity(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float v[3];
t->getVelocity(v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
return 3;
}
int w_Source_setDirection(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float v[3];
v[0] = (float)luaL_checknumber(L, 2);
v[1] = (float)luaL_checknumber(L, 3);
v[2] = (float)luaL_optnumber(L, 4, 0);
t->setDirection(v);
return 0;
}
int w_Source_getDirection(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float v[3];
t->getDirection(v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
return 3;
}
int w_Source_setCone(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float innerAngle = (float) luaL_checknumber(L, 2);
float outerAngle = (float) luaL_checknumber(L, 3);
float outerVolume = (float) luaL_optnumber(L, 4, 0.0);
t->setCone(innerAngle, outerAngle, outerVolume);
return 0;
}
int w_Source_getCone(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float innerAngle, outerAngle, outerVolume;
t->getCone(innerAngle, outerAngle, outerVolume);
lua_pushnumber(L, innerAngle);
lua_pushnumber(L, outerAngle);
lua_pushnumber(L, outerVolume);
return 3;
}
int w_Source_setRelative(lua_State *L)
{
Source *t = luax_checksource(L, 1);
t->setRelative(luax_toboolean(L, 2));
return 0;
}
int w_Source_isRelative(lua_State *L)
{
Source *t = luax_checksource(L, 1);
luax_pushboolean(L, t->isRelative());
return 1;
}
int w_Source_setLooping(lua_State *L)
{
Source *t = luax_checksource(L, 1);
t->setLooping(luax_toboolean(L, 2));
return 0;
}
int w_Source_isLooping(lua_State *L)
{
Source *t = luax_checksource(L, 1);
luax_pushboolean(L, t->isLooping());
return 1;
}
int w_Source_isStopped(lua_State *L)
{
Source *t = luax_checksource(L, 1);
luax_pushboolean(L, t->isStopped());
return 1;
}
int w_Source_isPaused(lua_State *L)
{
Source *t = luax_checksource(L, 1);
luax_pushboolean(L, t->isPaused());
return 1;
}
int w_Source_isPlaying(lua_State *L)
{
Source *t = luax_checksource(L, 1);
luax_pushboolean(L, !t->isStopped() && !t->isPaused());
return 1;
}
int w_Source_isStatic(lua_State *L)
{
Source *t = luax_checksource(L, 1);
luax_pushboolean(L, t->isStatic());
return 1;
}
int w_Source_setVolumeLimits(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float vmin = (float)luaL_checknumber(L, 2);
float vmax = (float)luaL_checknumber(L, 3);
if (vmin < .0f || vmin > 1.f || vmax < .0f || vmax > 1.f)
return luaL_error(L, "Invalid volume limits: [%f:%f]. Must be in [0:1]", vmin, vmax);
t->setMinVolume(vmin);
t->setMaxVolume(vmax);
return 0;
}
int w_Source_getVolumeLimits(lua_State *L)
{
Source *t = luax_checksource(L, 1);
lua_pushnumber(L, t->getMinVolume());
lua_pushnumber(L, t->getMaxVolume());
return 2;
}
int w_Source_setAttenuationDistances(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float dref = (float)luaL_checknumber(L, 2);
float dmax = (float)luaL_checknumber(L, 3);
if (dref < .0f || dmax < .0f)
return luaL_error(L, "Invalid distances: %f, %f. Must be > 0", dref, dmax);
t->setReferenceDistance(dref);
t->setMaxDistance(dmax);
return 0;
}
int w_Source_getAttenuationDistances(lua_State *L)
{
Source *t = luax_checksource(L, 1);
lua_pushnumber(L, t->getReferenceDistance());
lua_pushnumber(L, t->getMaxDistance());
return 2;
}
int w_Source_setRolloff(lua_State *L)
{
Source *t = luax_checksource(L, 1);
float rolloff = (float)luaL_checknumber(L, 2);
if (rolloff < .0f)
return luaL_error(L, "Invalid rolloff: %f. Must be > 0.", rolloff);
t->setRolloffFactor(rolloff);
return 0;
}
int w_Source_getRolloff(lua_State *L)
{
Source *t = luax_checksource(L, 1);
lua_pushnumber(L, t->getRolloffFactor());
return 1;
}
int w_Source_getChannels(lua_State *L)
{
Source *t = luax_checksource(L, 1);
lua_pushinteger(L, t->getChannels());
return 1;
}
static const luaL_Reg functions[] =
{
{ "play", w_Source_play },
{ "stop", w_Source_stop },
{ "pause", w_Source_pause },
{ "resume", w_Source_resume },
{ "rewind", w_Source_rewind },
{ "setPitch", w_Source_setPitch },
{ "getPitch", w_Source_getPitch },
{ "setVolume", w_Source_setVolume },
{ "getVolume", w_Source_getVolume },
{ "seek", w_Source_seek },
{ "tell", w_Source_tell },
{ "setPosition", w_Source_setPosition },
{ "getPosition", w_Source_getPosition },
{ "setVelocity", w_Source_setVelocity },
{ "getVelocity", w_Source_getVelocity },
{ "setDirection", w_Source_setDirection },
{ "getDirection", w_Source_getDirection },
{ "setCone", w_Source_setCone },
{ "getCone", w_Source_getCone },
{ "setRelative", w_Source_setRelative },
{ "isRelative", w_Source_isRelative },
{ "setLooping", w_Source_setLooping },
{ "isLooping", w_Source_isLooping },
{ "isStopped", w_Source_isStopped },
{ "isPaused", w_Source_isPaused },
{ "isPlaying", w_Source_isPlaying },
{ "isStatic", w_Source_isStatic },
{ "setVolumeLimits", w_Source_setVolumeLimits },
{ "getVolumeLimits", w_Source_getVolumeLimits },
{ "setAttenuationDistances", w_Source_setAttenuationDistances },
{ "getAttenuationDistances", w_Source_getAttenuationDistances },
{ "setRolloff", w_Source_setRolloff},
{ "getRolloff", w_Source_getRolloff},
{ "getChannels", w_Source_getChannels },
{ 0, 0 }
};
extern "C" int luaopen_source(lua_State *L)
{
return luax_register_type(L, "Source", functions);
}
} // audio
} // love
+72
View File
@@ -0,0 +1,72 @@
/**
* Copyright (c) 2006-2013 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_SOURCE_H
#define LOVE_AUDIO_WRAP_SOURCE_H
#include "common/runtime.h"
#include "Source.h"
namespace love
{
namespace audio
{
Source *luax_checksource(lua_State *L, int idx);
int w_Source_play(lua_State *L);
int w_Source_stop(lua_State *L);
int w_Source_pause(lua_State *L);
int w_Source_resume(lua_State *L);
int w_Source_rewind(lua_State *L);
int w_Source_setPitch(lua_State *L);
int w_Source_getPitch(lua_State *L);
int w_Source_setVolume(lua_State *L);
int w_Source_getVolume(lua_State *L);
int w_Source_seek(lua_State *L);
int w_Source_tell(lua_State *L);
int w_Source_setPosition(lua_State *L);
int w_Source_getPosition(lua_State *L);
int w_Source_setVelocity(lua_State *L);
int w_Source_getVelocity(lua_State *L);
int w_Source_setDirection(lua_State *L);
int w_Source_getDirection(lua_State *L);
int w_Source_setCone(lua_State *L);
int w_Source_getCone(lua_State *L);
int w_Source_setRelative(lua_State *L);
int w_Source_isRelative(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 w_Source_isPaused(lua_State *L);
int w_Source_isPlaying(lua_State *L);
int w_Source_isStatic(lua_State *L);
int w_Source_setVolumeLimits(lua_State *L);
int w_Source_getVolumeLimits(lua_State *L);
int w_Source_setAttenuationDistances(lua_State *L);
int w_Source_getAttenuationDistances(lua_State *L);
int w_Source_setRolloff(lua_State *L);
int w_Source_getRolloff(lua_State *L);
int w_Source_getChannels(lua_State *L);
extern "C" int luaopen_source(lua_State *L);
} // audio
} // love
#endif // LOVE_AUDIO_WRAP_SOURCE_H