🛠️🐜 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.

521 lines
18 KiB

  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 2013 by Mike Gorchak
  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. #include <cstdlib>
  22. #include <cmath>
  23. #include <algorithm>
  24. #include "alMain.h"
  25. #include "alcontext.h"
  26. #include "alAuxEffectSlot.h"
  27. #include "alError.h"
  28. #include "alu.h"
  29. #include "filters/biquad.h"
  30. #include "vector.h"
  31. namespace {
  32. static_assert(AL_CHORUS_WAVEFORM_SINUSOID == AL_FLANGER_WAVEFORM_SINUSOID, "Chorus/Flanger waveform value mismatch");
  33. static_assert(AL_CHORUS_WAVEFORM_TRIANGLE == AL_FLANGER_WAVEFORM_TRIANGLE, "Chorus/Flanger waveform value mismatch");
  34. enum class WaveForm {
  35. Sinusoid,
  36. Triangle
  37. };
  38. void GetTriangleDelays(ALint *delays, ALsizei offset, ALsizei lfo_range, ALfloat lfo_scale,
  39. ALfloat depth, ALsizei delay, ALsizei todo)
  40. {
  41. std::generate_n<ALint*RESTRICT>(delays, todo,
  42. [&offset,lfo_range,lfo_scale,depth,delay]() -> ALint
  43. {
  44. offset = (offset+1)%lfo_range;
  45. return fastf2i((1.0f - std::abs(2.0f - lfo_scale*offset)) * depth) + delay;
  46. }
  47. );
  48. }
  49. void GetSinusoidDelays(ALint *delays, ALsizei offset, ALsizei lfo_range, ALfloat lfo_scale,
  50. ALfloat depth, ALsizei delay, ALsizei todo)
  51. {
  52. std::generate_n<ALint*RESTRICT>(delays, todo,
  53. [&offset,lfo_range,lfo_scale,depth,delay]() -> ALint
  54. {
  55. offset = (offset+1)%lfo_range;
  56. return fastf2i(std::sin(lfo_scale*offset) * depth) + delay;
  57. }
  58. );
  59. }
  60. struct ChorusState final : public EffectState {
  61. al::vector<ALfloat,16> mSampleBuffer;
  62. ALsizei mOffset{0};
  63. ALsizei mLfoOffset{0};
  64. ALsizei mLfoRange{1};
  65. ALfloat mLfoScale{0.0f};
  66. ALint mLfoDisp{0};
  67. /* Gains for left and right sides */
  68. struct {
  69. ALfloat Current[MAX_OUTPUT_CHANNELS]{};
  70. ALfloat Target[MAX_OUTPUT_CHANNELS]{};
  71. } mGains[2];
  72. /* effect parameters */
  73. WaveForm mWaveform{};
  74. ALint mDelay{0};
  75. ALfloat mDepth{0.0f};
  76. ALfloat mFeedback{0.0f};
  77. ALboolean deviceUpdate(const ALCdevice *device) override;
  78. void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override;
  79. void process(ALsizei samplesToDo, const ALfloat (*RESTRICT samplesIn)[BUFFERSIZE], const ALsizei numInput, ALfloat (*RESTRICT samplesOut)[BUFFERSIZE], const ALsizei numOutput) override;
  80. DEF_NEWDEL(ChorusState)
  81. };
  82. ALboolean ChorusState::deviceUpdate(const ALCdevice *Device)
  83. {
  84. const ALfloat max_delay = maxf(AL_CHORUS_MAX_DELAY, AL_FLANGER_MAX_DELAY);
  85. size_t maxlen;
  86. maxlen = NextPowerOf2(float2int(max_delay*2.0f*Device->Frequency) + 1u);
  87. if(maxlen <= 0) return AL_FALSE;
  88. if(maxlen != mSampleBuffer.size())
  89. {
  90. mSampleBuffer.resize(maxlen);
  91. mSampleBuffer.shrink_to_fit();
  92. }
  93. std::fill(mSampleBuffer.begin(), mSampleBuffer.end(), 0.0f);
  94. for(auto &e : mGains)
  95. {
  96. std::fill(std::begin(e.Current), std::end(e.Current), 0.0f);
  97. std::fill(std::begin(e.Target), std::end(e.Target), 0.0f);
  98. }
  99. return AL_TRUE;
  100. }
  101. void ChorusState::update(const ALCcontext *Context, const ALeffectslot *Slot, const EffectProps *props, const EffectTarget target)
  102. {
  103. static constexpr ALsizei mindelay = MAX_RESAMPLE_PADDING << FRACTIONBITS;
  104. switch(props->Chorus.Waveform)
  105. {
  106. case AL_CHORUS_WAVEFORM_TRIANGLE:
  107. mWaveform = WaveForm::Triangle;
  108. break;
  109. case AL_CHORUS_WAVEFORM_SINUSOID:
  110. mWaveform = WaveForm::Sinusoid;
  111. break;
  112. }
  113. /* The LFO depth is scaled to be relative to the sample delay. Clamp the
  114. * delay and depth to allow enough padding for resampling.
  115. */
  116. const ALCdevice *device{Context->Device};
  117. const auto frequency = static_cast<ALfloat>(device->Frequency);
  118. mDelay = maxi(float2int(props->Chorus.Delay*frequency*FRACTIONONE + 0.5f), mindelay);
  119. mDepth = minf(props->Chorus.Depth * mDelay, static_cast<ALfloat>(mDelay - mindelay));
  120. mFeedback = props->Chorus.Feedback;
  121. /* Gains for left and right sides */
  122. ALfloat coeffs[2][MAX_AMBI_CHANNELS];
  123. CalcDirectionCoeffs({-1.0f, 0.0f, 0.0f}, 0.0f, coeffs[0]);
  124. CalcDirectionCoeffs({ 1.0f, 0.0f, 0.0f}, 0.0f, coeffs[1]);
  125. mOutBuffer = target.Main->Buffer;
  126. mOutChannels = target.Main->NumChannels;
  127. ComputePanGains(target.Main, coeffs[0], Slot->Params.Gain, mGains[0].Target);
  128. ComputePanGains(target.Main, coeffs[1], Slot->Params.Gain, mGains[1].Target);
  129. ALfloat rate{props->Chorus.Rate};
  130. if(!(rate > 0.0f))
  131. {
  132. mLfoOffset = 0;
  133. mLfoRange = 1;
  134. mLfoScale = 0.0f;
  135. mLfoDisp = 0;
  136. }
  137. else
  138. {
  139. /* Calculate LFO coefficient (number of samples per cycle). Limit the
  140. * max range to avoid overflow when calculating the displacement.
  141. */
  142. ALsizei lfo_range = float2int(minf(frequency/rate + 0.5f, static_cast<ALfloat>(INT_MAX/360 - 180)));
  143. mLfoOffset = float2int(static_cast<ALfloat>(mLfoOffset)/mLfoRange*lfo_range + 0.5f) % lfo_range;
  144. mLfoRange = lfo_range;
  145. switch(mWaveform)
  146. {
  147. case WaveForm::Triangle:
  148. mLfoScale = 4.0f / mLfoRange;
  149. break;
  150. case WaveForm::Sinusoid:
  151. mLfoScale = al::MathDefs<float>::Tau() / mLfoRange;
  152. break;
  153. }
  154. /* Calculate lfo phase displacement */
  155. ALint phase{props->Chorus.Phase};
  156. if(phase < 0) phase = 360 + phase;
  157. mLfoDisp = (mLfoRange*phase + 180) / 360;
  158. }
  159. }
  160. void ChorusState::process(ALsizei samplesToDo, const ALfloat (*RESTRICT samplesIn)[BUFFERSIZE], const ALsizei /*numInput*/, ALfloat (*RESTRICT samplesOut)[BUFFERSIZE], const ALsizei numOutput)
  161. {
  162. const auto bufmask = static_cast<ALsizei>(mSampleBuffer.size()-1);
  163. const ALfloat feedback{mFeedback};
  164. const ALsizei avgdelay{(mDelay + (FRACTIONONE>>1)) >> FRACTIONBITS};
  165. ALfloat *RESTRICT delaybuf{mSampleBuffer.data()};
  166. ALsizei offset{mOffset};
  167. ALsizei i, c;
  168. ALsizei base;
  169. for(base = 0;base < samplesToDo;)
  170. {
  171. const ALsizei todo = mini(256, samplesToDo-base);
  172. ALint moddelays[2][256];
  173. alignas(16) ALfloat temps[2][256];
  174. if(mWaveform == WaveForm::Sinusoid)
  175. {
  176. GetSinusoidDelays(moddelays[0], mLfoOffset, mLfoRange, mLfoScale, mDepth, mDelay,
  177. todo);
  178. GetSinusoidDelays(moddelays[1], (mLfoOffset+mLfoDisp)%mLfoRange, mLfoRange, mLfoScale,
  179. mDepth, mDelay, todo);
  180. }
  181. else /*if(mWaveform == WaveForm::Triangle)*/
  182. {
  183. GetTriangleDelays(moddelays[0], mLfoOffset, mLfoRange, mLfoScale, mDepth, mDelay,
  184. todo);
  185. GetTriangleDelays(moddelays[1], (mLfoOffset+mLfoDisp)%mLfoRange, mLfoRange, mLfoScale,
  186. mDepth, mDelay, todo);
  187. }
  188. mLfoOffset = (mLfoOffset+todo) % mLfoRange;
  189. for(i = 0;i < todo;i++)
  190. {
  191. // Feed the buffer's input first (necessary for delays < 1).
  192. delaybuf[offset&bufmask] = samplesIn[0][base+i];
  193. // Tap for the left output.
  194. ALint delay{offset - (moddelays[0][i]>>FRACTIONBITS)};
  195. ALfloat mu{(moddelays[0][i]&FRACTIONMASK) * (1.0f/FRACTIONONE)};
  196. temps[0][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask],
  197. delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask],
  198. mu);
  199. // Tap for the right output.
  200. delay = offset - (moddelays[1][i]>>FRACTIONBITS);
  201. mu = (moddelays[1][i]&FRACTIONMASK) * (1.0f/FRACTIONONE);
  202. temps[1][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask],
  203. delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask],
  204. mu);
  205. // Accumulate feedback from the average delay of the taps.
  206. delaybuf[offset&bufmask] += delaybuf[(offset-avgdelay) & bufmask] * feedback;
  207. offset++;
  208. }
  209. for(c = 0;c < 2;c++)
  210. MixSamples(temps[c], numOutput, samplesOut, mGains[c].Current, mGains[c].Target,
  211. samplesToDo-base, base, todo);
  212. base += todo;
  213. }
  214. mOffset = offset;
  215. }
  216. void Chorus_setParami(EffectProps *props, ALCcontext *context, ALenum param, ALint val)
  217. {
  218. switch(param)
  219. {
  220. case AL_CHORUS_WAVEFORM:
  221. if(!(val >= AL_CHORUS_MIN_WAVEFORM && val <= AL_CHORUS_MAX_WAVEFORM))
  222. SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid chorus waveform");
  223. props->Chorus.Waveform = val;
  224. break;
  225. case AL_CHORUS_PHASE:
  226. if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE))
  227. SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus phase out of range");
  228. props->Chorus.Phase = val;
  229. break;
  230. default:
  231. alSetError(context, AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param);
  232. }
  233. }
  234. void Chorus_setParamiv(EffectProps *props, ALCcontext *context, ALenum param, const ALint *vals)
  235. { Chorus_setParami(props, context, param, vals[0]); }
  236. void Chorus_setParamf(EffectProps *props, ALCcontext *context, ALenum param, ALfloat val)
  237. {
  238. switch(param)
  239. {
  240. case AL_CHORUS_RATE:
  241. if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE))
  242. SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus rate out of range");
  243. props->Chorus.Rate = val;
  244. break;
  245. case AL_CHORUS_DEPTH:
  246. if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH))
  247. SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus depth out of range");
  248. props->Chorus.Depth = val;
  249. break;
  250. case AL_CHORUS_FEEDBACK:
  251. if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK))
  252. SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus feedback out of range");
  253. props->Chorus.Feedback = val;
  254. break;
  255. case AL_CHORUS_DELAY:
  256. if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY))
  257. SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus delay out of range");
  258. props->Chorus.Delay = val;
  259. break;
  260. default:
  261. alSetError(context, AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param);
  262. }
  263. }
  264. void Chorus_setParamfv(EffectProps *props, ALCcontext *context, ALenum param, const ALfloat *vals)
  265. { Chorus_setParamf(props, context, param, vals[0]); }
  266. void Chorus_getParami(const EffectProps *props, ALCcontext *context, ALenum param, ALint *val)
  267. {
  268. switch(param)
  269. {
  270. case AL_CHORUS_WAVEFORM:
  271. *val = props->Chorus.Waveform;
  272. break;
  273. case AL_CHORUS_PHASE:
  274. *val = props->Chorus.Phase;
  275. break;
  276. default:
  277. alSetError(context, AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param);
  278. }
  279. }
  280. void Chorus_getParamiv(const EffectProps *props, ALCcontext *context, ALenum param, ALint *vals)
  281. { Chorus_getParami(props, context, param, vals); }
  282. void Chorus_getParamf(const EffectProps *props, ALCcontext *context, ALenum param, ALfloat *val)
  283. {
  284. switch(param)
  285. {
  286. case AL_CHORUS_RATE:
  287. *val = props->Chorus.Rate;
  288. break;
  289. case AL_CHORUS_DEPTH:
  290. *val = props->Chorus.Depth;
  291. break;
  292. case AL_CHORUS_FEEDBACK:
  293. *val = props->Chorus.Feedback;
  294. break;
  295. case AL_CHORUS_DELAY:
  296. *val = props->Chorus.Delay;
  297. break;
  298. default:
  299. alSetError(context, AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param);
  300. }
  301. }
  302. void Chorus_getParamfv(const EffectProps *props, ALCcontext *context, ALenum param, ALfloat *vals)
  303. { Chorus_getParamf(props, context, param, vals); }
  304. DEFINE_ALEFFECT_VTABLE(Chorus);
  305. struct ChorusStateFactory final : public EffectStateFactory {
  306. EffectState *create() override { return new ChorusState{}; }
  307. EffectProps getDefaultProps() const noexcept override;
  308. const EffectVtable *getEffectVtable() const noexcept override { return &Chorus_vtable; }
  309. };
  310. EffectProps ChorusStateFactory::getDefaultProps() const noexcept
  311. {
  312. EffectProps props{};
  313. props.Chorus.Waveform = AL_CHORUS_DEFAULT_WAVEFORM;
  314. props.Chorus.Phase = AL_CHORUS_DEFAULT_PHASE;
  315. props.Chorus.Rate = AL_CHORUS_DEFAULT_RATE;
  316. props.Chorus.Depth = AL_CHORUS_DEFAULT_DEPTH;
  317. props.Chorus.Feedback = AL_CHORUS_DEFAULT_FEEDBACK;
  318. props.Chorus.Delay = AL_CHORUS_DEFAULT_DELAY;
  319. return props;
  320. }
  321. void Flanger_setParami(EffectProps *props, ALCcontext *context, ALenum param, ALint val)
  322. {
  323. switch(param)
  324. {
  325. case AL_FLANGER_WAVEFORM:
  326. if(!(val >= AL_FLANGER_MIN_WAVEFORM && val <= AL_FLANGER_MAX_WAVEFORM))
  327. SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid flanger waveform");
  328. props->Chorus.Waveform = val;
  329. break;
  330. case AL_FLANGER_PHASE:
  331. if(!(val >= AL_FLANGER_MIN_PHASE && val <= AL_FLANGER_MAX_PHASE))
  332. SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger phase out of range");
  333. props->Chorus.Phase = val;
  334. break;
  335. default:
  336. alSetError(context, AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param);
  337. }
  338. }
  339. void Flanger_setParamiv(EffectProps *props, ALCcontext *context, ALenum param, const ALint *vals)
  340. { Flanger_setParami(props, context, param, vals[0]); }
  341. void Flanger_setParamf(EffectProps *props, ALCcontext *context, ALenum param, ALfloat val)
  342. {
  343. switch(param)
  344. {
  345. case AL_FLANGER_RATE:
  346. if(!(val >= AL_FLANGER_MIN_RATE && val <= AL_FLANGER_MAX_RATE))
  347. SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger rate out of range");
  348. props->Chorus.Rate = val;
  349. break;
  350. case AL_FLANGER_DEPTH:
  351. if(!(val >= AL_FLANGER_MIN_DEPTH && val <= AL_FLANGER_MAX_DEPTH))
  352. SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger depth out of range");
  353. props->Chorus.Depth = val;
  354. break;
  355. case AL_FLANGER_FEEDBACK:
  356. if(!(val >= AL_FLANGER_MIN_FEEDBACK && val <= AL_FLANGER_MAX_FEEDBACK))
  357. SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger feedback out of range");
  358. props->Chorus.Feedback = val;
  359. break;
  360. case AL_FLANGER_DELAY:
  361. if(!(val >= AL_FLANGER_MIN_DELAY && val <= AL_FLANGER_MAX_DELAY))
  362. SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger delay out of range");
  363. props->Chorus.Delay = val;
  364. break;
  365. default:
  366. alSetError(context, AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param);
  367. }
  368. }
  369. void Flanger_setParamfv(EffectProps *props, ALCcontext *context, ALenum param, const ALfloat *vals)
  370. { Flanger_setParamf(props, context, param, vals[0]); }
  371. void Flanger_getParami(const EffectProps *props, ALCcontext *context, ALenum param, ALint *val)
  372. {
  373. switch(param)
  374. {
  375. case AL_FLANGER_WAVEFORM:
  376. *val = props->Chorus.Waveform;
  377. break;
  378. case AL_FLANGER_PHASE:
  379. *val = props->Chorus.Phase;
  380. break;
  381. default:
  382. alSetError(context, AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param);
  383. }
  384. }
  385. void Flanger_getParamiv(const EffectProps *props, ALCcontext *context, ALenum param, ALint *vals)
  386. { Flanger_getParami(props, context, param, vals); }
  387. void Flanger_getParamf(const EffectProps *props, ALCcontext *context, ALenum param, ALfloat *val)
  388. {
  389. switch(param)
  390. {
  391. case AL_FLANGER_RATE:
  392. *val = props->Chorus.Rate;
  393. break;
  394. case AL_FLANGER_DEPTH:
  395. *val = props->Chorus.Depth;
  396. break;
  397. case AL_FLANGER_FEEDBACK:
  398. *val = props->Chorus.Feedback;
  399. break;
  400. case AL_FLANGER_DELAY:
  401. *val = props->Chorus.Delay;
  402. break;
  403. default:
  404. alSetError(context, AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param);
  405. }
  406. }
  407. void Flanger_getParamfv(const EffectProps *props, ALCcontext *context, ALenum param, ALfloat *vals)
  408. { Flanger_getParamf(props, context, param, vals); }
  409. DEFINE_ALEFFECT_VTABLE(Flanger);
  410. /* Flanger is basically a chorus with a really short delay. They can both use
  411. * the same processing functions, so piggyback flanger on the chorus functions.
  412. */
  413. struct FlangerStateFactory final : public EffectStateFactory {
  414. EffectState *create() override { return new ChorusState{}; }
  415. EffectProps getDefaultProps() const noexcept override;
  416. const EffectVtable *getEffectVtable() const noexcept override { return &Flanger_vtable; }
  417. };
  418. EffectProps FlangerStateFactory::getDefaultProps() const noexcept
  419. {
  420. EffectProps props{};
  421. props.Chorus.Waveform = AL_FLANGER_DEFAULT_WAVEFORM;
  422. props.Chorus.Phase = AL_FLANGER_DEFAULT_PHASE;
  423. props.Chorus.Rate = AL_FLANGER_DEFAULT_RATE;
  424. props.Chorus.Depth = AL_FLANGER_DEFAULT_DEPTH;
  425. props.Chorus.Feedback = AL_FLANGER_DEFAULT_FEEDBACK;
  426. props.Chorus.Delay = AL_FLANGER_DEFAULT_DELAY;
  427. return props;
  428. }
  429. } // namespace
  430. EffectStateFactory *ChorusStateFactory_getFactory()
  431. {
  432. static ChorusStateFactory ChorusFactory{};
  433. return &ChorusFactory;
  434. }
  435. EffectStateFactory *FlangerStateFactory_getFactory()
  436. {
  437. static FlangerStateFactory FlangerFactory{};
  438. return &FlangerFactory;
  439. }