🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

406 lines
14 KiB

  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 2018 by Raul Herraiz.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #ifdef HAVE_SSE_INTRINSICS
  22. #include <emmintrin.h>
  23. #endif
  24. #include <cmath>
  25. #include <cstdlib>
  26. #include <array>
  27. #include <complex>
  28. #include <algorithm>
  29. #include "alMain.h"
  30. #include "alcontext.h"
  31. #include "alAuxEffectSlot.h"
  32. #include "alError.h"
  33. #include "alu.h"
  34. #include "alcomplex.h"
  35. namespace {
  36. using complex_d = std::complex<double>;
  37. #define STFT_SIZE 1024
  38. #define STFT_HALF_SIZE (STFT_SIZE>>1)
  39. #define OVERSAMP (1<<2)
  40. #define STFT_STEP (STFT_SIZE / OVERSAMP)
  41. #define FIFO_LATENCY (STFT_STEP * (OVERSAMP-1))
  42. inline int double2int(double d)
  43. {
  44. #if defined(HAVE_SSE_INTRINSICS)
  45. return _mm_cvttsd_si32(_mm_set_sd(d));
  46. #elif ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
  47. !defined(__SSE2_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2)
  48. int sign, shift;
  49. int64_t mant;
  50. union {
  51. double d;
  52. int64_t i64;
  53. } conv;
  54. conv.d = d;
  55. sign = (conv.i64>>63) | 1;
  56. shift = ((conv.i64>>52)&0x7ff) - (1023+52);
  57. /* Over/underflow */
  58. if(UNLIKELY(shift >= 63 || shift < -52))
  59. return 0;
  60. mant = (conv.i64&0xfffffffffffff_i64) | 0x10000000000000_i64;
  61. if(LIKELY(shift < 0))
  62. return (int)(mant >> -shift) * sign;
  63. return (int)(mant << shift) * sign;
  64. #else
  65. return static_cast<int>(d);
  66. #endif
  67. }
  68. /* Define a Hann window, used to filter the STFT input and output. */
  69. /* Making this constexpr seems to require C++14. */
  70. std::array<ALdouble,STFT_SIZE> InitHannWindow()
  71. {
  72. std::array<ALdouble,STFT_SIZE> ret;
  73. /* Create lookup table of the Hann window for the desired size, i.e. HIL_SIZE */
  74. for(ALsizei i{0};i < STFT_SIZE>>1;i++)
  75. {
  76. ALdouble val = std::sin(al::MathDefs<double>::Pi() * i / ALdouble{STFT_SIZE-1});
  77. ret[i] = ret[STFT_SIZE-1-i] = val * val;
  78. }
  79. return ret;
  80. }
  81. alignas(16) const std::array<ALdouble,STFT_SIZE> HannWindow = InitHannWindow();
  82. struct ALphasor {
  83. ALdouble Amplitude;
  84. ALdouble Phase;
  85. };
  86. struct ALfrequencyDomain {
  87. ALdouble Amplitude;
  88. ALdouble Frequency;
  89. };
  90. /* Converts complex to ALphasor */
  91. inline ALphasor rect2polar(const complex_d &number)
  92. {
  93. ALphasor polar;
  94. polar.Amplitude = std::abs(number);
  95. polar.Phase = std::arg(number);
  96. return polar;
  97. }
  98. /* Converts ALphasor to complex */
  99. inline complex_d polar2rect(const ALphasor &number)
  100. { return std::polar<double>(number.Amplitude, number.Phase); }
  101. struct PshifterState final : public EffectState {
  102. /* Effect parameters */
  103. ALsizei mCount;
  104. ALsizei mPitchShiftI;
  105. ALfloat mPitchShift;
  106. ALfloat mFreqPerBin;
  107. /* Effects buffers */
  108. ALfloat mInFIFO[STFT_SIZE];
  109. ALfloat mOutFIFO[STFT_STEP];
  110. ALdouble mLastPhase[STFT_HALF_SIZE+1];
  111. ALdouble mSumPhase[STFT_HALF_SIZE+1];
  112. ALdouble mOutputAccum[STFT_SIZE];
  113. complex_d mFFTbuffer[STFT_SIZE];
  114. ALfrequencyDomain mAnalysis_buffer[STFT_HALF_SIZE+1];
  115. ALfrequencyDomain mSyntesis_buffer[STFT_HALF_SIZE+1];
  116. alignas(16) ALfloat mBufferOut[BUFFERSIZE];
  117. /* Effect gains for each output channel */
  118. ALfloat mCurrentGains[MAX_OUTPUT_CHANNELS];
  119. ALfloat mTargetGains[MAX_OUTPUT_CHANNELS];
  120. ALboolean deviceUpdate(const ALCdevice *device) override;
  121. void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override;
  122. void process(ALsizei samplesToDo, const ALfloat (*RESTRICT samplesIn)[BUFFERSIZE], const ALsizei numInput, ALfloat (*RESTRICT samplesOut)[BUFFERSIZE], const ALsizei numOutput) override;
  123. DEF_NEWDEL(PshifterState)
  124. };
  125. ALboolean PshifterState::deviceUpdate(const ALCdevice *device)
  126. {
  127. /* (Re-)initializing parameters and clear the buffers. */
  128. mCount = FIFO_LATENCY;
  129. mPitchShiftI = FRACTIONONE;
  130. mPitchShift = 1.0f;
  131. mFreqPerBin = device->Frequency / static_cast<ALfloat>(STFT_SIZE);
  132. std::fill(std::begin(mInFIFO), std::end(mInFIFO), 0.0f);
  133. std::fill(std::begin(mOutFIFO), std::end(mOutFIFO), 0.0f);
  134. std::fill(std::begin(mLastPhase), std::end(mLastPhase), 0.0);
  135. std::fill(std::begin(mSumPhase), std::end(mSumPhase), 0.0);
  136. std::fill(std::begin(mOutputAccum), std::end(mOutputAccum), 0.0);
  137. std::fill(std::begin(mFFTbuffer), std::end(mFFTbuffer), complex_d{});
  138. std::fill(std::begin(mAnalysis_buffer), std::end(mAnalysis_buffer), ALfrequencyDomain{});
  139. std::fill(std::begin(mSyntesis_buffer), std::end(mSyntesis_buffer), ALfrequencyDomain{});
  140. std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f);
  141. std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f);
  142. return AL_TRUE;
  143. }
  144. void PshifterState::update(const ALCcontext* UNUSED(context), const ALeffectslot *slot, const EffectProps *props, const EffectTarget target)
  145. {
  146. const float pitch{std::pow(2.0f,
  147. static_cast<ALfloat>(props->Pshifter.CoarseTune*100 + props->Pshifter.FineTune) / 1200.0f
  148. )};
  149. mPitchShiftI = fastf2i(pitch*FRACTIONONE);
  150. mPitchShift = mPitchShiftI * (1.0f/FRACTIONONE);
  151. ALfloat coeffs[MAX_AMBI_CHANNELS];
  152. CalcDirectionCoeffs({0.0f, 0.0f, -1.0f}, 0.0f, coeffs);
  153. mOutBuffer = target.Main->Buffer;
  154. mOutChannels = target.Main->NumChannels;
  155. ComputePanGains(target.Main, coeffs, slot->Params.Gain, mTargetGains);
  156. }
  157. void PshifterState::process(ALsizei samplesToDo, const ALfloat (*RESTRICT samplesIn)[BUFFERSIZE], const ALsizei /*numInput*/, ALfloat (*RESTRICT samplesOut)[BUFFERSIZE], const ALsizei numOutput)
  158. {
  159. /* Pitch shifter engine based on the work of Stephan Bernsee.
  160. * http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/
  161. */
  162. static constexpr ALdouble expected{al::MathDefs<double>::Tau() / OVERSAMP};
  163. const ALdouble freq_per_bin{mFreqPerBin};
  164. ALfloat *RESTRICT bufferOut{mBufferOut};
  165. ALsizei count{mCount};
  166. for(ALsizei i{0};i < samplesToDo;)
  167. {
  168. do {
  169. /* Fill FIFO buffer with samples data */
  170. mInFIFO[count] = samplesIn[0][i];
  171. bufferOut[i] = mOutFIFO[count - FIFO_LATENCY];
  172. count++;
  173. } while(++i < samplesToDo && count < STFT_SIZE);
  174. /* Check whether FIFO buffer is filled */
  175. if(count < STFT_SIZE) break;
  176. count = FIFO_LATENCY;
  177. /* Real signal windowing and store in FFTbuffer */
  178. for(ALsizei k{0};k < STFT_SIZE;k++)
  179. {
  180. mFFTbuffer[k].real(mInFIFO[k] * HannWindow[k]);
  181. mFFTbuffer[k].imag(0.0);
  182. }
  183. /* ANALYSIS */
  184. /* Apply FFT to FFTbuffer data */
  185. complex_fft(mFFTbuffer, STFT_SIZE, -1.0);
  186. /* Analyze the obtained data. Since the real FFT is symmetric, only
  187. * STFT_HALF_SIZE+1 samples are needed.
  188. */
  189. for(ALsizei k{0};k < STFT_HALF_SIZE+1;k++)
  190. {
  191. /* Compute amplitude and phase */
  192. ALphasor component{rect2polar(mFFTbuffer[k])};
  193. /* Compute phase difference and subtract expected phase difference */
  194. double tmp{(component.Phase - mLastPhase[k]) - k*expected};
  195. /* Map delta phase into +/- Pi interval */
  196. int qpd{double2int(tmp / al::MathDefs<double>::Pi())};
  197. tmp -= al::MathDefs<double>::Pi() * (qpd + (qpd%2));
  198. /* Get deviation from bin frequency from the +/- Pi interval */
  199. tmp /= expected;
  200. /* Compute the k-th partials' true frequency, twice the amplitude
  201. * for maintain the gain (because half of bins are used) and store
  202. * amplitude and true frequency in analysis buffer.
  203. */
  204. mAnalysis_buffer[k].Amplitude = 2.0 * component.Amplitude;
  205. mAnalysis_buffer[k].Frequency = (k + tmp) * freq_per_bin;
  206. /* Store actual phase[k] for the calculations in the next frame*/
  207. mLastPhase[k] = component.Phase;
  208. }
  209. /* PROCESSING */
  210. /* pitch shifting */
  211. for(ALsizei k{0};k < STFT_HALF_SIZE+1;k++)
  212. {
  213. mSyntesis_buffer[k].Amplitude = 0.0;
  214. mSyntesis_buffer[k].Frequency = 0.0;
  215. }
  216. for(ALsizei k{0};k < STFT_HALF_SIZE+1;k++)
  217. {
  218. ALsizei j{(k*mPitchShiftI) >> FRACTIONBITS};
  219. if(j >= STFT_HALF_SIZE+1) break;
  220. mSyntesis_buffer[j].Amplitude += mAnalysis_buffer[k].Amplitude;
  221. mSyntesis_buffer[j].Frequency = mAnalysis_buffer[k].Frequency * mPitchShift;
  222. }
  223. /* SYNTHESIS */
  224. /* Synthesis the processing data */
  225. for(ALsizei k{0};k < STFT_HALF_SIZE+1;k++)
  226. {
  227. ALphasor component;
  228. ALdouble tmp;
  229. /* Compute bin deviation from scaled freq */
  230. tmp = mSyntesis_buffer[k].Frequency/freq_per_bin - k;
  231. /* Calculate actual delta phase and accumulate it to get bin phase */
  232. mSumPhase[k] += (k + tmp) * expected;
  233. component.Amplitude = mSyntesis_buffer[k].Amplitude;
  234. component.Phase = mSumPhase[k];
  235. /* Compute phasor component to cartesian complex number and storage it into FFTbuffer*/
  236. mFFTbuffer[k] = polar2rect(component);
  237. }
  238. /* zero negative frequencies for recontruct a real signal */
  239. for(ALsizei k{STFT_HALF_SIZE+1};k < STFT_SIZE;k++)
  240. mFFTbuffer[k] = complex_d{};
  241. /* Apply iFFT to buffer data */
  242. complex_fft(mFFTbuffer, STFT_SIZE, 1.0);
  243. /* Windowing and add to output */
  244. for(ALsizei k{0};k < STFT_SIZE;k++)
  245. mOutputAccum[k] += HannWindow[k] * mFFTbuffer[k].real() /
  246. (0.5 * STFT_HALF_SIZE * OVERSAMP);
  247. /* Shift accumulator, input & output FIFO */
  248. ALsizei j, k;
  249. for(k = 0;k < STFT_STEP;k++) mOutFIFO[k] = static_cast<ALfloat>(mOutputAccum[k]);
  250. for(j = 0;k < STFT_SIZE;k++,j++) mOutputAccum[j] = mOutputAccum[k];
  251. for(;j < STFT_SIZE;j++) mOutputAccum[j] = 0.0;
  252. for(k = 0;k < FIFO_LATENCY;k++)
  253. mInFIFO[k] = mInFIFO[k+STFT_STEP];
  254. }
  255. mCount = count;
  256. /* Now, mix the processed sound data to the output. */
  257. MixSamples(bufferOut, numOutput, samplesOut, mCurrentGains, mTargetGains,
  258. maxi(samplesToDo, 512), 0, samplesToDo);
  259. }
  260. void Pshifter_setParamf(EffectProps*, ALCcontext *context, ALenum param, ALfloat)
  261. { alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param); }
  262. void Pshifter_setParamfv(EffectProps*, ALCcontext *context, ALenum param, const ALfloat*)
  263. { alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter float-vector property 0x%04x", param); }
  264. void Pshifter_setParami(EffectProps *props, ALCcontext *context, ALenum param, ALint val)
  265. {
  266. switch(param)
  267. {
  268. case AL_PITCH_SHIFTER_COARSE_TUNE:
  269. if(!(val >= AL_PITCH_SHIFTER_MIN_COARSE_TUNE && val <= AL_PITCH_SHIFTER_MAX_COARSE_TUNE))
  270. SETERR_RETURN(context, AL_INVALID_VALUE,,"Pitch shifter coarse tune out of range");
  271. props->Pshifter.CoarseTune = val;
  272. break;
  273. case AL_PITCH_SHIFTER_FINE_TUNE:
  274. if(!(val >= AL_PITCH_SHIFTER_MIN_FINE_TUNE && val <= AL_PITCH_SHIFTER_MAX_FINE_TUNE))
  275. SETERR_RETURN(context, AL_INVALID_VALUE,,"Pitch shifter fine tune out of range");
  276. props->Pshifter.FineTune = val;
  277. break;
  278. default:
  279. alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x", param);
  280. }
  281. }
  282. void Pshifter_setParamiv(EffectProps *props, ALCcontext *context, ALenum param, const ALint *vals)
  283. { Pshifter_setParami(props, context, param, vals[0]); }
  284. void Pshifter_getParami(const EffectProps *props, ALCcontext *context, ALenum param, ALint *val)
  285. {
  286. switch(param)
  287. {
  288. case AL_PITCH_SHIFTER_COARSE_TUNE:
  289. *val = props->Pshifter.CoarseTune;
  290. break;
  291. case AL_PITCH_SHIFTER_FINE_TUNE:
  292. *val = props->Pshifter.FineTune;
  293. break;
  294. default:
  295. alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x", param);
  296. }
  297. }
  298. void Pshifter_getParamiv(const EffectProps *props, ALCcontext *context, ALenum param, ALint *vals)
  299. { Pshifter_getParami(props, context, param, vals); }
  300. void Pshifter_getParamf(const EffectProps*, ALCcontext *context, ALenum param, ALfloat*)
  301. { alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param); }
  302. void Pshifter_getParamfv(const EffectProps*, ALCcontext *context, ALenum param, ALfloat*)
  303. { alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter float vector-property 0x%04x", param); }
  304. DEFINE_ALEFFECT_VTABLE(Pshifter);
  305. struct PshifterStateFactory final : public EffectStateFactory {
  306. EffectState *create() override;
  307. EffectProps getDefaultProps() const noexcept override;
  308. const EffectVtable *getEffectVtable() const noexcept override { return &Pshifter_vtable; }
  309. };
  310. EffectState *PshifterStateFactory::create()
  311. { return new PshifterState{}; }
  312. EffectProps PshifterStateFactory::getDefaultProps() const noexcept
  313. {
  314. EffectProps props{};
  315. props.Pshifter.CoarseTune = AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE;
  316. props.Pshifter.FineTune = AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE;
  317. return props;
  318. }
  319. } // namespace
  320. EffectStateFactory *PshifterStateFactory_getFactory()
  321. {
  322. static PshifterStateFactory PshifterFactory{};
  323. return &PshifterFactory;
  324. }