Avoid AL types and enums in the effect processors

This commit is contained in:
Chris Robinson
2020-12-21 21:11:25 -08:00
parent eedc42890f
commit 0d3b041aa2
17 changed files with 391 additions and 203 deletions
+46 -20
View File
@@ -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;
+3
View File
@@ -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
View File
@@ -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;
}
+31 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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"
+4 -5
View File
@@ -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);
+3 -3
View File
@@ -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)
{
+2 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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 -4
View File
@@ -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 {
+2 -2
View File
@@ -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 */
+8 -8
View File
@@ -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
View File
@@ -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];