mirror of
https://github.com/love2d/love-android.git
synced 2026-08-19 12:14:49 +02:00
imported Löve GLES branch (changeset 1ba9037e558b)
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user