Effects re-made to operate on literal names instead of numerical indices.

Added buffer count parameter to queueable source constructor.
Added getEffectsList function.
Internal cleanup.

--HG--
branch : minor
This commit is contained in:
raidho36
2017-06-22 15:07:31 +03:00
parent ad399cab39
commit 157d94fae3
12 changed files with 435 additions and 279 deletions
+14 -7
View File
@@ -77,7 +77,7 @@ public:
virtual Source *newSource(love::sound::Decoder *decoder) = 0; virtual Source *newSource(love::sound::Decoder *decoder) = 0;
virtual Source *newSource(love::sound::SoundData *soundData) = 0; virtual Source *newSource(love::sound::SoundData *soundData) = 0;
virtual Source *newSource(int sampleRate, int bitDepth, int channels) = 0; virtual Source *newSource(int sampleRate, int bitDepth, int channels, int buffers) = 0;
/** /**
* Gets the current number of simultaneous playing sources. * Gets the current number of simultaneous playing sources.
@@ -210,26 +210,33 @@ public:
/** /**
* Sets scene EFX effect. * Sets scene EFX effect.
* @param slot Slot to put effect into. * @param name Effect name to use.
* @param fxparams Effect description table. * @param fxparams Effect description table.
* @return true if successful, false otherwise. * @return true if successful, false otherwise.
*/ */
virtual bool setSceneEffect(int slot, std::map<Effect::Parameter, float> &params) = 0; virtual bool setEffect(const char *name, std::map<Effect::Parameter, float> &params) = 0;
/** /**
* Removes scene EFX effect. * Removes scene EFX effect.
* @param slot Effect slot to clear. * @param name Effect name to clear.
* @return true if successful, false otherwise. * @return true if successful, false otherwise.
*/ */
virtual bool setSceneEffect(int slot) = 0; virtual bool unsetEffect(const char *name) = 0;
/** /**
* Gets scene EFX effect. * Gets scene EFX effect.
* @param slot Slot from which to get effect. * @param name Effect name to get data from.
* @param fxparams Effect description table. * @param fxparams Effect description table.
* @return true if effect was present, false otherwise. * @return true if effect was present, false otherwise.
*/ */
virtual bool getSceneEffect(int slot, std::map<Effect::Parameter, float> &params) = 0; virtual bool getEffect(const char *name, std::map<Effect::Parameter, float> &params) = 0;
/**
* Gets list of EFX effect names.
* @param list List of EFX names to fill.
* @return true if effect was present, false otherwise.
*/
virtual bool getEffectsList(std::vector<std::string> &list) = 0;
/** /**
* Gets maximum number of scene EFX effects. * Gets maximum number of scene EFX effects.
+5 -4
View File
@@ -113,10 +113,11 @@ public:
virtual bool setFilter() = 0; virtual bool setFilter() = 0;
virtual bool getFilter(std::map<Filter::Parameter, float> &params) = 0; virtual bool getFilter(std::map<Filter::Parameter, float> &params) = 0;
virtual bool setSceneEffect(int slot, int effect) = 0; virtual bool setEffect(const char *effect) = 0;
virtual bool setSceneEffect(int slot, int effect, const std::map<Filter::Parameter, float> &params) = 0; virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params) = 0;
virtual bool setSceneEffect(int slot) = 0; virtual bool unsetEffect(const char *effect) = 0;
virtual bool getSceneEffect(int slot, int &effect, std::map<Filter::Parameter, float> &params) = 0; virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params) = 0;
virtual bool getEffectsList(std::vector<std::string> &list) = 0;
virtual int getFreeBufferCount() const = 0; virtual int getFreeBufferCount() const = 0;
virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels) = 0; virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels) = 0;
+9 -4
View File
@@ -51,7 +51,7 @@ love::audio::Source *Audio::newSource(love::sound::SoundData *)
return new Source(); return new Source();
} }
love::audio::Source *Audio::newSource(int, int, int) love::audio::Source *Audio::newSource(int, int, int, int)
{ {
return new Source(); return new Source();
} }
@@ -168,17 +168,22 @@ void Audio::setDistanceModel(DistanceModel distanceModel)
this->distanceModel = distanceModel; this->distanceModel = distanceModel;
} }
bool Audio::setSceneEffect(int, std::map<Effect::Parameter, float> &) bool Audio::setEffect(const char *, std::map<Effect::Parameter, float> &)
{ {
return false; return false;
} }
bool Audio::setSceneEffect(int) bool Audio::unsetEffect(const char *)
{ {
return false; return false;
} }
bool Audio::getSceneEffect(int, std::map<Effect::Parameter, float> &) bool Audio::getEffect(const char *, std::map<Effect::Parameter, float> &)
{
return false;
}
bool Audio::getEffectsList(std::vector<std::string> &list)
{ {
return false; return false;
} }
+5 -4
View File
@@ -47,7 +47,7 @@ public:
// Implements Audio. // Implements Audio.
love::audio::Source *newSource(love::sound::Decoder *decoder); love::audio::Source *newSource(love::sound::Decoder *decoder);
love::audio::Source *newSource(love::sound::SoundData *soundData); love::audio::Source *newSource(love::sound::SoundData *soundData);
love::audio::Source *newSource(int sampleRate, int bitDepth, int channels); love::audio::Source *newSource(int sampleRate, int bitDepth, int channels, int buffers);
int getSourceCount() const; int getSourceCount() const;
int getMaxSources() const; int getMaxSources() const;
bool play(love::audio::Source *source); bool play(love::audio::Source *source);
@@ -78,9 +78,10 @@ public:
DistanceModel getDistanceModel() const; DistanceModel getDistanceModel() const;
void setDistanceModel(DistanceModel distanceModel); void setDistanceModel(DistanceModel distanceModel);
bool setSceneEffect(int slot, std::map<Effect::Parameter, float> &params); bool setEffect(const char *, std::map<Effect::Parameter, float> &params);
bool setSceneEffect(int slot); bool unsetEffect(const char *);
bool getSceneEffect(int slot, std::map<Effect::Parameter, float> &params); bool getEffect(const char *, std::map<Effect::Parameter, float> &params);
bool getEffectsList(std::vector<std::string> &list);
int getMaxSceneEffects() const; int getMaxSceneEffects() const;
int getMaxSourceEffects() const; int getMaxSourceEffects() const;
bool isEFXsupported() const; bool isEFXsupported() const;
+9 -4
View File
@@ -254,22 +254,27 @@ bool Source::getFilter(std::map<Filter::Parameter, float> &)
return false; return false;
} }
bool Source::setSceneEffect(int, int) bool Source::setEffect(const char *)
{ {
return false; return false;
} }
bool Source::setSceneEffect(int, int, const std::map<Filter::Parameter, float> &) bool Source::setEffect(const char *, const std::map<Filter::Parameter, float> &)
{ {
return false; return false;
} }
bool Source::setSceneEffect(int) bool Source::unsetEffect(const char *)
{ {
return false; return false;
} }
bool Source::getSceneEffect(int, int &, std::map<Filter::Parameter, float> &) bool Source::getEffect(const char *, std::map<Filter::Parameter, float> &)
{
return false;
}
bool Source::getEffectsList(std::vector<std::string> &)
{ {
return false; return false;
} }
+5 -4
View File
@@ -86,10 +86,11 @@ public:
virtual bool setFilter(); virtual bool setFilter();
virtual bool getFilter(std::map<Filter::Parameter, float> &params); virtual bool getFilter(std::map<Filter::Parameter, float> &params);
virtual bool setSceneEffect(int slot, int effect); virtual bool setEffect(const char *effect);
virtual bool setSceneEffect(int slot, int effect, const std::map<Filter::Parameter, float> &params); virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params);
virtual bool setSceneEffect(int slot); virtual bool unsetEffect(const char *effect);
virtual bool getSceneEffect(int slot, int &effect, std::map<Filter::Parameter, float> &params); virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params);
virtual bool getEffectsList(std::vector<std::string> &list);
private: private:
+74 -46
View File
@@ -129,11 +129,7 @@ Audio::Audio()
ALuint slot; ALuint slot;
alGenAuxiliaryEffectSlots(1, &slot); alGenAuxiliaryEffectSlots(1, &slot);
if (alGetError() == AL_NO_ERROR) if (alGetError() == AL_NO_ERROR)
{ slotlist.push(slot);
effectIndex[slot] = effectSlots.size();
effectSlots.push_back(slot);
effects.push_back(nullptr);
}
else else
{ {
MAX_SCENE_EFFECTS = i; MAX_SCENE_EFFECTS = i;
@@ -159,8 +155,11 @@ Audio::Audio()
#ifdef ALC_EXT_EFX #ifdef ALC_EXT_EFX
if (alDeleteAuxiliaryEffectSlots) if (alDeleteAuxiliaryEffectSlots)
{ {
for (auto slot : effectSlots) while (!slotlist.empty())
alDeleteAuxiliaryEffectSlots(1, &slot); {
alDeleteAuxiliaryEffectSlots(1, &slotlist.top());
slotlist.pop();
}
} }
#endif #endif
@@ -186,16 +185,19 @@ Audio::~Audio()
delete c; delete c;
#ifdef ALC_EXT_EFX #ifdef ALC_EXT_EFX
for (auto e : effects) for (auto e : effectmap)
{ {
if (e != nullptr) delete e.second.effect;
delete e; slotlist.push(e.second.slot);
} }
if (alDeleteAuxiliaryEffectSlots) if (alDeleteAuxiliaryEffectSlots)
{ {
for (auto slot : effectSlots) while (!slotlist.empty())
alDeleteAuxiliaryEffectSlots(1, &slot); {
alDeleteAuxiliaryEffectSlots(1, &slotlist.top());
slotlist.pop();
}
} }
#endif #endif
alcMakeContextCurrent(nullptr); alcMakeContextCurrent(nullptr);
@@ -218,9 +220,9 @@ love::audio::Source *Audio::newSource(love::sound::SoundData *soundData)
return new Source(pool, soundData); return new Source(pool, soundData);
} }
love::audio::Source *Audio::newSource(int sampleRate, int bitDepth, int channels) love::audio::Source *Audio::newSource(int sampleRate, int bitDepth, int channels, int buffers)
{ {
return new Source(pool, sampleRate, bitDepth, channels); return new Source(pool, sampleRate, bitDepth, channels, buffers);
} }
int Audio::getSourceCount() const int Audio::getSourceCount() const
@@ -456,27 +458,44 @@ const std::vector<love::audio::RecordingDevice*> &Audio::getRecordingDevices()
return capture; return capture;
} }
bool Audio::setSceneEffect(int slot, std::map<Effect::Parameter, float> &params) bool Audio::setEffect(const char *name, std::map<Effect::Parameter, float> &params)
{ {
if (slot < 0 || slot >= MAX_SCENE_EFFECTS) Effect *effect;
return false; ALuint slot;
if (!effects[slot]) auto iter = effectmap.find(name);
effects[slot] = new Effect(); if (iter == effectmap.end())
{
//new effect needed but no more slots
if (effectmap.size() >= (unsigned int)MAX_SCENE_EFFECTS)
return false;
bool result = effects[slot]->setParams(params); effect = new Effect();
slot = slotlist.top();
slotlist.pop();
effectmap[name] = {effect, slot};
}
else
{
effect = iter->second.effect;
slot = iter->second.slot;
}
bool result = effect->setParams(params);
#ifdef ALC_EXT_EFX #ifdef ALC_EXT_EFX
if (alAuxiliaryEffectSloti) if (alAuxiliaryEffectSloti)
{ {
if (result) if (result)
{ {
if (params.find(Effect::EFFECT_VOLUME) != params.end()) auto iter = params.find(Effect::EFFECT_VOLUME);
alAuxiliaryEffectSlotf(effectSlots[slot], AL_EFFECTSLOT_GAIN, params[Effect::EFFECT_VOLUME]); if (iter != params.end())
alAuxiliaryEffectSloti(effectSlots[slot], AL_EFFECTSLOT_EFFECT, effects[slot]->getEffect()); alAuxiliaryEffectSlotf(slot, AL_EFFECTSLOT_GAIN, iter->second);
alAuxiliaryEffectSloti(slot, AL_EFFECTSLOT_EFFECT, effect->getEffect());
} }
else else
alAuxiliaryEffectSloti(effectSlots[slot], AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL); alAuxiliaryEffectSloti(slot, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL);
alGetError(); alGetError();
} }
#endif #endif
@@ -484,33 +503,45 @@ bool Audio::setSceneEffect(int slot, std::map<Effect::Parameter, float> &params)
return result; return result;
} }
bool Audio::setSceneEffect(int slot) bool Audio::unsetEffect(const char *name)
{ {
if (slot < 0 || slot >= MAX_SCENE_EFFECTS) auto iter = effectmap.find(name);
if (iter == effectmap.end())
return false; return false;
if (effects[slot]) Effect *effect = iter->second.effect;
delete effects[slot]; ALuint slot = iter->second.slot;
effects[slot] = nullptr;
#ifdef ALC_EXT_EFX #ifdef ALC_EXT_EFX
if (alAuxiliaryEffectSloti) if (alAuxiliaryEffectSloti)
alAuxiliaryEffectSloti(effectSlots[slot], AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL); alAuxiliaryEffectSloti(slot, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL);
#endif #endif
delete effect;
effectmap.erase(iter);
slotlist.push(slot);
return true;
}
bool Audio::getEffect(const char *name, std::map<Effect::Parameter, float> &params)
{
auto iter = effectmap.find(name);
if (iter == effectmap.end())
return false;
params = iter->second.effect->getParams();
return true; return true;
} }
bool Audio::getSceneEffect(int slot, std::map<Effect::Parameter, float> &params) bool Audio::getEffectsList(std::vector<std::string> &list)
{ {
if (slot < 0 || slot >= MAX_SCENE_EFFECTS) if (effectmap.empty())
return false; return false;
if (!effects[slot]) list.reserve(effectmap.size());
return false; for (auto i : effectmap)
list.push_back(i.first);
params = effects[slot]->getParams();
return true; return true;
} }
@@ -534,17 +565,14 @@ bool Audio::isEFXsupported() const
#endif #endif
} }
ALuint Audio::getSceneEffectID(int slot) bool Audio::getEffectID(const char *name, ALuint &id)
{ {
if (slot < 0 || slot >= MAX_SCENE_EFFECTS) auto iter = effectmap.find(name);
return effectSlots[0]; if (iter == effectmap.end())
return false;
return effectSlots[slot]; id = iter->second.slot;
} return true;
int Audio::getSceneEffectIndex(ALuint effect)
{
return effectIndex[effect];
} }
#ifdef ALC_EXT_EFX #ifdef ALC_EXT_EFX
+16 -11
View File
@@ -25,6 +25,7 @@
#include <queue> #include <queue>
#include <map> #include <map>
#include <vector> #include <vector>
#include <stack>
#include <cmath> #include <cmath>
// LOVE // LOVE
@@ -83,7 +84,7 @@ public:
// Implements Audio. // Implements Audio.
love::audio::Source *newSource(love::sound::Decoder *decoder); love::audio::Source *newSource(love::sound::Decoder *decoder);
love::audio::Source *newSource(love::sound::SoundData *soundData); love::audio::Source *newSource(love::sound::SoundData *soundData);
love::audio::Source *newSource(int sampleRate, int bitDepth, int channels); love::audio::Source *newSource(int sampleRate, int bitDepth, int channels, int buffers);
int getSourceCount() const; int getSourceCount() const;
int getMaxSources() const; int getMaxSources() const;
bool play(love::audio::Source *source); bool play(love::audio::Source *source);
@@ -114,15 +115,15 @@ public:
DistanceModel getDistanceModel() const; DistanceModel getDistanceModel() const;
void setDistanceModel(DistanceModel distanceModel); void setDistanceModel(DistanceModel distanceModel);
bool setSceneEffect(int slot, std::map<Effect::Parameter, float> &params); bool setEffect(const char *name, std::map<Effect::Parameter, float> &params);
bool setSceneEffect(int slot); bool unsetEffect(const char *name);
bool getSceneEffect(int slot, std::map<Effect::Parameter, float> &params); bool getEffect(const char *name, std::map<Effect::Parameter, float> &params);
bool getEffectsList(std::vector<std::string> &list);
int getMaxSceneEffects() const; int getMaxSceneEffects() const;
int getMaxSourceEffects() const; int getMaxSourceEffects() const;
bool isEFXsupported() const; bool isEFXsupported() const;
ALuint getSceneEffectID(int slot); bool getEffectID(const char *name, ALuint &id);
int getSceneEffectIndex(ALuint effect);
private: private:
void initializeEFX(); void initializeEFX();
@@ -136,11 +137,15 @@ private:
ALCcontext *context; ALCcontext *context;
// The OpenAL effects // The OpenAL effects
std::vector<Effect*> effects; struct effectmapStorage
std::vector<ALuint> effectSlots; {
std::map<ALuint, int> effectIndex; Effect *effect;
int MAX_SCENE_EFFECTS = 16; ALuint slot;
int MAX_SOURCE_EFFECTS = 16; };
std::map<std::string, struct effectmapStorage> effectmap;
std::stack<ALuint> slotlist;
int MAX_SCENE_EFFECTS = 64;
int MAX_SOURCE_EFFECTS = 64;
// The Pool. // The Pool.
Pool *pool; Pool *pool;
+215 -142
View File
@@ -124,8 +124,6 @@ Source::Source(Pool *pool, love::sound::SoundData *soundData)
, sampleRate(soundData->getSampleRate()) , sampleRate(soundData->getSampleRate())
, channels(soundData->getChannels()) , channels(soundData->getChannels())
, bitDepth(soundData->getBitDepth()) , bitDepth(soundData->getBitDepth())
, sendfilters(audiomodule()->getMaxSourceEffects(), nullptr)
, sendtargets(audiomodule()->getMaxSourceEffects(), AL_EFFECTSLOT_NULL)
{ {
ALenum fmt = Audio::getFormat(soundData->getBitDepth(), soundData->getChannels()); ALenum fmt = Audio::getFormat(soundData->getBitDepth(), soundData->getChannels());
if (fmt == AL_NONE) if (fmt == AL_NONE)
@@ -138,6 +136,9 @@ Source::Source(Pool *pool, love::sound::SoundData *soundData)
setFloatv(position, z); setFloatv(position, z);
setFloatv(velocity, z); setFloatv(velocity, z);
setFloatv(direction, z); setFloatv(direction, z);
for (unsigned int i = 0; i < (unsigned int)audiomodule()->getMaxSourceEffects(); i++)
slotlist.push(i);
} }
Source::Source(Pool *pool, love::sound::Decoder *decoder) Source::Source(Pool *pool, love::sound::Decoder *decoder)
@@ -147,46 +148,72 @@ Source::Source(Pool *pool, love::sound::Decoder *decoder)
, channels(decoder->getChannels()) , channels(decoder->getChannels())
, bitDepth(decoder->getBitDepth()) , bitDepth(decoder->getBitDepth())
, decoder(decoder) , decoder(decoder)
, unusedBufferTop(MAX_BUFFERS - 1) , buffers(DEFAULT_BUFFERS)
, sendfilters(audiomodule()->getMaxSourceEffects(), nullptr)
, sendtargets(audiomodule()->getMaxSourceEffects(), AL_EFFECTSLOT_NULL)
{ {
if (Audio::getFormat(decoder->getBitDepth(), decoder->getChannels()) == AL_NONE) if (Audio::getFormat(decoder->getBitDepth(), decoder->getChannels()) == AL_NONE)
throw InvalidFormatException(decoder->getChannels(), decoder->getBitDepth()); throw InvalidFormatException(decoder->getChannels(), decoder->getBitDepth());
alGenBuffers(MAX_BUFFERS, streamBuffers); for (int i = 0; i < buffers; i++)
for (unsigned int i = 0; i < MAX_BUFFERS; i++) {
unusedBuffers[i] = streamBuffers[i]; ALuint buf;
alGenBuffers(1, &buf);
if (alGetError() == AL_NO_ERROR)
unusedBuffers.push(buf);
else
{
buffers = i;
break;
}
}
float z[3] = {0, 0, 0}; float z[3] = {0, 0, 0};
setFloatv(position, z); setFloatv(position, z);
setFloatv(velocity, z); setFloatv(velocity, z);
setFloatv(direction, z); setFloatv(direction, z);
for (unsigned int i = 0; i < (unsigned int)audiomodule()->getMaxSourceEffects(); i++)
slotlist.push(i);
} }
Source::Source(Pool *pool, int sampleRate, int bitDepth, int channels) Source::Source(Pool *pool, int sampleRate, int bitDepth, int channels, int buffers)
: love::audio::Source(Source::TYPE_QUEUE) : love::audio::Source(Source::TYPE_QUEUE)
, pool(pool) , pool(pool)
, sampleRate(sampleRate) , sampleRate(sampleRate)
, channels(channels) , channels(channels)
, bitDepth(bitDepth) , bitDepth(bitDepth)
, sendfilters(audiomodule()->getMaxSourceEffects(), nullptr) , buffers(buffers)
, sendtargets(audiomodule()->getMaxSourceEffects(), AL_EFFECTSLOT_NULL)
{ {
ALenum fmt = Audio::getFormat(bitDepth, channels); ALenum fmt = Audio::getFormat(bitDepth, channels);
if (fmt == AL_NONE) if (fmt == AL_NONE)
throw InvalidFormatException(channels, bitDepth); throw InvalidFormatException(channels, bitDepth);
alGenBuffers(MAX_BUFFERS, streamBuffers); if (buffers < 1)
for (unsigned int i = 0; i < MAX_BUFFERS; i++) buffers = DEFAULT_BUFFERS;
unusedBuffers[i] = streamBuffers[i]; if (buffers > MAX_BUFFERS)
buffers = MAX_BUFFERS;
for (int i = 0; i < buffers; i++)
{
ALuint buf;
alGenBuffers(1, &buf);
if (alGetError() == AL_NO_ERROR)
unusedBuffers.push(buf);
else
{
buffers = i;
break;
}
}
float z[3] = {0, 0, 0}; float z[3] = {0, 0, 0};
setFloatv(position, z); setFloatv(position, z);
setFloatv(velocity, z); setFloatv(velocity, z);
setFloatv(direction, z); setFloatv(direction, z);
for (unsigned int i = 0; i < (unsigned int)audiomodule()->getMaxSourceEffects(); i++)
slotlist.push(i);
} }
Source::Source(const Source &s) Source::Source(const Source &s)
@@ -211,9 +238,7 @@ Source::Source(const Source &s)
, bitDepth(s.bitDepth) , bitDepth(s.bitDepth)
, decoder(nullptr) , decoder(nullptr)
, toLoop(0) , toLoop(0)
, unusedBufferTop(s.sourceType == TYPE_STREAM ? MAX_BUFFERS - 1 : -1) , buffers(s.buffers)
, sendfilters(s.sendfilters)
, sendtargets(s.sendtargets)
{ {
if (sourceType == TYPE_STREAM) if (sourceType == TYPE_STREAM)
{ {
@@ -222,16 +247,43 @@ Source::Source(const Source &s)
} }
if (sourceType != TYPE_STATIC) if (sourceType != TYPE_STATIC)
{ {
alGenBuffers(MAX_BUFFERS, streamBuffers); for (int i = 0; i < buffers; i++)
for (unsigned int i = 0; i < MAX_BUFFERS; i++) {
unusedBuffers[i] = streamBuffers[i]; ALuint buf;
alGenBuffers(1, &buf);
if (alGetError() == AL_NO_ERROR)
unusedBuffers.push(buf);
else
{
buffers = i;
break;
}
}
} }
if (s.directfilter) if (s.directfilter)
directfilter = s.directfilter->clone(); directfilter = s.directfilter->clone();
for (auto e : s.effectmap)
effectmap[e.first] = { e.second.filter ? e.second.filter->clone() : nullptr, e.second.slot, e.second.target };
setFloatv(position, s.position); setFloatv(position, s.position);
setFloatv(velocity, s.velocity); setFloatv(velocity, s.velocity);
setFloatv(direction, s.direction); setFloatv(direction, s.direction);
for (unsigned int i = 0; i < (unsigned int)audiomodule()->getMaxSourceEffects(); i++)
{
// filter out already taken slots
bool push = true;
for (auto e : effectmap)
{
if (e.second.slot)
push = false;
break;
}
if (push)
slotlist.push(i);
}
} }
Source::~Source() Source::~Source()
@@ -239,15 +291,26 @@ Source::~Source()
stop(); stop();
if (sourceType != TYPE_STATIC) if (sourceType != TYPE_STATIC)
alDeleteBuffers(MAX_BUFFERS, streamBuffers); {
while (!streamBuffers.empty())
{
alDeleteBuffers(1, &streamBuffers.front());
streamBuffers.pop();
}
while (!unusedBuffers.empty())
{
alDeleteBuffers(1, &unusedBuffers.top());
unusedBuffers.pop();
}
}
if (directfilter) if (directfilter)
delete directfilter; delete directfilter;
for (auto sf : sendfilters) for (auto e : effectmap)
{ {
if (sf != nullptr) if (e.second.filter)
delete sf; delete e.second.filter;
} }
} }
@@ -329,7 +392,7 @@ bool Source::update()
if (!isFinished()) if (!isFinished())
{ {
ALint processed; ALint processed;
ALuint buffers[MAX_BUFFERS]; ALuint buffers[this->buffers];
float curOffsetSamples, curOffsetSecs, newOffsetSamples, newOffsetSecs; float curOffsetSamples, curOffsetSecs, newOffsetSamples, newOffsetSecs;
int freq = decoder->getSampleRate(); int freq = decoder->getSampleRate();
@@ -346,12 +409,16 @@ bool Source::update()
offsetSeconds += (curOffsetSecs - newOffsetSecs); offsetSeconds += (curOffsetSecs - newOffsetSecs);
for (unsigned int i = 0; i < (unsigned int)processed; i++) for (unsigned int i = 0; i < (unsigned int)processed; i++)
unusedBufferPush(buffers[i]); unusedBuffers.push(buffers[i]);
while (unusedBufferPeek() != AL_NONE) while (!unusedBuffers.empty())
{ {
if(streamAtomic(unusedBufferPeek(), decoder.get()) > 0) auto b = unusedBuffers.top();
alSourceQueueBuffers(source, 1, unusedBufferPop()); if (streamAtomic(b, decoder.get()) > 0)
{
alSourceQueueBuffers(source, 1, &b);
unusedBuffers.pop();
}
else else
break; break;
} }
@@ -359,10 +426,10 @@ bool Source::update()
return true; return true;
} }
return false; return false;
case TYPE_QUEUE: case TYPE_QUEUE:
{ {
ALint processed; ALint processed;
ALuint buffers[MAX_BUFFERS]; ALuint buffers[this->buffers];
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
alSourceUnqueueBuffers(source, processed, buffers); alSourceUnqueueBuffers(source, processed, buffers);
@@ -372,7 +439,7 @@ bool Source::update()
ALint size; ALint size;
alGetBufferi(buffers[i], AL_SIZE, &size); alGetBufferi(buffers[i], AL_SIZE, &size);
bufferedBytes -= size; bufferedBytes -= size;
unusedBufferPush(buffers[i]); unusedBuffers.push(buffers[i]);
} }
return !isFinished(); return !isFinished();
} }
@@ -475,23 +542,21 @@ void Source::seek(float offset, Source::Unit unit)
} }
else else
{ {
ALint size;
ALuint buffer = unusedBufferPeek();
//emulate AL behavior, discarding buffer once playback head is past one //emulate AL behavior, discarding buffer once playback head is past one
while (buffer != AL_NONE) while (!unusedBuffers.empty())
{ {
ALint size;
auto buffer = unusedBuffers.top();
alGetBufferi(buffer, AL_SIZE, &size); alGetBufferi(buffer, AL_SIZE, &size);
if (offsetSamples < size / (bitDepth / 8 * channels)) if (offsetSamples < size / (bitDepth / 8 * channels))
break; break;
unusedBufferPop(); unusedBuffers.pop();
buffer = unusedBufferPeek();
bufferedBytes -= size; bufferedBytes -= size;
offsetSamples -= size / (bitDepth / 8 * channels); offsetSamples -= size / (bitDepth / 8 * channels);
} }
if (buffer == AL_NONE) if (unusedBuffers.empty())
offsetSamples = 0; offsetSamples = 0;
offsetSeconds = offsetSamples / sampleRate; offsetSeconds = offsetSamples / sampleRate;
} }
@@ -723,28 +788,19 @@ bool Source::queue(void *data, size_t length, int dataSampleRate, int dataBitDep
Lock l = pool->lock(); Lock l = pool->lock();
if (valid) if (unusedBuffers.empty())
{ return false;
ALuint buffer = unusedBufferPeek();
if (buffer == AL_NONE)
return false;
alBufferData(buffer, Audio::getFormat(bitDepth, channels), data, length, sampleRate); auto buffer = unusedBuffers.top();
alSourceQueueBuffers(source, 1, &buffer); unusedBuffers.pop();
unusedBufferPop(); alBufferData(buffer, Audio::getFormat(bitDepth, channels), data, length, sampleRate);
}
else
{
ALuint buffer = unusedBufferPeekNext();
if (buffer == AL_NONE)
return false;
//stack acts as queue while stopped
alBufferData(buffer, Audio::getFormat(bitDepth, channels), data, length, sampleRate);
unusedBufferQueue(buffer);
}
bufferedBytes += length; bufferedBytes += length;
if (valid)
alSourceQueueBuffers(source, 1, &buffer);
else
streamBuffers.push(buffer);
return true; return true;
} }
@@ -755,9 +811,9 @@ int Source::getFreeBufferCount() const
case TYPE_STATIC: case TYPE_STATIC:
return 0; return 0;
case TYPE_STREAM: case TYPE_STREAM:
return unusedBufferTop + 1; return unusedBuffers.size();
case TYPE_QUEUE: case TYPE_QUEUE:
return valid ? unusedBufferTop + 1 : (int)MAX_BUFFERS - unusedBufferTop - 1; return unusedBuffers.size();
case TYPE_MAX_ENUM: case TYPE_MAX_ENUM:
return 0; return 0;
} }
@@ -777,12 +833,14 @@ void Source::prepareAtomic()
alSourcei(source, AL_BUFFER, staticBuffer->getBuffer()); alSourcei(source, AL_BUFFER, staticBuffer->getBuffer());
break; break;
case TYPE_STREAM: case TYPE_STREAM:
while (unusedBufferPeek() != AL_NONE) while (!unusedBuffers.empty())
{ {
if(streamAtomic(unusedBufferPeek(), decoder.get()) == 0) auto b = unusedBuffers.top();
if (streamAtomic(b, decoder.get()) == 0)
break; break;
alSourceQueueBuffers(source, 1, unusedBufferPop()); alSourceQueueBuffers(source, 1, &b);
unusedBuffers.pop();
if (decoder->isFinished()) if (decoder->isFinished())
break; break;
@@ -790,14 +848,11 @@ void Source::prepareAtomic()
break; break;
case TYPE_QUEUE: case TYPE_QUEUE:
{ {
int top = unusedBufferTop; while (!streamBuffers.empty())
//when queue source is stopped, loaded buffers are stored in unused buffers stack {
while (unusedBufferPeek() != AL_NONE) alSourceQueueBuffers(source, 1, &streamBuffers.front());
alSourceQueueBuffers(source, 1, unusedBufferPop()); streamBuffers.pop();
//construct a stack of unused buffers (beyond the end of stack) }
for (unsigned int i = top + 1; i < MAX_BUFFERS; i++)
unusedBufferPush(unusedBuffers[i]);
break; break;
} }
case TYPE_MAX_ENUM: case TYPE_MAX_ENUM:
@@ -821,13 +876,10 @@ void Source::teardownAtomic()
//since we only unqueue 1 buffer, it's OK to use singular variable pointer instead of array //since we only unqueue 1 buffer, it's OK to use singular variable pointer instead of array
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued); alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
for (unsigned int i = 0; i < (unsigned int)queued; i++) for (unsigned int i = 0; i < (unsigned int)queued; i++)
{
alSourceUnqueueBuffers(source, 1, &buffer); alSourceUnqueueBuffers(source, 1, &buffer);
unusedBuffers.push(buffer);
// generate unused buffers list }
for (unsigned int i = 0; i < MAX_BUFFERS; i++)
unusedBuffers[i] = streamBuffers[i];
unusedBufferTop = MAX_BUFFERS - 1;
break; break;
} }
case TYPE_QUEUE: case TYPE_QUEUE:
@@ -837,13 +889,10 @@ void Source::teardownAtomic()
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued); alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
for (unsigned int i = (unsigned int)queued; i > 0; i--) for (unsigned int i = (unsigned int)queued; i > 0; i--)
{
alSourceUnqueueBuffers(source, 1, &buffer); alSourceUnqueueBuffers(source, 1, &buffer);
unusedBuffers.push(buffer);
// generate unused buffers list }
for (unsigned int i = 0; i < MAX_BUFFERS; i++)
unusedBuffers[i] = streamBuffers[i];
unusedBufferTop = -1;
break; break;
} }
case TYPE_MAX_ENUM: case TYPE_MAX_ENUM:
@@ -912,7 +961,8 @@ void Source::resumeAtomic()
{ {
alSourcePlay(source); alSourcePlay(source);
if (alGetError() == AL_INVALID_VALUE || (sourceType == TYPE_STREAM && unusedBufferTop == MAX_BUFFERS - 1)) //failed to play or nothing to play
if (alGetError() == AL_INVALID_VALUE || (sourceType == TYPE_STREAM && unusedBuffers.empty()))
stop(); stop();
} }
} }
@@ -1059,8 +1109,11 @@ void Source::reset()
alSourcef(source, AL_CONE_OUTER_GAINHF, cone.outerHighGain); alSourcef(source, AL_CONE_OUTER_GAINHF, cone.outerHighGain);
alSourcef(source, AL_ROOM_ROLLOFF_FACTOR, rolloffFactor); //reverb-specific rolloff alSourcef(source, AL_ROOM_ROLLOFF_FACTOR, rolloffFactor); //reverb-specific rolloff
alSourcei(source, AL_DIRECT_FILTER, directfilter ? directfilter->getFilter() : AL_FILTER_NULL); alSourcei(source, AL_DIRECT_FILTER, directfilter ? directfilter->getFilter() : AL_FILTER_NULL);
for (unsigned int i = 0; i < sendtargets.size(); i++) // clear all send slots, then re-enable applied ones
alSource3i(source, AL_AUXILIARY_SEND_FILTER, sendtargets[i], i, sendfilters[i] ? sendfilters[i]->getFilter() : AL_FILTER_NULL); for (int i = 0; i < audiomodule()->getMaxSourceEffects(); i++)
alSource3i(source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, i, AL_FILTER_NULL);
for (auto i : effectmap)
alSource3i(source, AL_AUXILIARY_SEND_FILTER, i.second.target, i.second.slot, i.second.filter ? i.second.filter->getFilter() : AL_FILTER_NULL);
//alGetError(); //alGetError();
#endif #endif
} }
@@ -1072,33 +1125,6 @@ void Source::setFloatv(float *dst, const float *src) const
dst[2] = src[2]; dst[2] = src[2];
} }
ALuint Source::unusedBufferPeek()
{
return (unusedBufferTop < 0) ? AL_NONE : unusedBuffers[unusedBufferTop];
}
ALuint Source::unusedBufferPeekNext()
{
return (unusedBufferTop >= (int)MAX_BUFFERS - 1) ? AL_NONE : unusedBuffers[unusedBufferTop + 1];
}
ALuint *Source::unusedBufferPop()
{
return &unusedBuffers[unusedBufferTop--];
}
void Source::unusedBufferPush(ALuint buffer)
{
unusedBuffers[++unusedBufferTop] = buffer;
}
void Source::unusedBufferQueue(ALuint buffer)
{
for (unsigned int i = ++unusedBufferTop; i > 0; i--)
unusedBuffers[i] = unusedBuffers[i - 1];
unusedBuffers[0] = buffer;
}
int Source::streamAtomic(ALuint buffer, love::sound::Decoder *d) int Source::streamAtomic(ALuint buffer, love::sound::Decoder *d)
{ {
// Get more sound data. // Get more sound data.
@@ -1123,7 +1149,7 @@ int Source::streamAtomic(ALuint buffer, love::sound::Decoder *d)
if (queued > processed) if (queued > processed)
toLoop = queued-processed; toLoop = queued-processed;
else else
toLoop = MAX_BUFFERS-processed; toLoop = buffers-processed;
d->rewind(); d->rewind();
} }
@@ -1339,22 +1365,39 @@ bool Source::getFilter(std::map<Filter::Parameter, float> &params)
return true; return true;
} }
bool Source::setSceneEffect(int slot, int effect) bool Source::setEffect(const char *name)
{ {
if (slot < 0 || slot >= (int)sendtargets.size()) ALuint slot, target;
Filter *filter;
// effect with this name doesn't exist
if (!dynamic_cast<Audio*>(audiomodule())->getEffectID(name, target))
return false; return false;
sendtargets[slot] = dynamic_cast<Audio*>(audiomodule())->getSceneEffectID(effect); auto iter = effectmap.find(name);
if (iter == effectmap.end())
{
// new send target needed but no more room
if (slotlist.empty())
return false;
if (sendfilters[slot]) slot = slotlist.top();
delete sendfilters[slot]; slotlist.pop();
}
else
{
slot = iter->second.slot;
filter = iter->second.filter;
sendfilters[slot] = nullptr; if (filter)
delete filter;
}
effectmap[name] = {nullptr, slot, target};
#ifdef ALC_EXT_EFX #ifdef ALC_EXT_EFX
if (valid) if (valid)
{ {
alSource3i(source, AL_AUXILIARY_SEND_FILTER, sendtargets[slot], slot, AL_FILTER_NULL); alSource3i(source, AL_AUXILIARY_SEND_FILTER, target, slot, AL_FILTER_NULL);
//alGetError(); //alGetError();
} }
#endif #endif
@@ -1362,39 +1405,59 @@ bool Source::setSceneEffect(int slot, int effect)
return true; return true;
} }
bool Source::setSceneEffect(int slot, int effect, const std::map<Filter::Parameter, float> &params) bool Source::setEffect(const char *name, const std::map<Filter::Parameter, float> &params)
{ {
if (slot < 0 || slot >= (int)sendtargets.size()) ALuint slot, target;
Filter *filter;
// effect with this name doesn't exist
if (!dynamic_cast<Audio*>(audiomodule())->getEffectID(name, target))
return false; return false;
sendtargets[slot] = dynamic_cast<Audio*>(audiomodule())->getSceneEffectID(effect); auto iter = effectmap.find(name);
if (iter == effectmap.end())
{
// new send target needed but no more room
if (slotlist.empty())
return false;
if (!sendfilters[slot]) slot = slotlist.top();
sendfilters[slot] = new Filter(); slotlist.pop();
}
else
{
slot = iter->second.slot;
filter = iter->second.filter;
}
if (!filter)
filter = new Filter();
sendfilters[slot]->setParams(params); effectmap[name] = {filter, slot, target};
filter->setParams(params);
#ifdef ALC_EXT_EFX #ifdef ALC_EXT_EFX
if (valid) if (valid)
{ {
//in case of failure contains AL_FILTER_NULL, a valid non-filter //in case of failure contains AL_FILTER_NULL, a valid non-filter
alSource3i(source, AL_AUXILIARY_SEND_FILTER, sendtargets[slot], slot, sendfilters[slot]->getFilter()); alSource3i(source, AL_AUXILIARY_SEND_FILTER, target, slot, filter->getFilter());
//alGetError(); //alGetError();
} }
#endif #endif
return true; return true;
} }
bool Source::setSceneEffect(int slot) bool Source::unsetEffect(const char *name)
{ {
if (slot < 0 || slot >= (int)sendtargets.size()) auto iter = effectmap.find(name);
if (iter == effectmap.end())
return false; return false;
sendtargets[slot] = AL_EFFECTSLOT_NULL; ALuint slot = iter->second.slot;
Filter *filter = iter->second.filter;
if (sendfilters[slot]) if (filter)
delete sendfilters[slot]; delete filter;
sendfilters[slot] = nullptr;
#ifdef ALC_EXT_EFX #ifdef ALC_EXT_EFX
if (valid) if (valid)
@@ -1403,22 +1466,32 @@ bool Source::setSceneEffect(int slot)
//alGetError(); //alGetError();
} }
#endif #endif
effectmap.erase(iter);
slotlist.push(slot);
return true;
}
bool Source::getEffect(const char *name, std::map<Filter::Parameter, float> &params)
{
auto iter = effectmap.find(name);
if (iter == effectmap.end())
return false;
if (iter->second.filter)
params = iter->second.filter->getParams();
return true; return true;
} }
bool Source::getSceneEffect(int slot, int &effect, std::map<Filter::Parameter, float> &params) bool Source::getEffectsList(std::vector<std::string> &list)
{ {
if (slot < 0 || slot >= (int)sendtargets.size()) if (effectmap.empty())
return false; return false;
if (sendtargets[slot] == AL_EFFECTSLOT_NULL) list.reserve(effectmap.size());
return false;
effect = dynamic_cast<Audio*>(audiomodule())->getSceneEffectIndex(sendtargets[slot]); for (auto i : effectmap)
list.push_back(i.first);
if(sendfilters[slot])
params = sendfilters[slot]->getParams();
return true; return true;
} }
+20 -17
View File
@@ -33,6 +33,7 @@
// STL // STL
#include <vector> #include <vector>
#include <stack>
// C // C
#include <float.h> #include <float.h>
@@ -99,7 +100,7 @@ public:
Source(Pool *pool, love::sound::SoundData *soundData); Source(Pool *pool, love::sound::SoundData *soundData);
Source(Pool *pool, love::sound::Decoder *decoder); Source(Pool *pool, love::sound::Decoder *decoder);
Source(Pool *pool, int sampleRate, int bitDepth, int channels); Source(Pool *pool, int sampleRate, int bitDepth, int channels, int buffers);
Source(const Source &s); Source(const Source &s);
virtual ~Source(); virtual ~Source();
@@ -147,10 +148,11 @@ public:
virtual bool setFilter(); virtual bool setFilter();
virtual bool getFilter(std::map<Filter::Parameter, float> &params); virtual bool getFilter(std::map<Filter::Parameter, float> &params);
virtual bool setSceneEffect(int slot, int effect); virtual bool setEffect(const char *effect);
virtual bool setSceneEffect(int slot, int effect, const std::map<Filter::Parameter, float> &params); virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params);
virtual bool setSceneEffect(int slot); virtual bool unsetEffect(const char *effect);
virtual bool getSceneEffect(int slot, int &effect, std::map<Filter::Parameter, float> &params); virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params);
virtual bool getEffectsList(std::vector<std::string> &list);
virtual int getFreeBufferCount() const; virtual int getFreeBufferCount() const;
virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels); virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels);
@@ -178,19 +180,14 @@ private:
int streamAtomic(ALuint buffer, love::sound::Decoder *d); int streamAtomic(ALuint buffer, love::sound::Decoder *d);
ALuint unusedBufferPeek();
ALuint unusedBufferPeekNext();
ALuint *unusedBufferPop();
void unusedBufferPush(ALuint buffer);
void unusedBufferQueue(ALuint buffer);
Pool *pool = nullptr; Pool *pool = nullptr;
ALuint source = 0; ALuint source = 0;
bool valid = false; bool valid = false;
static const unsigned int MAX_BUFFERS = 8; const static int DEFAULT_BUFFERS = 8;
ALuint streamBuffers[MAX_BUFFERS]; const static int MAX_BUFFERS = 64;
ALuint unusedBuffers[MAX_BUFFERS]; std::queue<ALuint> streamBuffers;
std::stack<ALuint> unusedBuffers;
StrongRef<StaticDataBuffer> staticBuffer; StrongRef<StaticDataBuffer> staticBuffer;
@@ -226,12 +223,18 @@ private:
StrongRef<love::sound::Decoder> decoder; StrongRef<love::sound::Decoder> decoder;
unsigned int toLoop = 0; unsigned int toLoop = 0;
int unusedBufferTop = -1;
ALsizei bufferedBytes = 0; ALsizei bufferedBytes = 0;
int buffers = 0;
Filter *directfilter = nullptr; Filter *directfilter = nullptr;
std::vector<Filter*> sendfilters;
std::vector<ALint> sendtargets; struct effectmapStorage
{
Filter *filter;
ALuint slot, target;
};
std::map<std::string, struct effectmapStorage> effectmap;
std::stack<ALuint> slotlist;
}; // Source }; // Source
} // openal } // openal
+30 -13
View File
@@ -84,7 +84,7 @@ int w_newQueueableSource(lua_State *L)
Source *t = nullptr; Source *t = nullptr;
luax_catchexcept(L, [&]() { luax_catchexcept(L, [&]() {
t = instance()->newSource((int)luaL_checknumber(L, 1), (int)luaL_checknumber(L, 2), (int)luaL_checknumber(L, 3)); t = instance()->newSource((int)luaL_checknumber(L, 1), (int)luaL_checknumber(L, 2), (int)luaL_checknumber(L, 3), (int)luaL_optnumber(L, 4, 0));
}); });
if (t != nullptr) if (t != nullptr)
@@ -305,13 +305,13 @@ int w_getRecordingDevices(lua_State *L)
return 1; return 1;
} }
int w_setSceneEffect(lua_State *L) int w_setEffect(lua_State *L)
{ {
int slot = luaL_checknumber(L, 1) - 1; const char *namestr = luaL_checkstring(L, 1);
if (lua_gettop(L) == 1 || (lua_gettop(L) == 2 && lua_isnoneornil(L, 2))) if (lua_isnoneornil(L, 2) || (lua_gettop(L) == 2 && lua_isboolean(L, 2) && !lua_toboolean(L, 2)))
{ {
lua_pushboolean(L, instance()->setSceneEffect(slot)); lua_pushboolean(L, instance()->unsetEffect(namestr));
return 1; return 1;
} }
@@ -405,17 +405,17 @@ int w_setSceneEffect(lua_State *L)
lua_pop(L, 1); lua_pop(L, 1);
} }
luax_catchexcept(L, [&]() { lua_pushboolean(L, instance()->setSceneEffect(slot, params)); }); luax_catchexcept(L, [&]() { lua_pushboolean(L, instance()->setEffect(namestr, params)); });
return 1; return 1;
} }
int w_getSceneEffect(lua_State *L) int w_getEffect(lua_State *L)
{ {
int slot = luaL_checknumber(L, 1) - 1; const char *namestr = luaL_checkstring(L, 1);
std::map<Effect::Parameter, float> params; std::map<Effect::Parameter, float> params;
if (!instance()->getSceneEffect(slot, params)) if (!instance()->getEffect(namestr, params))
return 0; return 0;
const char *keystr, *valstr; const char *keystr, *valstr;
@@ -463,6 +463,22 @@ int w_getSceneEffect(lua_State *L)
return 1; return 1;
} }
int w_getEffectsList(lua_State *L)
{
std::vector<std::string> list;
if (!instance()->getEffectsList(list))
return 0;
lua_createtable(L, 0, list.size());
for (unsigned int i = 0; i < list.size(); i++)
{
lua_pushnumber(L, i + 1);
lua_pushstring(L, list[i].c_str());
lua_rawset(L, -3);
}
return 1;
}
int w_getMaxSceneEffects(lua_State *L) int w_getMaxSceneEffects(lua_State *L)
{ {
lua_pushnumber(L, instance()->getMaxSceneEffects()); lua_pushnumber(L, instance()->getMaxSceneEffects());
@@ -475,7 +491,7 @@ int w_getMaxSourceEffects(lua_State *L)
return 1; return 1;
} }
int w_isSceneEffectsSupported(lua_State *L) int w_isEffectsSupported(lua_State *L)
{ {
lua_pushboolean(L, instance()->isEFXsupported()); lua_pushboolean(L, instance()->isEFXsupported());
return 1; return 1;
@@ -505,11 +521,12 @@ static const luaL_Reg functions[] =
{ "setDistanceModel", w_setDistanceModel }, { "setDistanceModel", w_setDistanceModel },
{ "getDistanceModel", w_getDistanceModel }, { "getDistanceModel", w_getDistanceModel },
{ "getRecordingDevices", w_getRecordingDevices }, { "getRecordingDevices", w_getRecordingDevices },
{ "setEffect", w_setSceneEffect }, { "setEffect", w_setEffect },
{ "getEffect", w_getSceneEffect }, { "getEffect", w_getEffect },
{ "getEffectsList", w_getEffectsList },
{ "getMaxSceneEffects", w_getMaxSceneEffects }, { "getMaxSceneEffects", w_getMaxSceneEffects },
{ "getMaxSourceEffects", w_getMaxSourceEffects }, { "getMaxSourceEffects", w_getMaxSourceEffects },
{ "isEffectsSupported", w_isSceneEffectsSupported }, { "isEffectsSupported", w_isEffectsSupported },
{ 0, 0 } { 0, 0 }
}; };
+33 -23
View File
@@ -456,49 +456,58 @@ int w_Source_getFilter(lua_State *L)
return 1; return 1;
} }
int w_Source_setSceneEffect(lua_State *L) int w_Source_setEffect(lua_State *L)
{ {
Source *t = luax_checksource(L, 1); Source *t = luax_checksource(L, 1);
const char *namestr = luaL_checkstring(L, 2);
int slot = luaL_checknumber(L, 2) - 1; // :setEffect(effect, false) = clear effect
if (lua_gettop(L) == 2) if (lua_gettop(L) == 3 && lua_isboolean(L, 3) && !lua_toboolean(L, 3))
{ {
luax_catchexcept(L, [&]() { lua_pushboolean(L, t->setSceneEffect(slot)); }); luax_catchexcept(L, [&]() { lua_pushboolean(L, t->unsetEffect(namestr)); });
return 1;
}
int effect = luaL_checknumber(L, 3) - 1;
if (lua_gettop(L) == 3)
{
luax_catchexcept(L, [&]() { lua_pushboolean(L, t->setSceneEffect(slot, effect)); });
return 1; return 1;
} }
std::map<Filter::Parameter, float> params; std::map<Filter::Parameter, float> params;
if (setFilterReadFilter(L, 4, params) == 1) if (setFilterReadFilter(L, 3, params) == 1)
luax_catchexcept(L, [&]() { lua_pushboolean(L, t->setSceneEffect(slot, effect, params)); }); luax_catchexcept(L, [&]() { lua_pushboolean(L, t->setEffect(namestr, params)); });
else else
luax_catchexcept(L, [&]() { lua_pushboolean(L, t->setSceneEffect(slot, effect)); }); luax_catchexcept(L, [&]() { lua_pushboolean(L, t->setEffect(namestr)); });
return 1; return 1;
} }
int w_Source_getSceneEffect(lua_State *L) int w_Source_getEffect(lua_State *L)
{ {
Source *t = luax_checksource(L, 1); Source *t = luax_checksource(L, 1);
int slot = luaL_checknumber(L, 2) - 1; const char *namestr = luaL_checkstring(L, 2);
int effect;
std::map<Filter::Parameter, float> params; std::map<Filter::Parameter, float> params;
if (!t->getSceneEffect(slot, effect, params)) if (!t->getEffect(namestr, params))
return 0; return 0;
lua_pushnumber(L, effect + 1);
if (params.size() == 0) if (params.size() == 0)
return 1; return 0;
getFilterWriteFilter(L, params); getFilterWriteFilter(L, params);
return 2; return 1;
}
int w_Source_getEffectsList(lua_State *L)
{
Source *t = luax_checksource(L, 1);
std::vector<std::string> list;
if (!t->getEffectsList(list))
return 0;
lua_createtable(L, 0, list.size());
for (unsigned int i = 0; i < list.size(); i++)
{
lua_pushnumber(L, i + 1);
lua_pushstring(L, list[i].c_str());
lua_rawset(L, -3);
}
return 1;
} }
int w_Source_getFreeBufferCount(lua_State *L) int w_Source_getFreeBufferCount(lua_State *L)
@@ -613,8 +622,9 @@ static const luaL_Reg w_Source_functions[] =
{ "setFilter", w_Source_setFilter }, { "setFilter", w_Source_setFilter },
{ "getFilter", w_Source_getFilter }, { "getFilter", w_Source_getFilter },
{ "setEffect", w_Source_setSceneEffect }, { "setEffect", w_Source_setEffect },
{ "getEffect", w_Source_getSceneEffect }, { "getEffect", w_Source_getEffect },
{ "getEffectsList", w_Source_getEffectsList },
{ "getFreeBufferCount", w_Source_getFreeBufferCount }, { "getFreeBufferCount", w_Source_getFreeBufferCount },
{ "queue", w_Source_queue }, { "queue", w_Source_queue },