aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/effects/pshifter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/effects/pshifter.cpp')
-rw-r--r--Alc/effects/pshifter.cpp161
1 files changed, 80 insertions, 81 deletions
diff --git a/Alc/effects/pshifter.cpp b/Alc/effects/pshifter.cpp
index d3a399ff..410eb982 100644
--- a/Alc/effects/pshifter.cpp
+++ b/Alc/effects/pshifter.cpp
@@ -20,8 +20,8 @@
#include "config.h"
-#include <math.h>
-#include <stdlib.h>
+#include <cmath>
+#include <cstdlib>
#include "alMain.h"
#include "alAuxEffectSlot.h"
@@ -32,6 +32,8 @@
#include "alcomplex.h"
+namespace {
+
#define STFT_SIZE 1024
#define STFT_HALF_SIZE (STFT_SIZE>>1)
#define OVERSAMP (1<<2)
@@ -39,71 +41,7 @@
#define STFT_STEP (STFT_SIZE / OVERSAMP)
#define FIFO_LATENCY (STFT_STEP * (OVERSAMP-1))
-
-typedef struct ALphasor {
- ALdouble Amplitude;
- ALdouble Phase;
-} ALphasor;
-
-typedef struct ALFrequencyDomain {
- ALdouble Amplitude;
- ALdouble Frequency;
-} ALfrequencyDomain;
-
-
-struct ALpshifterState final : public ALeffectState {
- /* Effect parameters */
- ALsizei count;
- ALsizei PitchShiftI;
- ALfloat PitchShift;
- ALfloat FreqPerBin;
-
- /*Effects buffers*/
- ALfloat InFIFO[STFT_SIZE];
- ALfloat OutFIFO[STFT_STEP];
- ALdouble LastPhase[STFT_HALF_SIZE+1];
- ALdouble SumPhase[STFT_HALF_SIZE+1];
- ALdouble OutputAccum[STFT_SIZE];
-
- ALcomplex FFTbuffer[STFT_SIZE];
-
- ALfrequencyDomain Analysis_buffer[STFT_HALF_SIZE+1];
- ALfrequencyDomain Syntesis_buffer[STFT_HALF_SIZE+1];
-
- alignas(16) ALfloat BufferOut[BUFFERSIZE];
-
- /* Effect gains for each output channel */
- ALfloat CurrentGains[MAX_OUTPUT_CHANNELS];
- ALfloat TargetGains[MAX_OUTPUT_CHANNELS];
-};
-
-static ALvoid ALpshifterState_Destruct(ALpshifterState *state);
-static ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device);
-static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
-DECLARE_DEFAULT_ALLOCATORS(ALpshifterState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALpshifterState);
-
-
-/* Define a Hann window, used to filter the STFT input and output. */
-alignas(16) static ALdouble HannWindow[STFT_SIZE];
-
-static void InitHannWindow(void)
-{
- ALsizei i;
-
- /* Create lookup table of the Hann window for the desired size, i.e. STFT_SIZE */
- for(i = 0;i < STFT_SIZE>>1;i++)
- {
- ALdouble val = sin(M_PI * (ALdouble)i / (ALdouble)(STFT_SIZE-1));
- HannWindow[i] = HannWindow[STFT_SIZE-1-i] = val * val;
- }
-}
-static alonce_flag HannInitOnce = AL_ONCE_FLAG_INIT;
-
-
-static inline ALint double2int(ALdouble d)
+inline ALint double2int(ALdouble d)
{
#if ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
!defined(__SSE2_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2)
@@ -133,46 +71,105 @@ static inline ALint double2int(ALdouble d)
#endif
}
+/* Define a Hann window, used to filter the STFT input and output. */
+/* Making this constexpr seems to require C++14. */
+std::array<ALdouble,STFT_SIZE> InitHannWindow(void)
+{
+ std::array<ALdouble,STFT_SIZE> ret;
+ /* Create lookup table of the Hann window for the desired size, i.e. HIL_SIZE */
+ for(ALsizei i{0};i < STFT_SIZE>>1;i++)
+ {
+ ALdouble val = std::sin(M_PI * (ALdouble)i / (ALdouble)(STFT_SIZE-1));
+ ret[i] = ret[STFT_SIZE-1-i] = val * val;
+ }
+ return ret;
+}
+alignas(16) const std::array<ALdouble,STFT_SIZE> HannWindow = InitHannWindow();
+
+
+struct ALphasor {
+ ALdouble Amplitude;
+ ALdouble Phase;
+};
+
+struct ALfrequencyDomain {
+ ALdouble Amplitude;
+ ALdouble Frequency;
+};
+
/* Converts ALcomplex to ALphasor */
-static inline ALphasor rect2polar(ALcomplex number)
+inline ALphasor rect2polar(ALcomplex number)
{
ALphasor polar;
- polar.Amplitude = sqrt(number.Real*number.Real + number.Imag*number.Imag);
- polar.Phase = atan2(number.Imag, number.Real);
+ polar.Amplitude = std::sqrt(number.Real*number.Real + number.Imag*number.Imag);
+ polar.Phase = std::atan2(number.Imag, number.Real);
return polar;
}
/* Converts ALphasor to ALcomplex */
-static inline ALcomplex polar2rect(ALphasor number)
+inline ALcomplex polar2rect(ALphasor number)
{
ALcomplex cartesian;
- cartesian.Real = number.Amplitude * cos(number.Phase);
- cartesian.Imag = number.Amplitude * sin(number.Phase);
+ cartesian.Real = number.Amplitude * std::cos(number.Phase);
+ cartesian.Imag = number.Amplitude * std::sin(number.Phase);
return cartesian;
}
-static void ALpshifterState_Construct(ALpshifterState *state)
+
+struct ALpshifterState final : public ALeffectState {
+ /* Effect parameters */
+ ALsizei count;
+ ALsizei PitchShiftI;
+ ALfloat PitchShift;
+ ALfloat FreqPerBin;
+
+ /*Effects buffers*/
+ ALfloat InFIFO[STFT_SIZE];
+ ALfloat OutFIFO[STFT_STEP];
+ ALdouble LastPhase[STFT_HALF_SIZE+1];
+ ALdouble SumPhase[STFT_HALF_SIZE+1];
+ ALdouble OutputAccum[STFT_SIZE];
+
+ ALcomplex FFTbuffer[STFT_SIZE];
+
+ ALfrequencyDomain Analysis_buffer[STFT_HALF_SIZE+1];
+ ALfrequencyDomain Syntesis_buffer[STFT_HALF_SIZE+1];
+
+ alignas(16) ALfloat BufferOut[BUFFERSIZE];
+
+ /* Effect gains for each output channel */
+ ALfloat CurrentGains[MAX_OUTPUT_CHANNELS];
+ ALfloat TargetGains[MAX_OUTPUT_CHANNELS];
+};
+
+static ALvoid ALpshifterState_Destruct(ALpshifterState *state);
+static ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device);
+static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
+static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+DECLARE_DEFAULT_ALLOCATORS(ALpshifterState)
+
+DEFINE_ALEFFECTSTATE_VTABLE(ALpshifterState);
+
+void ALpshifterState_Construct(ALpshifterState *state)
{
new (state) ALpshifterState{};
ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
SET_VTABLE2(ALpshifterState, ALeffectState, state);
-
- alcall_once(&HannInitOnce, InitHannWindow);
}
-static ALvoid ALpshifterState_Destruct(ALpshifterState *state)
+ALvoid ALpshifterState_Destruct(ALpshifterState *state)
{
ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
state->~ALpshifterState();
}
-static ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device)
+ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device)
{
/* (Re-)initializing parameters and clear the buffers. */
state->count = FIFO_LATENCY;
@@ -195,13 +192,13 @@ static ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice
return AL_TRUE;
}
-static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
+ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
{
const ALCdevice *device = context->Device;
ALfloat coeffs[MAX_AMBI_COEFFS];
float pitch;
- pitch = powf(2.0f,
+ pitch = std::pow(2.0f,
(ALfloat)(props->Pshifter.CoarseTune*100 + props->Pshifter.FineTune) / 1200.0f
);
state->PitchShiftI = fastf2i(pitch*FRACTIONONE);
@@ -211,7 +208,7 @@ static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *c
ComputePanGains(&device->Dry, coeffs, slot->Params.Gain, state->TargetGains);
}
-static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
/* Pitch shifter engine based on the work of Stephan Bernsee.
* http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/
@@ -347,6 +344,8 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
maxi(SamplesToDo, 512), 0, SamplesToDo);
}
+} // namespace
+
struct PshifterStateFactory final : public EffectStateFactory {
PshifterStateFactory() noexcept;
};