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.cpp147
1 files changed, 64 insertions, 83 deletions
diff --git a/Alc/effects/pshifter.cpp b/Alc/effects/pshifter.cpp
index ec473678..3c375499 100644
--- a/Alc/effects/pshifter.cpp
+++ b/Alc/effects/pshifter.cpp
@@ -117,7 +117,7 @@ inline complex_d polar2rect(const ALphasor &number)
{ return std::polar<double>(number.Amplitude, number.Phase); }
-struct ALpshifterState final : public ALeffectState {
+struct ALpshifterState final : public EffectState {
/* Effect parameters */
ALsizei mCount;
ALsizei mPitchShiftI;
@@ -141,53 +141,39 @@ struct ALpshifterState final : public ALeffectState {
/* Effect gains for each output channel */
ALfloat mCurrentGains[MAX_OUTPUT_CHANNELS];
ALfloat mTargetGains[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);
+ ALboolean deviceUpdate(ALCdevice *device) override;
+ void update(const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props) override;
+ void process(ALsizei samplesToDo, const ALfloat (*RESTRICT samplesIn)[BUFFERSIZE], ALfloat (*RESTRICT samplesOut)[BUFFERSIZE], ALsizei numChannels) override;
-void ALpshifterState_Construct(ALpshifterState *state)
-{
- new (state) ALpshifterState{};
- ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
- SET_VTABLE2(ALpshifterState, ALeffectState, state);
-}
-
-ALvoid ALpshifterState_Destruct(ALpshifterState *state)
-{
- ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
- state->~ALpshifterState();
-}
+ DEF_NEWDEL(ALpshifterState)
+};
-ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device)
+ALboolean ALpshifterState::deviceUpdate(ALCdevice *device)
{
/* (Re-)initializing parameters and clear the buffers. */
- state->mCount = FIFO_LATENCY;
- state->mPitchShiftI = FRACTIONONE;
- state->mPitchShift = 1.0f;
- state->mFreqPerBin = device->Frequency / (ALfloat)STFT_SIZE;
-
- std::fill(std::begin(state->mInFIFO), std::end(state->mInFIFO), 0.0f);
- std::fill(std::begin(state->mOutFIFO), std::end(state->mOutFIFO), 0.0f);
- std::fill(std::begin(state->mLastPhase), std::end(state->mLastPhase), 0.0);
- std::fill(std::begin(state->mSumPhase), std::end(state->mSumPhase), 0.0);
- std::fill(std::begin(state->mOutputAccum), std::end(state->mOutputAccum), 0.0);
- std::fill(std::begin(state->mFFTbuffer), std::end(state->mFFTbuffer), complex_d{});
- std::fill(std::begin(state->mAnalysis_buffer), std::end(state->mAnalysis_buffer), ALfrequencyDomain{});
- std::fill(std::begin(state->mSyntesis_buffer), std::end(state->mSyntesis_buffer), ALfrequencyDomain{});
-
- std::fill(std::begin(state->mCurrentGains), std::end(state->mCurrentGains), 0.0f);
- std::fill(std::begin(state->mTargetGains), std::end(state->mTargetGains), 0.0f);
+ mCount = FIFO_LATENCY;
+ mPitchShiftI = FRACTIONONE;
+ mPitchShift = 1.0f;
+ mFreqPerBin = device->Frequency / (ALfloat)STFT_SIZE;
+
+ std::fill(std::begin(mInFIFO), std::end(mInFIFO), 0.0f);
+ std::fill(std::begin(mOutFIFO), std::end(mOutFIFO), 0.0f);
+ std::fill(std::begin(mLastPhase), std::end(mLastPhase), 0.0);
+ std::fill(std::begin(mSumPhase), std::end(mSumPhase), 0.0);
+ std::fill(std::begin(mOutputAccum), std::end(mOutputAccum), 0.0);
+ std::fill(std::begin(mFFTbuffer), std::end(mFFTbuffer), complex_d{});
+ std::fill(std::begin(mAnalysis_buffer), std::end(mAnalysis_buffer), ALfrequencyDomain{});
+ std::fill(std::begin(mSyntesis_buffer), std::end(mSyntesis_buffer), ALfrequencyDomain{});
+
+ std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f);
+ std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f);
return AL_TRUE;
}
-ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
+void ALpshifterState::update(const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
{
const ALCdevice *device = context->Device;
ALfloat coeffs[MAX_AMBI_COEFFS];
@@ -196,30 +182,30 @@ ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context,
pitch = std::pow(2.0f,
(ALfloat)(props->Pshifter.CoarseTune*100 + props->Pshifter.FineTune) / 1200.0f
);
- state->mPitchShiftI = fastf2i(pitch*FRACTIONONE);
- state->mPitchShift = state->mPitchShiftI * (1.0f/FRACTIONONE);
+ mPitchShiftI = fastf2i(pitch*FRACTIONONE);
+ mPitchShift = mPitchShiftI * (1.0f/FRACTIONONE);
CalcAngleCoeffs(0.0f, 0.0f, 0.0f, coeffs);
- ComputePanGains(&device->Dry, coeffs, slot->Params.Gain, state->mTargetGains);
+ ComputePanGains(&device->Dry, coeffs, slot->Params.Gain, mTargetGains);
}
-ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+void ALpshifterState::process(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/
*/
static constexpr ALdouble expected{M_PI*2.0 / OVERSAMP};
- const ALdouble freq_per_bin{state->mFreqPerBin};
- ALfloat *RESTRICT bufferOut{state->mBufferOut};
- ALsizei count{state->mCount};
+ const ALdouble freq_per_bin{mFreqPerBin};
+ ALfloat *RESTRICT bufferOut{mBufferOut};
+ ALsizei count{mCount};
for(ALsizei i{0};i < SamplesToDo;)
{
do {
/* Fill FIFO buffer with samples data */
- state->mInFIFO[count] = SamplesIn[0][i];
- bufferOut[i] = state->mOutFIFO[count - FIFO_LATENCY];
+ mInFIFO[count] = SamplesIn[0][i];
+ bufferOut[i] = mOutFIFO[count - FIFO_LATENCY];
count++;
} while(++i < SamplesToDo && count < STFT_SIZE);
@@ -231,13 +217,13 @@ ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, cons
/* Real signal windowing and store in FFTbuffer */
for(ALsizei k{0};k < STFT_SIZE;k++)
{
- state->mFFTbuffer[k].real(state->mInFIFO[k] * HannWindow[k]);
- state->mFFTbuffer[k].imag(0.0);
+ mFFTbuffer[k].real(mInFIFO[k] * HannWindow[k]);
+ mFFTbuffer[k].imag(0.0);
}
/* ANALYSIS */
/* Apply FFT to FFTbuffer data */
- complex_fft(state->mFFTbuffer, STFT_SIZE, -1.0);
+ complex_fft(mFFTbuffer, STFT_SIZE, -1.0);
/* Analyze the obtained data. Since the real FFT is symmetric, only
* STFT_HALF_SIZE+1 samples are needed.
@@ -245,10 +231,10 @@ ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, cons
for(ALsizei k{0};k < STFT_HALF_SIZE+1;k++)
{
/* Compute amplitude and phase */
- ALphasor component{rect2polar(state->mFFTbuffer[k])};
+ ALphasor component{rect2polar(mFFTbuffer[k])};
/* Compute phase difference and subtract expected phase difference */
- double tmp{(component.Phase - state->mLastPhase[k]) - k*expected};
+ double tmp{(component.Phase - mLastPhase[k]) - k*expected};
/* Map delta phase into +/- Pi interval */
int qpd{double2int(tmp / M_PI)};
@@ -261,29 +247,28 @@ ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, cons
* for maintain the gain (because half of bins are used) and store
* amplitude and true frequency in analysis buffer.
*/
- state->mAnalysis_buffer[k].Amplitude = 2.0 * component.Amplitude;
- state->mAnalysis_buffer[k].Frequency = (k + tmp) * freq_per_bin;
+ mAnalysis_buffer[k].Amplitude = 2.0 * component.Amplitude;
+ mAnalysis_buffer[k].Frequency = (k + tmp) * freq_per_bin;
/* Store actual phase[k] for the calculations in the next frame*/
- state->mLastPhase[k] = component.Phase;
+ mLastPhase[k] = component.Phase;
}
/* PROCESSING */
/* pitch shifting */
for(ALsizei k{0};k < STFT_HALF_SIZE+1;k++)
{
- state->mSyntesis_buffer[k].Amplitude = 0.0;
- state->mSyntesis_buffer[k].Frequency = 0.0;
+ mSyntesis_buffer[k].Amplitude = 0.0;
+ mSyntesis_buffer[k].Frequency = 0.0;
}
for(ALsizei k{0};k < STFT_HALF_SIZE+1;k++)
{
- ALsizei j{(k*state->mPitchShiftI) >> FRACTIONBITS};
+ ALsizei j{(k*mPitchShiftI) >> FRACTIONBITS};
if(j >= STFT_HALF_SIZE+1) break;
- state->mSyntesis_buffer[j].Amplitude += state->mAnalysis_buffer[k].Amplitude;
- state->mSyntesis_buffer[j].Frequency = state->mAnalysis_buffer[k].Frequency *
- state->mPitchShift;
+ mSyntesis_buffer[j].Amplitude += mAnalysis_buffer[k].Amplitude;
+ mSyntesis_buffer[j].Frequency = mAnalysis_buffer[k].Frequency * mPitchShift;
}
/* SYNTHESIS */
@@ -294,56 +279,52 @@ ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, cons
ALdouble tmp;
/* Compute bin deviation from scaled freq */
- tmp = state->mSyntesis_buffer[k].Frequency/freq_per_bin - k;
+ tmp = mSyntesis_buffer[k].Frequency/freq_per_bin - k;
/* Calculate actual delta phase and accumulate it to get bin phase */
- state->mSumPhase[k] += (k + tmp) * expected;
+ mSumPhase[k] += (k + tmp) * expected;
- component.Amplitude = state->mSyntesis_buffer[k].Amplitude;
- component.Phase = state->mSumPhase[k];
+ component.Amplitude = mSyntesis_buffer[k].Amplitude;
+ component.Phase = mSumPhase[k];
/* Compute phasor component to cartesian complex number and storage it into FFTbuffer*/
- state->mFFTbuffer[k] = polar2rect(component);
+ mFFTbuffer[k] = polar2rect(component);
}
/* zero negative frequencies for recontruct a real signal */
for(ALsizei k{STFT_HALF_SIZE+1};k < STFT_SIZE;k++)
- state->mFFTbuffer[k] = complex_d{};
+ mFFTbuffer[k] = complex_d{};
/* Apply iFFT to buffer data */
- complex_fft(state->mFFTbuffer, STFT_SIZE, 1.0);
+ complex_fft(mFFTbuffer, STFT_SIZE, 1.0);
/* Windowing and add to output */
for(ALsizei k{0};k < STFT_SIZE;k++)
- state->mOutputAccum[k] += HannWindow[k] * state->mFFTbuffer[k].real() /
- (0.5 * STFT_HALF_SIZE * OVERSAMP);
+ mOutputAccum[k] += HannWindow[k] * mFFTbuffer[k].real() /
+ (0.5 * STFT_HALF_SIZE * OVERSAMP);
/* Shift accumulator, input & output FIFO */
ALsizei j, k;
- for(k = 0;k < STFT_STEP;k++) state->mOutFIFO[k] = (ALfloat)state->mOutputAccum[k];
- for(j = 0;k < STFT_SIZE;k++,j++) state->mOutputAccum[j] = state->mOutputAccum[k];
- for(;j < STFT_SIZE;j++) state->mOutputAccum[j] = 0.0;
+ for(k = 0;k < STFT_STEP;k++) mOutFIFO[k] = (ALfloat)mOutputAccum[k];
+ for(j = 0;k < STFT_SIZE;k++,j++) mOutputAccum[j] = mOutputAccum[k];
+ for(;j < STFT_SIZE;j++) mOutputAccum[j] = 0.0;
for(k = 0;k < FIFO_LATENCY;k++)
- state->mInFIFO[k] = state->mInFIFO[k+STFT_STEP];
+ mInFIFO[k] = mInFIFO[k+STFT_STEP];
}
- state->mCount = count;
+ mCount = count;
/* Now, mix the processed sound data to the output. */
- MixSamples(bufferOut, NumChannels, SamplesOut, state->mCurrentGains, state->mTargetGains,
+ MixSamples(bufferOut, NumChannels, SamplesOut, mCurrentGains, mTargetGains,
maxi(SamplesToDo, 512), 0, SamplesToDo);
}
} // namespace
struct PshifterStateFactory final : public EffectStateFactory {
- ALeffectState *create() override;
+ EffectState *create() override;
};
-ALeffectState *PshifterStateFactory::create()
-{
- ALpshifterState *state;
- NEW_OBJ0(state, ALpshifterState)();
- return state;
-}
+EffectState *PshifterStateFactory::create()
+{ return new ALpshifterState{}; }
EffectStateFactory *PshifterStateFactory_getFactory(void)
{