Avoid AL types and enums in the effect processors
This commit is contained in:
+46
-20
@@ -4,25 +4,50 @@
|
||||
#include "AL/al.h"
|
||||
#include "AL/efx.h"
|
||||
|
||||
#include "aloptional.h"
|
||||
#include "core/logging.h"
|
||||
#include "effects.h"
|
||||
#include "effects/base.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
static_assert(AL_CHORUS_WAVEFORM_SINUSOID == AL_FLANGER_WAVEFORM_SINUSOID, "Chorus/Flanger waveform value mismatch");
|
||||
static_assert(AL_CHORUS_WAVEFORM_TRIANGLE == AL_FLANGER_WAVEFORM_TRIANGLE, "Chorus/Flanger waveform value mismatch");
|
||||
|
||||
inline al::optional<ChorusWaveform> WaveformFromEnum(ALenum type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case AL_CHORUS_WAVEFORM_SINUSOID: return al::make_optional(ChorusWaveform::Sinusoid);
|
||||
case AL_CHORUS_WAVEFORM_TRIANGLE: return al::make_optional(ChorusWaveform::Triangle);
|
||||
}
|
||||
return al::nullopt;
|
||||
}
|
||||
inline ALenum EnumFromWaveform(ChorusWaveform type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ChorusWaveform::Sinusoid: return AL_CHORUS_WAVEFORM_SINUSOID;
|
||||
case ChorusWaveform::Triangle: return AL_CHORUS_WAVEFORM_TRIANGLE;
|
||||
}
|
||||
throw std::runtime_error{"Invalid chorus waveform: "+std::to_string(static_cast<int>(type))};
|
||||
}
|
||||
|
||||
void Chorus_setParami(EffectProps *props, ALenum param, int val)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_CHORUS_WAVEFORM:
|
||||
if(!(val >= AL_CHORUS_MIN_WAVEFORM && val <= AL_CHORUS_MAX_WAVEFORM))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Invalid chorus waveform"};
|
||||
props->Chorus.Waveform = val;
|
||||
if(auto formopt = WaveformFromEnum(val))
|
||||
props->Chorus.Waveform = *formopt;
|
||||
else
|
||||
throw effect_exception{AL_INVALID_VALUE, "Invalid chorus waveform: 0x%04x", val};
|
||||
break;
|
||||
|
||||
case AL_CHORUS_PHASE:
|
||||
if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus phase out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus phase out of range: %d", val};
|
||||
props->Chorus.Phase = val;
|
||||
break;
|
||||
|
||||
@@ -38,25 +63,25 @@ void Chorus_setParamf(EffectProps *props, ALenum param, float val)
|
||||
{
|
||||
case AL_CHORUS_RATE:
|
||||
if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus rate out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus rate out of range: %f", val};
|
||||
props->Chorus.Rate = val;
|
||||
break;
|
||||
|
||||
case AL_CHORUS_DEPTH:
|
||||
if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus depth out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus depth out of range: %f", val};
|
||||
props->Chorus.Depth = val;
|
||||
break;
|
||||
|
||||
case AL_CHORUS_FEEDBACK:
|
||||
if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus feedback out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus feedback out of range: %f", val};
|
||||
props->Chorus.Feedback = val;
|
||||
break;
|
||||
|
||||
case AL_CHORUS_DELAY:
|
||||
if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus delay out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Chorus delay out of range: %f", val};
|
||||
props->Chorus.Delay = val;
|
||||
break;
|
||||
|
||||
@@ -72,7 +97,7 @@ void Chorus_getParami(const EffectProps *props, ALenum param, int *val)
|
||||
switch(param)
|
||||
{
|
||||
case AL_CHORUS_WAVEFORM:
|
||||
*val = props->Chorus.Waveform;
|
||||
*val = EnumFromWaveform(props->Chorus.Waveform);
|
||||
break;
|
||||
|
||||
case AL_CHORUS_PHASE:
|
||||
@@ -115,7 +140,7 @@ void Chorus_getParamfv(const EffectProps *props, ALenum param, float *vals)
|
||||
const EffectProps genDefaultChorusProps() noexcept
|
||||
{
|
||||
EffectProps props{};
|
||||
props.Chorus.Waveform = AL_CHORUS_DEFAULT_WAVEFORM;
|
||||
props.Chorus.Waveform = *WaveformFromEnum(AL_CHORUS_DEFAULT_WAVEFORM);
|
||||
props.Chorus.Phase = AL_CHORUS_DEFAULT_PHASE;
|
||||
props.Chorus.Rate = AL_CHORUS_DEFAULT_RATE;
|
||||
props.Chorus.Depth = AL_CHORUS_DEFAULT_DEPTH;
|
||||
@@ -130,14 +155,15 @@ void Flanger_setParami(EffectProps *props, ALenum param, int val)
|
||||
switch(param)
|
||||
{
|
||||
case AL_FLANGER_WAVEFORM:
|
||||
if(!(val >= AL_FLANGER_MIN_WAVEFORM && val <= AL_FLANGER_MAX_WAVEFORM))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Invalid flanger waveform"};
|
||||
props->Chorus.Waveform = val;
|
||||
if(auto formopt = WaveformFromEnum(val))
|
||||
props->Chorus.Waveform = *formopt;
|
||||
else
|
||||
throw effect_exception{AL_INVALID_VALUE, "Invalid flanger waveform: 0x%04x", val};
|
||||
break;
|
||||
|
||||
case AL_FLANGER_PHASE:
|
||||
if(!(val >= AL_FLANGER_MIN_PHASE && val <= AL_FLANGER_MAX_PHASE))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger phase out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger phase out of range: %d", val};
|
||||
props->Chorus.Phase = val;
|
||||
break;
|
||||
|
||||
@@ -153,25 +179,25 @@ void Flanger_setParamf(EffectProps *props, ALenum param, float val)
|
||||
{
|
||||
case AL_FLANGER_RATE:
|
||||
if(!(val >= AL_FLANGER_MIN_RATE && val <= AL_FLANGER_MAX_RATE))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger rate out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger rate out of range: %f", val};
|
||||
props->Chorus.Rate = val;
|
||||
break;
|
||||
|
||||
case AL_FLANGER_DEPTH:
|
||||
if(!(val >= AL_FLANGER_MIN_DEPTH && val <= AL_FLANGER_MAX_DEPTH))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger depth out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger depth out of range: %f", val};
|
||||
props->Chorus.Depth = val;
|
||||
break;
|
||||
|
||||
case AL_FLANGER_FEEDBACK:
|
||||
if(!(val >= AL_FLANGER_MIN_FEEDBACK && val <= AL_FLANGER_MAX_FEEDBACK))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger feedback out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger feedback out of range: %f", val};
|
||||
props->Chorus.Feedback = val;
|
||||
break;
|
||||
|
||||
case AL_FLANGER_DELAY:
|
||||
if(!(val >= AL_FLANGER_MIN_DELAY && val <= AL_FLANGER_MAX_DELAY))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger delay out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Flanger delay out of range: %f", val};
|
||||
props->Chorus.Delay = val;
|
||||
break;
|
||||
|
||||
@@ -187,7 +213,7 @@ void Flanger_getParami(const EffectProps *props, ALenum param, int *val)
|
||||
switch(param)
|
||||
{
|
||||
case AL_FLANGER_WAVEFORM:
|
||||
*val = props->Chorus.Waveform;
|
||||
*val = EnumFromWaveform(props->Chorus.Waveform);
|
||||
break;
|
||||
|
||||
case AL_FLANGER_PHASE:
|
||||
@@ -230,7 +256,7 @@ void Flanger_getParamfv(const EffectProps *props, ALenum param, float *vals)
|
||||
EffectProps genDefaultFlangerProps() noexcept
|
||||
{
|
||||
EffectProps props{};
|
||||
props.Chorus.Waveform = AL_FLANGER_DEFAULT_WAVEFORM;
|
||||
props.Chorus.Waveform = *WaveformFromEnum(AL_FLANGER_DEFAULT_WAVEFORM);
|
||||
props.Chorus.Phase = AL_FLANGER_DEFAULT_PHASE;
|
||||
props.Chorus.Rate = AL_FLANGER_DEFAULT_RATE;
|
||||
props.Chorus.Depth = AL_FLANGER_DEFAULT_DEPTH;
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
namespace {
|
||||
|
||||
static_assert(EchoMaxDelay >= AL_ECHO_MAX_DELAY, "Echo max delay too short");
|
||||
static_assert(EchoMaxLRDelay >= AL_ECHO_MAX_LRDELAY, "Echo max left-right delay too short");
|
||||
|
||||
void Echo_setParami(EffectProps*, ALenum param, int)
|
||||
{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; }
|
||||
void Echo_setParamiv(EffectProps*, ALenum param, const int*)
|
||||
|
||||
+34
-10
@@ -4,12 +4,34 @@
|
||||
#include "AL/al.h"
|
||||
#include "AL/efx.h"
|
||||
|
||||
#include "aloptional.h"
|
||||
#include "effects.h"
|
||||
#include "effects/base.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
al::optional<FShifterDirection> DirectionFromEmum(ALenum value)
|
||||
{
|
||||
switch(value)
|
||||
{
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN: return al::make_optional(FShifterDirection::Down);
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_UP: return al::make_optional(FShifterDirection::Up);
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_OFF: return al::make_optional(FShifterDirection::Off);
|
||||
}
|
||||
return al::nullopt;
|
||||
}
|
||||
ALenum EnumFromDirection(FShifterDirection dir)
|
||||
{
|
||||
switch(dir)
|
||||
{
|
||||
case FShifterDirection::Down: return AL_FREQUENCY_SHIFTER_DIRECTION_DOWN;
|
||||
case FShifterDirection::Up: return AL_FREQUENCY_SHIFTER_DIRECTION_UP;
|
||||
case FShifterDirection::Off: return AL_FREQUENCY_SHIFTER_DIRECTION_OFF;
|
||||
}
|
||||
throw std::runtime_error{"Invalid direction: "+std::to_string(static_cast<int>(dir))};
|
||||
}
|
||||
|
||||
void Fshifter_setParamf(EffectProps *props, ALenum param, float val)
|
||||
{
|
||||
switch(param)
|
||||
@@ -33,17 +55,19 @@ void Fshifter_setParami(EffectProps *props, ALenum param, int val)
|
||||
switch(param)
|
||||
{
|
||||
case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
|
||||
if(!(val >= AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION && val <= AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION))
|
||||
if(auto diropt = DirectionFromEmum(val))
|
||||
props->Fshifter.LeftDirection = *diropt;
|
||||
else
|
||||
throw effect_exception{AL_INVALID_VALUE,
|
||||
"Frequency shifter left direction out of range"};
|
||||
props->Fshifter.LeftDirection = val;
|
||||
"Unsupported frequency shifter left direction: 0x%04x", val};
|
||||
break;
|
||||
|
||||
case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
|
||||
if(!(val >= AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION && val <= AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION))
|
||||
if(auto diropt = DirectionFromEmum(val))
|
||||
props->Fshifter.RightDirection = *diropt;
|
||||
else
|
||||
throw effect_exception{AL_INVALID_VALUE,
|
||||
"Frequency shifter right direction out of range"};
|
||||
props->Fshifter.RightDirection = val;
|
||||
"Unsupported frequency shifter right direction: 0x%04x", val};
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -59,10 +83,10 @@ void Fshifter_getParami(const EffectProps *props, ALenum param, int *val)
|
||||
switch(param)
|
||||
{
|
||||
case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION:
|
||||
*val = props->Fshifter.LeftDirection;
|
||||
*val = EnumFromDirection(props->Fshifter.LeftDirection);
|
||||
break;
|
||||
case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION:
|
||||
*val = props->Fshifter.RightDirection;
|
||||
*val = EnumFromDirection(props->Fshifter.RightDirection);
|
||||
break;
|
||||
default:
|
||||
throw effect_exception{AL_INVALID_ENUM,
|
||||
@@ -92,8 +116,8 @@ EffectProps genDefaultProps() noexcept
|
||||
{
|
||||
EffectProps props{};
|
||||
props.Fshifter.Frequency = AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY;
|
||||
props.Fshifter.LeftDirection = AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION;
|
||||
props.Fshifter.RightDirection = AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION;
|
||||
props.Fshifter.LeftDirection = *DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION);
|
||||
props.Fshifter.RightDirection = *DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION);
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,25 +4,48 @@
|
||||
#include "AL/al.h"
|
||||
#include "AL/efx.h"
|
||||
|
||||
#include "aloptional.h"
|
||||
#include "effects.h"
|
||||
#include "effects/base.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
al::optional<ModulatorWaveform> WaveformFromEmum(ALenum value)
|
||||
{
|
||||
switch(value)
|
||||
{
|
||||
case AL_RING_MODULATOR_SINUSOID: return al::make_optional(ModulatorWaveform::Sinusoid);
|
||||
case AL_RING_MODULATOR_SAWTOOTH: return al::make_optional(ModulatorWaveform::Sawtooth);
|
||||
case AL_RING_MODULATOR_SQUARE: return al::make_optional(ModulatorWaveform::Square);
|
||||
}
|
||||
return al::nullopt;
|
||||
}
|
||||
ALenum EnumFromWaveform(ModulatorWaveform type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ModulatorWaveform::Sinusoid: return AL_RING_MODULATOR_SINUSOID;
|
||||
case ModulatorWaveform::Sawtooth: return AL_RING_MODULATOR_SAWTOOTH;
|
||||
case ModulatorWaveform::Square: return AL_RING_MODULATOR_SQUARE;
|
||||
}
|
||||
throw std::runtime_error{"Invalid modulator waveform: " +
|
||||
std::to_string(static_cast<int>(type))};
|
||||
}
|
||||
|
||||
void Modulator_setParamf(EffectProps *props, ALenum param, float val)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_RING_MODULATOR_FREQUENCY:
|
||||
if(!(val >= AL_RING_MODULATOR_MIN_FREQUENCY && val <= AL_RING_MODULATOR_MAX_FREQUENCY))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Modulator frequency out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Modulator frequency out of range: %f", val};
|
||||
props->Modulator.Frequency = val;
|
||||
break;
|
||||
|
||||
case AL_RING_MODULATOR_HIGHPASS_CUTOFF:
|
||||
if(!(val >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && val <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Modulator high-pass cutoff out of range"};
|
||||
throw effect_exception{AL_INVALID_VALUE, "Modulator high-pass cutoff out of range: %f", val};
|
||||
props->Modulator.HighPassCutoff = val;
|
||||
break;
|
||||
|
||||
@@ -42,9 +65,10 @@ void Modulator_setParami(EffectProps *props, ALenum param, int val)
|
||||
break;
|
||||
|
||||
case AL_RING_MODULATOR_WAVEFORM:
|
||||
if(!(val >= AL_RING_MODULATOR_MIN_WAVEFORM && val <= AL_RING_MODULATOR_MAX_WAVEFORM))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Invalid modulator waveform"};
|
||||
props->Modulator.Waveform = val;
|
||||
if(auto formopt = WaveformFromEmum(val))
|
||||
props->Modulator.Waveform = *formopt;
|
||||
else
|
||||
throw effect_exception{AL_INVALID_VALUE, "Invalid modulator waveform: 0x%04x", val};
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -66,7 +90,7 @@ void Modulator_getParami(const EffectProps *props, ALenum param, int *val)
|
||||
*val = static_cast<int>(props->Modulator.HighPassCutoff);
|
||||
break;
|
||||
case AL_RING_MODULATOR_WAVEFORM:
|
||||
*val = props->Modulator.Waveform;
|
||||
*val = EnumFromWaveform(props->Modulator.Waveform);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -99,7 +123,7 @@ EffectProps genDefaultProps() noexcept
|
||||
EffectProps props{};
|
||||
props.Modulator.Frequency = AL_RING_MODULATOR_DEFAULT_FREQUENCY;
|
||||
props.Modulator.HighPassCutoff = AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF;
|
||||
props.Modulator.Waveform = AL_RING_MODULATOR_DEFAULT_WAVEFORM;
|
||||
props.Modulator.Waveform = *WaveformFromEmum(AL_RING_MODULATOR_DEFAULT_WAVEFORM);
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
+130
-24
@@ -4,32 +4,124 @@
|
||||
#include "AL/al.h"
|
||||
#include "AL/efx.h"
|
||||
|
||||
#include "aloptional.h"
|
||||
#include "effects.h"
|
||||
#include "effects/base.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
al::optional<VMorpherPhenome> PhenomeFromEnum(ALenum val)
|
||||
{
|
||||
#define HANDLE_PHENOME(x) case AL_VOCAL_MORPHER_PHONEME_ ## x: \
|
||||
return al::make_optional(VMorpherPhenome::x)
|
||||
switch(val)
|
||||
{
|
||||
HANDLE_PHENOME(A);
|
||||
HANDLE_PHENOME(E);
|
||||
HANDLE_PHENOME(I);
|
||||
HANDLE_PHENOME(O);
|
||||
HANDLE_PHENOME(U);
|
||||
HANDLE_PHENOME(AA);
|
||||
HANDLE_PHENOME(AE);
|
||||
HANDLE_PHENOME(AH);
|
||||
HANDLE_PHENOME(AO);
|
||||
HANDLE_PHENOME(EH);
|
||||
HANDLE_PHENOME(ER);
|
||||
HANDLE_PHENOME(IH);
|
||||
HANDLE_PHENOME(IY);
|
||||
HANDLE_PHENOME(UH);
|
||||
HANDLE_PHENOME(UW);
|
||||
HANDLE_PHENOME(B);
|
||||
HANDLE_PHENOME(D);
|
||||
HANDLE_PHENOME(F);
|
||||
HANDLE_PHENOME(G);
|
||||
HANDLE_PHENOME(J);
|
||||
HANDLE_PHENOME(K);
|
||||
HANDLE_PHENOME(L);
|
||||
HANDLE_PHENOME(M);
|
||||
HANDLE_PHENOME(N);
|
||||
HANDLE_PHENOME(P);
|
||||
HANDLE_PHENOME(R);
|
||||
HANDLE_PHENOME(S);
|
||||
HANDLE_PHENOME(T);
|
||||
HANDLE_PHENOME(V);
|
||||
HANDLE_PHENOME(Z);
|
||||
}
|
||||
return al::nullopt;
|
||||
#undef HANDLE_PHENOME
|
||||
}
|
||||
ALenum EnumFromPhenome(VMorpherPhenome phenome)
|
||||
{
|
||||
#define HANDLE_PHENOME(x) case VMorpherPhenome::x: return AL_VOCAL_MORPHER_PHONEME_ ## x
|
||||
switch(phenome)
|
||||
{
|
||||
HANDLE_PHENOME(A);
|
||||
HANDLE_PHENOME(E);
|
||||
HANDLE_PHENOME(I);
|
||||
HANDLE_PHENOME(O);
|
||||
HANDLE_PHENOME(U);
|
||||
HANDLE_PHENOME(AA);
|
||||
HANDLE_PHENOME(AE);
|
||||
HANDLE_PHENOME(AH);
|
||||
HANDLE_PHENOME(AO);
|
||||
HANDLE_PHENOME(EH);
|
||||
HANDLE_PHENOME(ER);
|
||||
HANDLE_PHENOME(IH);
|
||||
HANDLE_PHENOME(IY);
|
||||
HANDLE_PHENOME(UH);
|
||||
HANDLE_PHENOME(UW);
|
||||
HANDLE_PHENOME(B);
|
||||
HANDLE_PHENOME(D);
|
||||
HANDLE_PHENOME(F);
|
||||
HANDLE_PHENOME(G);
|
||||
HANDLE_PHENOME(J);
|
||||
HANDLE_PHENOME(K);
|
||||
HANDLE_PHENOME(L);
|
||||
HANDLE_PHENOME(M);
|
||||
HANDLE_PHENOME(N);
|
||||
HANDLE_PHENOME(P);
|
||||
HANDLE_PHENOME(R);
|
||||
HANDLE_PHENOME(S);
|
||||
HANDLE_PHENOME(T);
|
||||
HANDLE_PHENOME(V);
|
||||
HANDLE_PHENOME(Z);
|
||||
}
|
||||
throw std::runtime_error{"Invalid phenome: "+std::to_string(static_cast<int>(phenome))};
|
||||
#undef HANDLE_PHENOME
|
||||
}
|
||||
|
||||
al::optional<VMorpherWaveform> WaveformFromEmum(ALenum value)
|
||||
{
|
||||
switch(value)
|
||||
{
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_SINUSOID: return al::make_optional(VMorpherWaveform::Sinusoid);
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE: return al::make_optional(VMorpherWaveform::Triangle);
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH: return al::make_optional(VMorpherWaveform::Sawtooth);
|
||||
}
|
||||
return al::nullopt;
|
||||
}
|
||||
ALenum EnumFromWaveform(VMorpherWaveform type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case VMorpherWaveform::Sinusoid: return AL_VOCAL_MORPHER_WAVEFORM_SINUSOID;
|
||||
case VMorpherWaveform::Triangle: return AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE;
|
||||
case VMorpherWaveform::Sawtooth: return AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH;
|
||||
}
|
||||
throw std::runtime_error{"Invalid vocal morpher waveform: " +
|
||||
std::to_string(static_cast<int>(type))};
|
||||
}
|
||||
|
||||
void Vmorpher_setParami(EffectProps *props, ALenum param, int val)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_VOCAL_MORPHER_WAVEFORM:
|
||||
if(!(val >= AL_VOCAL_MORPHER_MIN_WAVEFORM && val <= AL_VOCAL_MORPHER_MAX_WAVEFORM))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher waveform out of range"};
|
||||
props->Vmorpher.Waveform = val;
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEA:
|
||||
if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEA && val <= AL_VOCAL_MORPHER_MAX_PHONEMEA))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a out of range"};
|
||||
props->Vmorpher.PhonemeA = val;
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEB:
|
||||
if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEB && val <= AL_VOCAL_MORPHER_MAX_PHONEMEB))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b out of range"};
|
||||
props->Vmorpher.PhonemeB = val;
|
||||
if(auto phenomeopt = PhenomeFromEnum(val))
|
||||
props->Vmorpher.PhonemeA = *phenomeopt;
|
||||
else
|
||||
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a out of range: 0x%04x", val};
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING:
|
||||
@@ -38,12 +130,26 @@ void Vmorpher_setParami(EffectProps *props, ALenum param, int val)
|
||||
props->Vmorpher.PhonemeACoarseTuning = val;
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEB:
|
||||
if(auto phenomeopt = PhenomeFromEnum(val))
|
||||
props->Vmorpher.PhonemeB = *phenomeopt;
|
||||
else
|
||||
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b out of range: 0x%04x", val};
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING:
|
||||
if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING))
|
||||
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b coarse tuning out of range"};
|
||||
props->Vmorpher.PhonemeBCoarseTuning = val;
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_WAVEFORM:
|
||||
if(auto formopt = WaveformFromEmum(val))
|
||||
props->Vmorpher.Waveform = *formopt;
|
||||
else
|
||||
throw effect_exception{AL_INVALID_VALUE, "Vocal morpher waveform out of range: 0x%04x", val};
|
||||
break;
|
||||
|
||||
default:
|
||||
throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x",
|
||||
param};
|
||||
@@ -77,23 +183,23 @@ void Vmorpher_getParami(const EffectProps *props, ALenum param, int* val)
|
||||
switch(param)
|
||||
{
|
||||
case AL_VOCAL_MORPHER_PHONEMEA:
|
||||
*val = props->Vmorpher.PhonemeA;
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEB:
|
||||
*val = props->Vmorpher.PhonemeB;
|
||||
*val = EnumFromPhenome(props->Vmorpher.PhonemeA);
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING:
|
||||
*val = props->Vmorpher.PhonemeACoarseTuning;
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEB:
|
||||
*val = EnumFromPhenome(props->Vmorpher.PhonemeB);
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING:
|
||||
*val = props->Vmorpher.PhonemeBCoarseTuning;
|
||||
break;
|
||||
|
||||
case AL_VOCAL_MORPHER_WAVEFORM:
|
||||
*val = props->Vmorpher.Waveform;
|
||||
*val = EnumFromWaveform(props->Vmorpher.Waveform);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -126,11 +232,11 @@ EffectProps genDefaultProps() noexcept
|
||||
{
|
||||
EffectProps props{};
|
||||
props.Vmorpher.Rate = AL_VOCAL_MORPHER_DEFAULT_RATE;
|
||||
props.Vmorpher.PhonemeA = AL_VOCAL_MORPHER_DEFAULT_PHONEMEA;
|
||||
props.Vmorpher.PhonemeB = AL_VOCAL_MORPHER_DEFAULT_PHONEMEB;
|
||||
props.Vmorpher.PhonemeA = *PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEA);
|
||||
props.Vmorpher.PhonemeB = *PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEB);
|
||||
props.Vmorpher.PhonemeACoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING;
|
||||
props.Vmorpher.PhonemeBCoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING;
|
||||
props.Vmorpher.Waveform = AL_VOCAL_MORPHER_DEFAULT_WAVEFORM;
|
||||
props.Vmorpher.Waveform = *WaveformFromEmum(AL_VOCAL_MORPHER_DEFAULT_WAVEFORM);
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
+39
-7
@@ -13,6 +13,38 @@ struct EffectSlot;
|
||||
struct BufferStorage;
|
||||
|
||||
|
||||
enum class ChorusWaveform {
|
||||
Sinusoid,
|
||||
Triangle
|
||||
};
|
||||
|
||||
constexpr float EchoMaxDelay{0.207f};
|
||||
constexpr float EchoMaxLRDelay{0.404f};
|
||||
|
||||
enum class FShifterDirection {
|
||||
Down,
|
||||
Up,
|
||||
Off
|
||||
};
|
||||
|
||||
enum class ModulatorWaveform {
|
||||
Sinusoid,
|
||||
Sawtooth,
|
||||
Square
|
||||
};
|
||||
|
||||
enum class VMorpherPhenome {
|
||||
A, E, I, O, U,
|
||||
AA, AE, AH, AO, EH, ER, IH, IY, UH, UW,
|
||||
B, D, F, G, J, K, L, M, N, P, R, S, T, V, Z
|
||||
};
|
||||
|
||||
enum class VMorpherWaveform {
|
||||
Sinusoid,
|
||||
Triangle,
|
||||
Sawtooth
|
||||
};
|
||||
|
||||
union EffectProps {
|
||||
struct {
|
||||
// Shared Reverb Properties
|
||||
@@ -51,7 +83,7 @@ union EffectProps {
|
||||
} Autowah;
|
||||
|
||||
struct {
|
||||
int Waveform;
|
||||
ChorusWaveform Waveform;
|
||||
int Phase;
|
||||
float Rate;
|
||||
float Depth;
|
||||
@@ -96,14 +128,14 @@ union EffectProps {
|
||||
|
||||
struct {
|
||||
float Frequency;
|
||||
int LeftDirection;
|
||||
int RightDirection;
|
||||
FShifterDirection LeftDirection;
|
||||
FShifterDirection RightDirection;
|
||||
} Fshifter;
|
||||
|
||||
struct {
|
||||
float Frequency;
|
||||
float HighPassCutoff;
|
||||
int Waveform;
|
||||
ModulatorWaveform Waveform;
|
||||
} Modulator;
|
||||
|
||||
struct {
|
||||
@@ -113,11 +145,11 @@ union EffectProps {
|
||||
|
||||
struct {
|
||||
float Rate;
|
||||
int PhonemeA;
|
||||
int PhonemeB;
|
||||
VMorpherPhenome PhonemeA;
|
||||
VMorpherPhenome PhonemeB;
|
||||
int PhonemeACoarseTuning;
|
||||
int PhonemeBCoarseTuning;
|
||||
int Waveform;
|
||||
VMorpherWaveform Waveform;
|
||||
} Vmorpher;
|
||||
|
||||
struct {
|
||||
|
||||
+32
-52
@@ -26,11 +26,6 @@
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/efx.h"
|
||||
|
||||
#include "al/auxeffectslot.h"
|
||||
#include "alcmain.h"
|
||||
#include "alcontext.h"
|
||||
#include "almalloc.h"
|
||||
@@ -39,6 +34,7 @@
|
||||
#include "alu.h"
|
||||
#include "core/ambidefs.h"
|
||||
#include "effects/base.h"
|
||||
#include "effectslot.h"
|
||||
#include "math_defs.h"
|
||||
#include "opthelpers.h"
|
||||
#include "vector.h"
|
||||
@@ -46,24 +42,16 @@
|
||||
|
||||
namespace {
|
||||
|
||||
static_assert(AL_CHORUS_WAVEFORM_SINUSOID == AL_FLANGER_WAVEFORM_SINUSOID, "Chorus/Flanger waveform value mismatch");
|
||||
static_assert(AL_CHORUS_WAVEFORM_TRIANGLE == AL_FLANGER_WAVEFORM_TRIANGLE, "Chorus/Flanger waveform value mismatch");
|
||||
|
||||
enum class WaveForm {
|
||||
Sinusoid,
|
||||
Triangle
|
||||
};
|
||||
|
||||
#define MAX_UPDATE_SAMPLES 256
|
||||
|
||||
struct ChorusState final : public EffectState {
|
||||
al::vector<float,16> mSampleBuffer;
|
||||
ALuint mOffset{0};
|
||||
uint mOffset{0};
|
||||
|
||||
ALuint mLfoOffset{0};
|
||||
ALuint mLfoRange{1};
|
||||
uint mLfoOffset{0};
|
||||
uint mLfoRange{1};
|
||||
float mLfoScale{0.0f};
|
||||
ALuint mLfoDisp{0};
|
||||
uint mLfoDisp{0};
|
||||
|
||||
/* Gains for left and right sides */
|
||||
struct {
|
||||
@@ -72,13 +60,13 @@ struct ChorusState final : public EffectState {
|
||||
} mGains[2];
|
||||
|
||||
/* effect parameters */
|
||||
WaveForm mWaveform{};
|
||||
ChorusWaveform mWaveform{};
|
||||
int mDelay{0};
|
||||
float mDepth{0.0f};
|
||||
float mFeedback{0.0f};
|
||||
|
||||
void getTriangleDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo);
|
||||
void getSinusoidDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo);
|
||||
void getTriangleDelays(uint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo);
|
||||
void getSinusoidDelays(uint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo);
|
||||
|
||||
void deviceUpdate(const ALCdevice *device) override;
|
||||
void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props,
|
||||
@@ -111,22 +99,14 @@ void ChorusState::update(const ALCcontext *Context, const EffectSlot *Slot,
|
||||
{
|
||||
constexpr int mindelay{(MaxResamplerPadding>>1) << MixerFracBits};
|
||||
|
||||
switch(props->Chorus.Waveform)
|
||||
{
|
||||
case AL_CHORUS_WAVEFORM_TRIANGLE:
|
||||
mWaveform = WaveForm::Triangle;
|
||||
break;
|
||||
case AL_CHORUS_WAVEFORM_SINUSOID:
|
||||
mWaveform = WaveForm::Sinusoid;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The LFO depth is scaled to be relative to the sample delay. Clamp the
|
||||
* delay and depth to allow enough padding for resampling.
|
||||
*/
|
||||
const ALCdevice *device{Context->mDevice.get()};
|
||||
const auto frequency = static_cast<float>(device->Frequency);
|
||||
|
||||
mWaveform = props->Chorus.Waveform;
|
||||
|
||||
mDelay = maxi(float2int(props->Chorus.Delay*frequency*MixerFracOne + 0.5f), mindelay);
|
||||
mDepth = minf(props->Chorus.Depth * static_cast<float>(mDelay),
|
||||
static_cast<float>(mDelay - mindelay));
|
||||
@@ -154,16 +134,16 @@ void ChorusState::update(const ALCcontext *Context, const EffectSlot *Slot,
|
||||
/* Calculate LFO coefficient (number of samples per cycle). Limit the
|
||||
* max range to avoid overflow when calculating the displacement.
|
||||
*/
|
||||
ALuint lfo_range{float2uint(minf(frequency/rate + 0.5f, float{INT_MAX/360 - 180}))};
|
||||
uint lfo_range{float2uint(minf(frequency/rate + 0.5f, float{INT_MAX/360 - 180}))};
|
||||
|
||||
mLfoOffset = mLfoOffset * lfo_range / mLfoRange;
|
||||
mLfoRange = lfo_range;
|
||||
switch(mWaveform)
|
||||
{
|
||||
case WaveForm::Triangle:
|
||||
case ChorusWaveform::Triangle:
|
||||
mLfoScale = 4.0f / static_cast<float>(mLfoRange);
|
||||
break;
|
||||
case WaveForm::Sinusoid:
|
||||
case ChorusWaveform::Sinusoid:
|
||||
mLfoScale = al::MathDefs<float>::Tau() / static_cast<float>(mLfoRange);
|
||||
break;
|
||||
}
|
||||
@@ -171,14 +151,14 @@ void ChorusState::update(const ALCcontext *Context, const EffectSlot *Slot,
|
||||
/* Calculate lfo phase displacement */
|
||||
int phase{props->Chorus.Phase};
|
||||
if(phase < 0) phase = 360 + phase;
|
||||
mLfoDisp = (mLfoRange*static_cast<ALuint>(phase) + 180) / 360;
|
||||
mLfoDisp = (mLfoRange*static_cast<uint>(phase) + 180) / 360;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ChorusState::getTriangleDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo)
|
||||
void ChorusState::getTriangleDelays(uint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo)
|
||||
{
|
||||
const ALuint lfo_range{mLfoRange};
|
||||
const uint lfo_range{mLfoRange};
|
||||
const float lfo_scale{mLfoScale};
|
||||
const float depth{mDepth};
|
||||
const int delay{mDelay};
|
||||
@@ -186,24 +166,24 @@ void ChorusState::getTriangleDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const
|
||||
ASSUME(lfo_range > 0);
|
||||
ASSUME(todo > 0);
|
||||
|
||||
ALuint offset{mLfoOffset};
|
||||
auto gen_lfo = [&offset,lfo_range,lfo_scale,depth,delay]() -> ALuint
|
||||
uint offset{mLfoOffset};
|
||||
auto gen_lfo = [&offset,lfo_range,lfo_scale,depth,delay]() -> uint
|
||||
{
|
||||
offset = (offset+1)%lfo_range;
|
||||
const float offset_norm{static_cast<float>(offset) * lfo_scale};
|
||||
return static_cast<ALuint>(fastf2i((1.0f-std::abs(2.0f-offset_norm)) * depth) + delay);
|
||||
return static_cast<uint>(fastf2i((1.0f-std::abs(2.0f-offset_norm)) * depth) + delay);
|
||||
};
|
||||
std::generate_n(delays[0], todo, gen_lfo);
|
||||
|
||||
offset = (mLfoOffset+mLfoDisp) % lfo_range;
|
||||
std::generate_n(delays[1], todo, gen_lfo);
|
||||
|
||||
mLfoOffset = static_cast<ALuint>(mLfoOffset+todo) % lfo_range;
|
||||
mLfoOffset = static_cast<uint>(mLfoOffset+todo) % lfo_range;
|
||||
}
|
||||
|
||||
void ChorusState::getSinusoidDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo)
|
||||
void ChorusState::getSinusoidDelays(uint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo)
|
||||
{
|
||||
const ALuint lfo_range{mLfoRange};
|
||||
const uint lfo_range{mLfoRange};
|
||||
const float lfo_scale{mLfoScale};
|
||||
const float depth{mDepth};
|
||||
const int delay{mDelay};
|
||||
@@ -211,37 +191,37 @@ void ChorusState::getSinusoidDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const
|
||||
ASSUME(lfo_range > 0);
|
||||
ASSUME(todo > 0);
|
||||
|
||||
ALuint offset{mLfoOffset};
|
||||
auto gen_lfo = [&offset,lfo_range,lfo_scale,depth,delay]() -> ALuint
|
||||
uint offset{mLfoOffset};
|
||||
auto gen_lfo = [&offset,lfo_range,lfo_scale,depth,delay]() -> uint
|
||||
{
|
||||
offset = (offset+1)%lfo_range;
|
||||
const float offset_norm{static_cast<float>(offset) * lfo_scale};
|
||||
return static_cast<ALuint>(fastf2i(std::sin(offset_norm)*depth) + delay);
|
||||
return static_cast<uint>(fastf2i(std::sin(offset_norm)*depth) + delay);
|
||||
};
|
||||
std::generate_n(delays[0], todo, gen_lfo);
|
||||
|
||||
offset = (mLfoOffset+mLfoDisp) % lfo_range;
|
||||
std::generate_n(delays[1], todo, gen_lfo);
|
||||
|
||||
mLfoOffset = static_cast<ALuint>(mLfoOffset+todo) % lfo_range;
|
||||
mLfoOffset = static_cast<uint>(mLfoOffset+todo) % lfo_range;
|
||||
}
|
||||
|
||||
void ChorusState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut)
|
||||
{
|
||||
const size_t bufmask{mSampleBuffer.size()-1};
|
||||
const float feedback{mFeedback};
|
||||
const ALuint avgdelay{(static_cast<ALuint>(mDelay) + (MixerFracOne>>1)) >> MixerFracBits};
|
||||
const uint avgdelay{(static_cast<uint>(mDelay) + (MixerFracOne>>1)) >> MixerFracBits};
|
||||
float *RESTRICT delaybuf{mSampleBuffer.data()};
|
||||
ALuint offset{mOffset};
|
||||
uint offset{mOffset};
|
||||
|
||||
for(size_t base{0u};base < samplesToDo;)
|
||||
{
|
||||
const size_t todo{minz(MAX_UPDATE_SAMPLES, samplesToDo-base)};
|
||||
|
||||
ALuint moddelays[2][MAX_UPDATE_SAMPLES];
|
||||
if(mWaveform == WaveForm::Sinusoid)
|
||||
uint moddelays[2][MAX_UPDATE_SAMPLES];
|
||||
if(mWaveform == ChorusWaveform::Sinusoid)
|
||||
getSinusoidDelays(moddelays, todo);
|
||||
else /*if(mWaveform == WaveForm::Triangle)*/
|
||||
else /*if(mWaveform == ChorusWaveform::Triangle)*/
|
||||
getTriangleDelays(moddelays, todo);
|
||||
|
||||
alignas(16) float temps[2][MAX_UPDATE_SAMPLES];
|
||||
@@ -251,7 +231,7 @@ void ChorusState::process(const size_t samplesToDo, const al::span<const FloatBu
|
||||
delaybuf[offset&bufmask] = samplesIn[0][base+i];
|
||||
|
||||
// Tap for the left output.
|
||||
ALuint delay{offset - (moddelays[0][i]>>MixerFracBits)};
|
||||
uint delay{offset - (moddelays[0][i]>>MixerFracBits)};
|
||||
float mu{static_cast<float>(moddelays[0][i]&MixerFracMask) * (1.0f/MixerFracOne)};
|
||||
temps[0][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask],
|
||||
delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask], mu);
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "al/auxeffectslot.h"
|
||||
#include "alcmain.h"
|
||||
#include "alcontext.h"
|
||||
#include "alu.h"
|
||||
#include "effectslot.h"
|
||||
#include "vecmat.h"
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_SSE_INTRINSICS
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#include "alcmain.h"
|
||||
#include "alcomplex.h"
|
||||
#include "alcontext.h"
|
||||
@@ -143,7 +142,7 @@ struct ConvolutionState final : public EffectState {
|
||||
FmtChannels mChannels{};
|
||||
AmbiLayout mAmbiLayout{};
|
||||
AmbiScaling mAmbiScaling{};
|
||||
ALuint mAmbiOrder{};
|
||||
uint mAmbiOrder{};
|
||||
|
||||
size_t mFifoPos{0};
|
||||
std::array<float,ConvolveUpdateSamples*2> mInput{};
|
||||
@@ -211,7 +210,7 @@ void ConvolutionState::deviceUpdate(const ALCdevice* /*device*/)
|
||||
|
||||
void ConvolutionState::setBuffer(const ALCdevice *device, const BufferStorage *buffer)
|
||||
{
|
||||
constexpr ALuint MaxConvolveAmbiOrder{1u};
|
||||
constexpr uint MaxConvolveAmbiOrder{1u};
|
||||
|
||||
mFifoPos = 0;
|
||||
mInput.fill(0.0f);
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
#include "al/auxeffectslot.h"
|
||||
#include "alcmain.h"
|
||||
#include "alcontext.h"
|
||||
#include "alu.h"
|
||||
#include "effectslot.h"
|
||||
|
||||
|
||||
namespace {
|
||||
@@ -60,7 +60,7 @@ void DedicatedState::update(const ALCcontext*, const EffectSlot *slot,
|
||||
|
||||
if(slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
|
||||
{
|
||||
const ALuint idx{!target.RealOut ? INVALID_CHANNEL_INDEX :
|
||||
const uint idx{!target.RealOut ? INVALID_CHANNEL_INDEX :
|
||||
GetChannelIdxByName(*target.RealOut, LFE)};
|
||||
if(idx != INVALID_CHANNEL_INDEX)
|
||||
{
|
||||
@@ -72,7 +72,7 @@ void DedicatedState::update(const ALCcontext*, const EffectSlot *slot,
|
||||
{
|
||||
/* Dialog goes to the front-center speaker if it exists, otherwise it
|
||||
* plays from the front-center location. */
|
||||
const ALuint idx{!target.RealOut ? INVALID_CHANNEL_INDEX :
|
||||
const uint idx{!target.RealOut ? INVALID_CHANNEL_INDEX :
|
||||
GetChannelIdxByName(*target.RealOut, FrontCenter)};
|
||||
if(idx != INVALID_CHANNEL_INDEX)
|
||||
{
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "AL/efx.h"
|
||||
|
||||
#include "alcmain.h"
|
||||
#include "alcontext.h"
|
||||
#include "core/filters/biquad.h"
|
||||
@@ -74,8 +72,8 @@ void EchoState::deviceUpdate(const ALCdevice *Device)
|
||||
|
||||
// Use the next power of 2 for the buffer length, so the tap offsets can be
|
||||
// wrapped using a mask instead of a modulo
|
||||
const ALuint maxlen{NextPowerOf2(float2uint(AL_ECHO_MAX_DELAY*frequency + 0.5f) +
|
||||
float2uint(AL_ECHO_MAX_LRDELAY*frequency + 0.5f))};
|
||||
const uint maxlen{NextPowerOf2(float2uint(EchoMaxDelay*frequency + 0.5f) +
|
||||
float2uint(EchoMaxLRDelay*frequency + 0.5f))};
|
||||
if(maxlen != mSampleBuffer.size())
|
||||
al::vector<float,16>(maxlen).swap(mSampleBuffer);
|
||||
|
||||
|
||||
+13
-18
@@ -26,12 +26,11 @@
|
||||
#include <complex>
|
||||
#include <algorithm>
|
||||
|
||||
#include "al/auxeffectslot.h"
|
||||
#include "alcmain.h"
|
||||
#include "alcomplex.h"
|
||||
#include "alcontext.h"
|
||||
#include "alu.h"
|
||||
|
||||
#include "alcomplex.h"
|
||||
#include "effectslot.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -62,8 +61,8 @@ alignas(16) const std::array<double,HIL_SIZE> HannWindow = InitHannWindow();
|
||||
struct FshifterState final : public EffectState {
|
||||
/* Effect parameters */
|
||||
size_t mCount{};
|
||||
ALuint mPhaseStep[2]{};
|
||||
ALuint mPhase[2]{};
|
||||
uint mPhaseStep[2]{};
|
||||
uint mPhase[2]{};
|
||||
double mSign[2]{};
|
||||
|
||||
/* Effects buffers */
|
||||
@@ -121,15 +120,13 @@ void FshifterState::update(const ALCcontext *context, const EffectSlot *slot,
|
||||
|
||||
switch(props->Fshifter.LeftDirection)
|
||||
{
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN:
|
||||
case FShifterDirection::Down:
|
||||
mSign[0] = -1.0;
|
||||
break;
|
||||
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_UP:
|
||||
case FShifterDirection::Up:
|
||||
mSign[0] = 1.0;
|
||||
break;
|
||||
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_OFF:
|
||||
case FShifterDirection::Off:
|
||||
mPhase[0] = 0;
|
||||
mPhaseStep[0] = 0;
|
||||
break;
|
||||
@@ -137,15 +134,13 @@ void FshifterState::update(const ALCcontext *context, const EffectSlot *slot,
|
||||
|
||||
switch(props->Fshifter.RightDirection)
|
||||
{
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN:
|
||||
case FShifterDirection::Down:
|
||||
mSign[1] = -1.0;
|
||||
break;
|
||||
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_UP:
|
||||
case FShifterDirection::Up:
|
||||
mSign[1] = 1.0;
|
||||
break;
|
||||
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_OFF:
|
||||
case FShifterDirection::Off:
|
||||
mPhase[1] = 0;
|
||||
mPhaseStep[1] = 0;
|
||||
break;
|
||||
@@ -199,10 +194,10 @@ void FshifterState::process(const size_t samplesToDo, const al::span<const Float
|
||||
|
||||
/* Process frequency shifter using the analytic signal obtained. */
|
||||
float *RESTRICT BufferOut{mBufferOut};
|
||||
for(ALsizei c{0};c < 2;++c)
|
||||
for(int c{0};c < 2;++c)
|
||||
{
|
||||
const ALuint phase_step{mPhaseStep[c]};
|
||||
ALuint phase_idx{mPhase[c]};
|
||||
const uint phase_step{mPhaseStep[c]};
|
||||
uint phase_idx{mPhase[c]};
|
||||
for(size_t k{0};k < samplesToDo;++k)
|
||||
{
|
||||
const double phase{phase_idx * ((1.0/MixerFracOne) * al::MathDefs<double>::Tau())};
|
||||
|
||||
+15
-15
@@ -41,22 +41,22 @@ namespace {
|
||||
#define WAVEFORM_FRACONE (1<<WAVEFORM_FRACBITS)
|
||||
#define WAVEFORM_FRACMASK (WAVEFORM_FRACONE-1)
|
||||
|
||||
inline float Sin(ALuint index)
|
||||
inline float Sin(uint index)
|
||||
{
|
||||
constexpr float scale{al::MathDefs<float>::Tau() / WAVEFORM_FRACONE};
|
||||
return std::sin(static_cast<float>(index) * scale);
|
||||
}
|
||||
|
||||
inline float Saw(ALuint index)
|
||||
inline float Saw(uint index)
|
||||
{ return static_cast<float>(index)*(2.0f/WAVEFORM_FRACONE) - 1.0f; }
|
||||
|
||||
inline float Square(ALuint index)
|
||||
inline float Square(uint index)
|
||||
{ return static_cast<float>(static_cast<int>((index>>(WAVEFORM_FRACBITS-2))&2) - 1); }
|
||||
|
||||
inline float One(ALuint) { return 1.0f; }
|
||||
inline float One(uint) { return 1.0f; }
|
||||
|
||||
template<float (&func)(ALuint)>
|
||||
void Modulate(float *RESTRICT dst, ALuint index, const ALuint step, size_t todo)
|
||||
template<float (&func)(uint)>
|
||||
void Modulate(float *RESTRICT dst, uint index, const uint step, size_t todo)
|
||||
{
|
||||
for(size_t i{0u};i < todo;i++)
|
||||
{
|
||||
@@ -68,10 +68,10 @@ void Modulate(float *RESTRICT dst, ALuint index, const ALuint step, size_t todo)
|
||||
|
||||
|
||||
struct ModulatorState final : public EffectState {
|
||||
void (*mGetSamples)(float*RESTRICT, ALuint, const ALuint, size_t){};
|
||||
void (*mGetSamples)(float*RESTRICT, uint, const uint, size_t){};
|
||||
|
||||
ALuint mIndex{0};
|
||||
ALuint mStep{1};
|
||||
uint mIndex{0};
|
||||
uint mStep{1};
|
||||
|
||||
struct {
|
||||
BiquadFilter Filter;
|
||||
@@ -109,11 +109,11 @@ void ModulatorState::update(const ALCcontext *context, const EffectSlot *slot,
|
||||
|
||||
if(mStep == 0)
|
||||
mGetSamples = Modulate<One>;
|
||||
else if(props->Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
|
||||
else if(props->Modulator.Waveform == ModulatorWaveform::Sinusoid)
|
||||
mGetSamples = Modulate<Sin>;
|
||||
else if(props->Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
|
||||
else if(props->Modulator.Waveform == ModulatorWaveform::Sawtooth)
|
||||
mGetSamples = Modulate<Saw>;
|
||||
else /*if(props->Modulator.Waveform == AL_RING_MODULATOR_SQUARE)*/
|
||||
else /*if(props->Modulator.Waveform == ModulatorWaveform::Square)*/
|
||||
mGetSamples = Modulate<Square>;
|
||||
|
||||
float f0norm{props->Modulator.HighPassCutoff / static_cast<float>(device->Frequency)};
|
||||
@@ -134,13 +134,13 @@ void ModulatorState::process(const size_t samplesToDo, const al::span<const Floa
|
||||
for(size_t base{0u};base < samplesToDo;)
|
||||
{
|
||||
alignas(16) float modsamples[MAX_UPDATE_SAMPLES];
|
||||
size_t td{minz(MAX_UPDATE_SAMPLES, samplesToDo-base)};
|
||||
const size_t td{minz(MAX_UPDATE_SAMPLES, samplesToDo-base)};
|
||||
|
||||
mGetSamples(modsamples, mIndex, mStep, td);
|
||||
mIndex += static_cast<ALuint>(mStep * td);
|
||||
mIndex += static_cast<uint>(mStep * td);
|
||||
mIndex &= WAVEFORM_FRACMASK;
|
||||
|
||||
auto chandata = std::addressof(mChans[0]);
|
||||
auto chandata = std::begin(mChans);
|
||||
for(const auto &input : samplesIn)
|
||||
{
|
||||
alignas(16) float temps[MAX_UPDATE_SAMPLES];
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#include "al/auxeffectslot.h"
|
||||
#include "alcmain.h"
|
||||
#include "alcontext.h"
|
||||
#include "almalloc.h"
|
||||
#include "alspan.h"
|
||||
#include "effects/base.h"
|
||||
#include "effectslot.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
#include <complex>
|
||||
#include <algorithm>
|
||||
|
||||
#include "al/auxeffectslot.h"
|
||||
#include "alcmain.h"
|
||||
#include "alcomplex.h"
|
||||
#include "alcontext.h"
|
||||
#include "alnumeric.h"
|
||||
#include "alu.h"
|
||||
#include "effectslot.h"
|
||||
|
||||
|
||||
namespace {
|
||||
@@ -70,7 +70,7 @@ struct FrequencyBin {
|
||||
struct PshifterState final : public EffectState {
|
||||
/* Effect parameters */
|
||||
size_t mCount;
|
||||
ALuint mPitchShiftI;
|
||||
uint mPitchShiftI;
|
||||
double mPitchShift;
|
||||
|
||||
/* Effects buffers */
|
||||
|
||||
@@ -245,13 +245,13 @@ struct DelayLineI {
|
||||
{ Line = sampleBuffer + LineOffset; }
|
||||
|
||||
/* Calculate the length of a delay line and store its mask and offset. */
|
||||
ALuint calcLineLength(const float length, const uintptr_t offset, const float frequency,
|
||||
const ALuint extra)
|
||||
uint calcLineLength(const float length, const uintptr_t offset, const float frequency,
|
||||
const uint extra)
|
||||
{
|
||||
/* All line lengths are powers of 2, calculated from their lengths in
|
||||
* seconds, rounded up.
|
||||
*/
|
||||
ALuint samples{float2uint(std::ceil(length*frequency))};
|
||||
uint samples{float2uint(std::ceil(length*frequency))};
|
||||
samples = NextPowerOf2(samples + extra);
|
||||
|
||||
/* All lines share a single sample buffer. */
|
||||
@@ -329,7 +329,7 @@ struct Modulation {
|
||||
/* The vibrato time is tracked with an index over a (MOD_FRACONE)
|
||||
* normalized range.
|
||||
*/
|
||||
ALuint Index, Step;
|
||||
uint Index, Step;
|
||||
|
||||
/* The depth of frequency change, in samples. */
|
||||
float Depth[2];
|
||||
@@ -1409,8 +1409,8 @@ void ReverbState::earlyFaded(const size_t offset, const size_t todo, const float
|
||||
void Modulation::calcDelays(size_t todo)
|
||||
{
|
||||
constexpr float inv_scale{MOD_FRACONE / al::MathDefs<float>::Tau()};
|
||||
ALuint idx{Index};
|
||||
const ALuint step{Step};
|
||||
uint idx{Index};
|
||||
const uint step{Step};
|
||||
const float depth{Depth[0]};
|
||||
for(size_t i{0};i < todo;++i)
|
||||
{
|
||||
@@ -1424,8 +1424,8 @@ void Modulation::calcDelays(size_t todo)
|
||||
void Modulation::calcFadedDelays(size_t todo, float fadeCount, float fadeStep)
|
||||
{
|
||||
constexpr float inv_scale{MOD_FRACONE / al::MathDefs<float>::Tau()};
|
||||
ALuint idx{Index};
|
||||
const ALuint step{Step};
|
||||
uint idx{Index};
|
||||
const uint step{Step};
|
||||
const float depth{Depth[0]};
|
||||
const float depthStep{(Depth[1]-depth) * fadeStep};
|
||||
for(size_t i{0};i < todo;++i)
|
||||
|
||||
+27
-23
@@ -25,10 +25,10 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include "al/auxeffectslot.h"
|
||||
#include "alcmain.h"
|
||||
#include "alcontext.h"
|
||||
#include "alu.h"
|
||||
#include "effectslot.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -44,22 +44,22 @@ namespace {
|
||||
#define WAVEFORM_FRACONE (1<<WAVEFORM_FRACBITS)
|
||||
#define WAVEFORM_FRACMASK (WAVEFORM_FRACONE-1)
|
||||
|
||||
inline float Sin(ALuint index)
|
||||
inline float Sin(uint index)
|
||||
{
|
||||
constexpr float scale{al::MathDefs<float>::Tau() / WAVEFORM_FRACONE};
|
||||
return std::sin(static_cast<float>(index) * scale)*0.5f + 0.5f;
|
||||
}
|
||||
|
||||
inline float Saw(ALuint index)
|
||||
inline float Saw(uint index)
|
||||
{ return static_cast<float>(index) / float{WAVEFORM_FRACONE}; }
|
||||
|
||||
inline float Triangle(ALuint index)
|
||||
inline float Triangle(uint index)
|
||||
{ return std::fabs(static_cast<float>(index)*(2.0f/WAVEFORM_FRACONE) - 1.0f); }
|
||||
|
||||
inline float Half(ALuint) { return 0.5f; }
|
||||
inline float Half(uint) { return 0.5f; }
|
||||
|
||||
template<float (&func)(ALuint)>
|
||||
void Oscillate(float *RESTRICT dst, ALuint index, const ALuint step, size_t todo)
|
||||
template<float (&func)(uint)>
|
||||
void Oscillate(float *RESTRICT dst, uint index, const uint step, size_t todo)
|
||||
{
|
||||
for(size_t i{0u};i < todo;i++)
|
||||
{
|
||||
@@ -126,10 +126,10 @@ struct VmorpherState final : public EffectState {
|
||||
float TargetGains[MAX_OUTPUT_CHANNELS]{};
|
||||
} mChans[MaxAmbiChannels];
|
||||
|
||||
void (*mGetSamples)(float*RESTRICT, ALuint, const ALuint, size_t){};
|
||||
void (*mGetSamples)(float*RESTRICT, uint, const uint, size_t){};
|
||||
|
||||
ALuint mIndex{0};
|
||||
ALuint mStep{1};
|
||||
uint mIndex{0};
|
||||
uint mStep{1};
|
||||
|
||||
/* Effects buffers */
|
||||
alignas(16) float mSampleBufferA[MAX_UPDATE_SAMPLES]{};
|
||||
@@ -142,12 +142,14 @@ struct VmorpherState final : public EffectState {
|
||||
void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn,
|
||||
const al::span<FloatBufferLine> samplesOut) override;
|
||||
|
||||
static std::array<FormantFilter,4> getFiltersByPhoneme(ALenum phoneme, float frequency, float pitch);
|
||||
static std::array<FormantFilter,4> getFiltersByPhoneme(VMorpherPhenome phoneme,
|
||||
float frequency, float pitch);
|
||||
|
||||
DEF_NEWDEL(VmorpherState)
|
||||
};
|
||||
|
||||
std::array<FormantFilter,4> VmorpherState::getFiltersByPhoneme(ALenum phoneme, float frequency, float pitch)
|
||||
std::array<FormantFilter,4> VmorpherState::getFiltersByPhoneme(VMorpherPhenome phoneme,
|
||||
float frequency, float pitch)
|
||||
{
|
||||
/* Using soprano formant set of values to
|
||||
* better match mid-range frequency space.
|
||||
@@ -156,41 +158,43 @@ std::array<FormantFilter,4> VmorpherState::getFiltersByPhoneme(ALenum phoneme, f
|
||||
*/
|
||||
switch(phoneme)
|
||||
{
|
||||
case AL_VOCAL_MORPHER_PHONEME_A:
|
||||
case VMorpherPhenome::A:
|
||||
return {{
|
||||
{( 800 * pitch) / frequency, 1.000000f}, /* std::pow(10.0f, 0 / 20.0f); */
|
||||
{(1150 * pitch) / frequency, 0.501187f}, /* std::pow(10.0f, -6 / 20.0f); */
|
||||
{(2900 * pitch) / frequency, 0.025118f}, /* std::pow(10.0f, -32 / 20.0f); */
|
||||
{(3900 * pitch) / frequency, 0.100000f} /* std::pow(10.0f, -20 / 20.0f); */
|
||||
}};
|
||||
case AL_VOCAL_MORPHER_PHONEME_E:
|
||||
case VMorpherPhenome::E:
|
||||
return {{
|
||||
{( 350 * pitch) / frequency, 1.000000f}, /* std::pow(10.0f, 0 / 20.0f); */
|
||||
{(2000 * pitch) / frequency, 0.100000f}, /* std::pow(10.0f, -20 / 20.0f); */
|
||||
{(2800 * pitch) / frequency, 0.177827f}, /* std::pow(10.0f, -15 / 20.0f); */
|
||||
{(3600 * pitch) / frequency, 0.009999f} /* std::pow(10.0f, -40 / 20.0f); */
|
||||
}};
|
||||
case AL_VOCAL_MORPHER_PHONEME_I:
|
||||
case VMorpherPhenome::I:
|
||||
return {{
|
||||
{( 270 * pitch) / frequency, 1.000000f}, /* std::pow(10.0f, 0 / 20.0f); */
|
||||
{(2140 * pitch) / frequency, 0.251188f}, /* std::pow(10.0f, -12 / 20.0f); */
|
||||
{(2950 * pitch) / frequency, 0.050118f}, /* std::pow(10.0f, -26 / 20.0f); */
|
||||
{(3900 * pitch) / frequency, 0.050118f} /* std::pow(10.0f, -26 / 20.0f); */
|
||||
}};
|
||||
case AL_VOCAL_MORPHER_PHONEME_O:
|
||||
case VMorpherPhenome::O:
|
||||
return {{
|
||||
{( 450 * pitch) / frequency, 1.000000f}, /* std::pow(10.0f, 0 / 20.0f); */
|
||||
{( 800 * pitch) / frequency, 0.281838f}, /* std::pow(10.0f, -11 / 20.0f); */
|
||||
{(2830 * pitch) / frequency, 0.079432f}, /* std::pow(10.0f, -22 / 20.0f); */
|
||||
{(3800 * pitch) / frequency, 0.079432f} /* std::pow(10.0f, -22 / 20.0f); */
|
||||
}};
|
||||
case AL_VOCAL_MORPHER_PHONEME_U:
|
||||
case VMorpherPhenome::U:
|
||||
return {{
|
||||
{( 325 * pitch) / frequency, 1.000000f}, /* std::pow(10.0f, 0 / 20.0f); */
|
||||
{( 700 * pitch) / frequency, 0.158489f}, /* std::pow(10.0f, -16 / 20.0f); */
|
||||
{(2700 * pitch) / frequency, 0.017782f}, /* std::pow(10.0f, -35 / 20.0f); */
|
||||
{(3800 * pitch) / frequency, 0.009999f} /* std::pow(10.0f, -40 / 20.0f); */
|
||||
}};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -218,12 +222,12 @@ void VmorpherState::update(const ALCcontext *context, const EffectSlot *slot,
|
||||
|
||||
if(mStep == 0)
|
||||
mGetSamples = Oscillate<Half>;
|
||||
else if(props->Vmorpher.Waveform == AL_VOCAL_MORPHER_WAVEFORM_SINUSOID)
|
||||
else if(props->Vmorpher.Waveform == VMorpherWaveform::Sinusoid)
|
||||
mGetSamples = Oscillate<Sin>;
|
||||
else if(props->Vmorpher.Waveform == AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH)
|
||||
mGetSamples = Oscillate<Saw>;
|
||||
else /*if(props->Vmorpher.Waveform == AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE)*/
|
||||
else if(props->Vmorpher.Waveform == VMorpherWaveform::Triangle)
|
||||
mGetSamples = Oscillate<Triangle>;
|
||||
else /*if(props->Vmorpher.Waveform == VMorpherWaveform::Sawtooth)*/
|
||||
mGetSamples = Oscillate<Saw>;
|
||||
|
||||
const float pitchA{std::pow(2.0f,
|
||||
static_cast<float>(props->Vmorpher.PhonemeACoarseTuning) / 12.0f)};
|
||||
@@ -256,10 +260,10 @@ void VmorpherState::process(const size_t samplesToDo, const al::span<const Float
|
||||
const size_t td{minz(MAX_UPDATE_SAMPLES, samplesToDo-base)};
|
||||
|
||||
mGetSamples(mLfo, mIndex, mStep, td);
|
||||
mIndex += static_cast<ALuint>(mStep * td);
|
||||
mIndex += static_cast<uint>(mStep * td);
|
||||
mIndex &= WAVEFORM_FRACMASK;
|
||||
|
||||
auto chandata = std::addressof(mChans[0]);
|
||||
auto chandata = std::begin(mChans);
|
||||
for(const auto &input : samplesIn)
|
||||
{
|
||||
auto& vowelA = chandata->Formants[VOWEL_A_INDEX];
|
||||
|
||||
Reference in New Issue
Block a user