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

786 lines
22 KiB

  1. #include "config.h"
  2. #include <stdexcept>
  3. #include "AL/al.h"
  4. #include "AL/efx.h"
  5. #include "alc/effects/base.h"
  6. #include "aloptional.h"
  7. #include "effects.h"
  8. #ifdef ALSOFT_EAX
  9. #include <cassert>
  10. #include "alnumeric.h"
  11. #include "al/eax_exception.h"
  12. #include "al/eax_utils.h"
  13. #endif // ALSOFT_EAX
  14. namespace {
  15. al::optional<VMorpherPhenome> PhenomeFromEnum(ALenum val)
  16. {
  17. #define HANDLE_PHENOME(x) case AL_VOCAL_MORPHER_PHONEME_ ## x: \
  18. return al::make_optional(VMorpherPhenome::x)
  19. switch(val)
  20. {
  21. HANDLE_PHENOME(A);
  22. HANDLE_PHENOME(E);
  23. HANDLE_PHENOME(I);
  24. HANDLE_PHENOME(O);
  25. HANDLE_PHENOME(U);
  26. HANDLE_PHENOME(AA);
  27. HANDLE_PHENOME(AE);
  28. HANDLE_PHENOME(AH);
  29. HANDLE_PHENOME(AO);
  30. HANDLE_PHENOME(EH);
  31. HANDLE_PHENOME(ER);
  32. HANDLE_PHENOME(IH);
  33. HANDLE_PHENOME(IY);
  34. HANDLE_PHENOME(UH);
  35. HANDLE_PHENOME(UW);
  36. HANDLE_PHENOME(B);
  37. HANDLE_PHENOME(D);
  38. HANDLE_PHENOME(F);
  39. HANDLE_PHENOME(G);
  40. HANDLE_PHENOME(J);
  41. HANDLE_PHENOME(K);
  42. HANDLE_PHENOME(L);
  43. HANDLE_PHENOME(M);
  44. HANDLE_PHENOME(N);
  45. HANDLE_PHENOME(P);
  46. HANDLE_PHENOME(R);
  47. HANDLE_PHENOME(S);
  48. HANDLE_PHENOME(T);
  49. HANDLE_PHENOME(V);
  50. HANDLE_PHENOME(Z);
  51. }
  52. return al::nullopt;
  53. #undef HANDLE_PHENOME
  54. }
  55. ALenum EnumFromPhenome(VMorpherPhenome phenome)
  56. {
  57. #define HANDLE_PHENOME(x) case VMorpherPhenome::x: return AL_VOCAL_MORPHER_PHONEME_ ## x
  58. switch(phenome)
  59. {
  60. HANDLE_PHENOME(A);
  61. HANDLE_PHENOME(E);
  62. HANDLE_PHENOME(I);
  63. HANDLE_PHENOME(O);
  64. HANDLE_PHENOME(U);
  65. HANDLE_PHENOME(AA);
  66. HANDLE_PHENOME(AE);
  67. HANDLE_PHENOME(AH);
  68. HANDLE_PHENOME(AO);
  69. HANDLE_PHENOME(EH);
  70. HANDLE_PHENOME(ER);
  71. HANDLE_PHENOME(IH);
  72. HANDLE_PHENOME(IY);
  73. HANDLE_PHENOME(UH);
  74. HANDLE_PHENOME(UW);
  75. HANDLE_PHENOME(B);
  76. HANDLE_PHENOME(D);
  77. HANDLE_PHENOME(F);
  78. HANDLE_PHENOME(G);
  79. HANDLE_PHENOME(J);
  80. HANDLE_PHENOME(K);
  81. HANDLE_PHENOME(L);
  82. HANDLE_PHENOME(M);
  83. HANDLE_PHENOME(N);
  84. HANDLE_PHENOME(P);
  85. HANDLE_PHENOME(R);
  86. HANDLE_PHENOME(S);
  87. HANDLE_PHENOME(T);
  88. HANDLE_PHENOME(V);
  89. HANDLE_PHENOME(Z);
  90. }
  91. throw std::runtime_error{"Invalid phenome: "+std::to_string(static_cast<int>(phenome))};
  92. #undef HANDLE_PHENOME
  93. }
  94. al::optional<VMorpherWaveform> WaveformFromEmum(ALenum value)
  95. {
  96. switch(value)
  97. {
  98. case AL_VOCAL_MORPHER_WAVEFORM_SINUSOID: return al::make_optional(VMorpherWaveform::Sinusoid);
  99. case AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE: return al::make_optional(VMorpherWaveform::Triangle);
  100. case AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH: return al::make_optional(VMorpherWaveform::Sawtooth);
  101. }
  102. return al::nullopt;
  103. }
  104. ALenum EnumFromWaveform(VMorpherWaveform type)
  105. {
  106. switch(type)
  107. {
  108. case VMorpherWaveform::Sinusoid: return AL_VOCAL_MORPHER_WAVEFORM_SINUSOID;
  109. case VMorpherWaveform::Triangle: return AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE;
  110. case VMorpherWaveform::Sawtooth: return AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH;
  111. }
  112. throw std::runtime_error{"Invalid vocal morpher waveform: " +
  113. std::to_string(static_cast<int>(type))};
  114. }
  115. void Vmorpher_setParami(EffectProps *props, ALenum param, int val)
  116. {
  117. switch(param)
  118. {
  119. case AL_VOCAL_MORPHER_PHONEMEA:
  120. if(auto phenomeopt = PhenomeFromEnum(val))
  121. props->Vmorpher.PhonemeA = *phenomeopt;
  122. else
  123. throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a out of range: 0x%04x", val};
  124. break;
  125. case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING:
  126. if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING))
  127. throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a coarse tuning out of range"};
  128. props->Vmorpher.PhonemeACoarseTuning = val;
  129. break;
  130. case AL_VOCAL_MORPHER_PHONEMEB:
  131. if(auto phenomeopt = PhenomeFromEnum(val))
  132. props->Vmorpher.PhonemeB = *phenomeopt;
  133. else
  134. throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b out of range: 0x%04x", val};
  135. break;
  136. case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING:
  137. if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING))
  138. throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b coarse tuning out of range"};
  139. props->Vmorpher.PhonemeBCoarseTuning = val;
  140. break;
  141. case AL_VOCAL_MORPHER_WAVEFORM:
  142. if(auto formopt = WaveformFromEmum(val))
  143. props->Vmorpher.Waveform = *formopt;
  144. else
  145. throw effect_exception{AL_INVALID_VALUE, "Vocal morpher waveform out of range: 0x%04x", val};
  146. break;
  147. default:
  148. throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x",
  149. param};
  150. }
  151. }
  152. void Vmorpher_setParamiv(EffectProps*, ALenum param, const int*)
  153. {
  154. throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x",
  155. param};
  156. }
  157. void Vmorpher_setParamf(EffectProps *props, ALenum param, float val)
  158. {
  159. switch(param)
  160. {
  161. case AL_VOCAL_MORPHER_RATE:
  162. if(!(val >= AL_VOCAL_MORPHER_MIN_RATE && val <= AL_VOCAL_MORPHER_MAX_RATE))
  163. throw effect_exception{AL_INVALID_VALUE, "Vocal morpher rate out of range"};
  164. props->Vmorpher.Rate = val;
  165. break;
  166. default:
  167. throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher float property 0x%04x",
  168. param};
  169. }
  170. }
  171. void Vmorpher_setParamfv(EffectProps *props, ALenum param, const float *vals)
  172. { Vmorpher_setParamf(props, param, vals[0]); }
  173. void Vmorpher_getParami(const EffectProps *props, ALenum param, int* val)
  174. {
  175. switch(param)
  176. {
  177. case AL_VOCAL_MORPHER_PHONEMEA:
  178. *val = EnumFromPhenome(props->Vmorpher.PhonemeA);
  179. break;
  180. case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING:
  181. *val = props->Vmorpher.PhonemeACoarseTuning;
  182. break;
  183. case AL_VOCAL_MORPHER_PHONEMEB:
  184. *val = EnumFromPhenome(props->Vmorpher.PhonemeB);
  185. break;
  186. case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING:
  187. *val = props->Vmorpher.PhonemeBCoarseTuning;
  188. break;
  189. case AL_VOCAL_MORPHER_WAVEFORM:
  190. *val = EnumFromWaveform(props->Vmorpher.Waveform);
  191. break;
  192. default:
  193. throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x",
  194. param};
  195. }
  196. }
  197. void Vmorpher_getParamiv(const EffectProps*, ALenum param, int*)
  198. {
  199. throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x",
  200. param};
  201. }
  202. void Vmorpher_getParamf(const EffectProps *props, ALenum param, float *val)
  203. {
  204. switch(param)
  205. {
  206. case AL_VOCAL_MORPHER_RATE:
  207. *val = props->Vmorpher.Rate;
  208. break;
  209. default:
  210. throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher float property 0x%04x",
  211. param};
  212. }
  213. }
  214. void Vmorpher_getParamfv(const EffectProps *props, ALenum param, float *vals)
  215. { Vmorpher_getParamf(props, param, vals); }
  216. EffectProps genDefaultProps() noexcept
  217. {
  218. EffectProps props{};
  219. props.Vmorpher.Rate = AL_VOCAL_MORPHER_DEFAULT_RATE;
  220. props.Vmorpher.PhonemeA = *PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEA);
  221. props.Vmorpher.PhonemeB = *PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEB);
  222. props.Vmorpher.PhonemeACoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING;
  223. props.Vmorpher.PhonemeBCoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING;
  224. props.Vmorpher.Waveform = *WaveformFromEmum(AL_VOCAL_MORPHER_DEFAULT_WAVEFORM);
  225. return props;
  226. }
  227. } // namespace
  228. DEFINE_ALEFFECT_VTABLE(Vmorpher);
  229. const EffectProps VmorpherEffectProps{genDefaultProps()};
  230. #ifdef ALSOFT_EAX
  231. namespace {
  232. using EaxVocalMorpherEffectDirtyFlagsValue = std::uint_least8_t;
  233. struct EaxVocalMorpherEffectDirtyFlags
  234. {
  235. using EaxIsBitFieldStruct = bool;
  236. EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeA : 1;
  237. EaxVocalMorpherEffectDirtyFlagsValue lPhonemeACoarseTuning : 1;
  238. EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeB : 1;
  239. EaxVocalMorpherEffectDirtyFlagsValue lPhonemeBCoarseTuning : 1;
  240. EaxVocalMorpherEffectDirtyFlagsValue ulWaveform : 1;
  241. EaxVocalMorpherEffectDirtyFlagsValue flRate : 1;
  242. }; // EaxPitchShifterEffectDirtyFlags
  243. class EaxVocalMorpherEffect final :
  244. public EaxEffect
  245. {
  246. public:
  247. EaxVocalMorpherEffect();
  248. void dispatch(const EaxEaxCall& eax_call) override;
  249. // [[nodiscard]]
  250. bool apply_deferred() override;
  251. private:
  252. EAXVOCALMORPHERPROPERTIES eax_{};
  253. EAXVOCALMORPHERPROPERTIES eax_d_{};
  254. EaxVocalMorpherEffectDirtyFlags eax_dirty_flags_{};
  255. void set_eax_defaults();
  256. void set_efx_phoneme_a();
  257. void set_efx_phoneme_a_coarse_tuning();
  258. void set_efx_phoneme_b();
  259. void set_efx_phoneme_b_coarse_tuning();
  260. void set_efx_waveform();
  261. void set_efx_rate();
  262. void set_efx_defaults();
  263. void get(const EaxEaxCall& eax_call);
  264. void validate_phoneme_a(unsigned long ulPhonemeA);
  265. void validate_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning);
  266. void validate_phoneme_b(unsigned long ulPhonemeB);
  267. void validate_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning);
  268. void validate_waveform(unsigned long ulWaveform);
  269. void validate_rate(float flRate);
  270. void validate_all(const EAXVOCALMORPHERPROPERTIES& all);
  271. void defer_phoneme_a(unsigned long ulPhonemeA);
  272. void defer_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning);
  273. void defer_phoneme_b(unsigned long ulPhonemeB);
  274. void defer_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning);
  275. void defer_waveform(unsigned long ulWaveform);
  276. void defer_rate(float flRate);
  277. void defer_all(const EAXVOCALMORPHERPROPERTIES& all);
  278. void defer_phoneme_a(const EaxEaxCall& eax_call);
  279. void defer_phoneme_a_coarse_tuning(const EaxEaxCall& eax_call);
  280. void defer_phoneme_b(const EaxEaxCall& eax_call);
  281. void defer_phoneme_b_coarse_tuning(const EaxEaxCall& eax_call);
  282. void defer_waveform(const EaxEaxCall& eax_call);
  283. void defer_rate(const EaxEaxCall& eax_call);
  284. void defer_all(const EaxEaxCall& eax_call);
  285. void set(const EaxEaxCall& eax_call);
  286. }; // EaxVocalMorpherEffect
  287. class EaxVocalMorpherEffectException :
  288. public EaxException
  289. {
  290. public:
  291. explicit EaxVocalMorpherEffectException(
  292. const char* message)
  293. :
  294. EaxException{"EAX_VOCAL_MORPHER_EFFECT", message}
  295. {
  296. }
  297. }; // EaxVocalMorpherEffectException
  298. EaxVocalMorpherEffect::EaxVocalMorpherEffect()
  299. : EaxEffect{AL_EFFECT_VOCAL_MORPHER}
  300. {
  301. set_eax_defaults();
  302. set_efx_defaults();
  303. }
  304. void EaxVocalMorpherEffect::dispatch(const EaxEaxCall& eax_call)
  305. {
  306. eax_call.is_get() ? get(eax_call) : set(eax_call);
  307. }
  308. void EaxVocalMorpherEffect::set_eax_defaults()
  309. {
  310. eax_.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA;
  311. eax_.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING;
  312. eax_.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB;
  313. eax_.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING;
  314. eax_.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM;
  315. eax_.flRate = EAXVOCALMORPHER_DEFAULTRATE;
  316. eax_d_ = eax_;
  317. }
  318. void EaxVocalMorpherEffect::set_efx_phoneme_a()
  319. {
  320. const auto phoneme_a = clamp(
  321. static_cast<ALint>(eax_.ulPhonemeA),
  322. AL_VOCAL_MORPHER_MIN_PHONEMEA,
  323. AL_VOCAL_MORPHER_MAX_PHONEMEA);
  324. const auto efx_phoneme_a = PhenomeFromEnum(phoneme_a);
  325. assert(efx_phoneme_a.has_value());
  326. al_effect_props_.Vmorpher.PhonemeA = *efx_phoneme_a;
  327. }
  328. void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning()
  329. {
  330. const auto phoneme_a_coarse_tuning = clamp(
  331. static_cast<ALint>(eax_.lPhonemeACoarseTuning),
  332. AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING,
  333. AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING);
  334. al_effect_props_.Vmorpher.PhonemeACoarseTuning = phoneme_a_coarse_tuning;
  335. }
  336. void EaxVocalMorpherEffect::set_efx_phoneme_b()
  337. {
  338. const auto phoneme_b = clamp(
  339. static_cast<ALint>(eax_.ulPhonemeB),
  340. AL_VOCAL_MORPHER_MIN_PHONEMEB,
  341. AL_VOCAL_MORPHER_MAX_PHONEMEB);
  342. const auto efx_phoneme_b = PhenomeFromEnum(phoneme_b);
  343. assert(efx_phoneme_b.has_value());
  344. al_effect_props_.Vmorpher.PhonemeB = *efx_phoneme_b;
  345. }
  346. void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning()
  347. {
  348. const auto phoneme_b_coarse_tuning = clamp(
  349. static_cast<ALint>(eax_.lPhonemeBCoarseTuning),
  350. AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING,
  351. AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING);
  352. al_effect_props_.Vmorpher.PhonemeBCoarseTuning = phoneme_b_coarse_tuning;
  353. }
  354. void EaxVocalMorpherEffect::set_efx_waveform()
  355. {
  356. const auto waveform = clamp(
  357. static_cast<ALint>(eax_.ulWaveform),
  358. AL_VOCAL_MORPHER_MIN_WAVEFORM,
  359. AL_VOCAL_MORPHER_MAX_WAVEFORM);
  360. const auto wfx_waveform = WaveformFromEmum(waveform);
  361. assert(wfx_waveform.has_value());
  362. al_effect_props_.Vmorpher.Waveform = *wfx_waveform;
  363. }
  364. void EaxVocalMorpherEffect::set_efx_rate()
  365. {
  366. const auto rate = clamp(
  367. eax_.flRate,
  368. AL_VOCAL_MORPHER_MIN_RATE,
  369. AL_VOCAL_MORPHER_MAX_RATE);
  370. al_effect_props_.Vmorpher.Rate = rate;
  371. }
  372. void EaxVocalMorpherEffect::set_efx_defaults()
  373. {
  374. set_efx_phoneme_a();
  375. set_efx_phoneme_a_coarse_tuning();
  376. set_efx_phoneme_b();
  377. set_efx_phoneme_b_coarse_tuning();
  378. set_efx_waveform();
  379. set_efx_rate();
  380. }
  381. void EaxVocalMorpherEffect::get(const EaxEaxCall& eax_call)
  382. {
  383. switch(eax_call.get_property_id())
  384. {
  385. case EAXVOCALMORPHER_NONE:
  386. break;
  387. case EAXVOCALMORPHER_ALLPARAMETERS:
  388. eax_call.set_value<EaxVocalMorpherEffectException>(eax_);
  389. break;
  390. case EAXVOCALMORPHER_PHONEMEA:
  391. eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulPhonemeA);
  392. break;
  393. case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
  394. eax_call.set_value<EaxVocalMorpherEffectException>(eax_.lPhonemeACoarseTuning);
  395. break;
  396. case EAXVOCALMORPHER_PHONEMEB:
  397. eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulPhonemeB);
  398. break;
  399. case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
  400. eax_call.set_value<EaxVocalMorpherEffectException>(eax_.lPhonemeBCoarseTuning);
  401. break;
  402. case EAXVOCALMORPHER_WAVEFORM:
  403. eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulWaveform);
  404. break;
  405. case EAXVOCALMORPHER_RATE:
  406. eax_call.set_value<EaxVocalMorpherEffectException>(eax_.flRate);
  407. break;
  408. default:
  409. throw EaxVocalMorpherEffectException{"Unsupported property id."};
  410. }
  411. }
  412. void EaxVocalMorpherEffect::validate_phoneme_a(
  413. unsigned long ulPhonemeA)
  414. {
  415. eax_validate_range<EaxVocalMorpherEffectException>(
  416. "Phoneme A",
  417. ulPhonemeA,
  418. EAXVOCALMORPHER_MINPHONEMEA,
  419. EAXVOCALMORPHER_MAXPHONEMEA);
  420. }
  421. void EaxVocalMorpherEffect::validate_phoneme_a_coarse_tuning(
  422. long lPhonemeACoarseTuning)
  423. {
  424. eax_validate_range<EaxVocalMorpherEffectException>(
  425. "Phoneme A Coarse Tuning",
  426. lPhonemeACoarseTuning,
  427. EAXVOCALMORPHER_MINPHONEMEACOARSETUNING,
  428. EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING);
  429. }
  430. void EaxVocalMorpherEffect::validate_phoneme_b(
  431. unsigned long ulPhonemeB)
  432. {
  433. eax_validate_range<EaxVocalMorpherEffectException>(
  434. "Phoneme B",
  435. ulPhonemeB,
  436. EAXVOCALMORPHER_MINPHONEMEB,
  437. EAXVOCALMORPHER_MAXPHONEMEB);
  438. }
  439. void EaxVocalMorpherEffect::validate_phoneme_b_coarse_tuning(
  440. long lPhonemeBCoarseTuning)
  441. {
  442. eax_validate_range<EaxVocalMorpherEffectException>(
  443. "Phoneme B Coarse Tuning",
  444. lPhonemeBCoarseTuning,
  445. EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING,
  446. EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING);
  447. }
  448. void EaxVocalMorpherEffect::validate_waveform(
  449. unsigned long ulWaveform)
  450. {
  451. eax_validate_range<EaxVocalMorpherEffectException>(
  452. "Waveform",
  453. ulWaveform,
  454. EAXVOCALMORPHER_MINWAVEFORM,
  455. EAXVOCALMORPHER_MAXWAVEFORM);
  456. }
  457. void EaxVocalMorpherEffect::validate_rate(
  458. float flRate)
  459. {
  460. eax_validate_range<EaxVocalMorpherEffectException>(
  461. "Rate",
  462. flRate,
  463. EAXVOCALMORPHER_MINRATE,
  464. EAXVOCALMORPHER_MAXRATE);
  465. }
  466. void EaxVocalMorpherEffect::validate_all(
  467. const EAXVOCALMORPHERPROPERTIES& all)
  468. {
  469. validate_phoneme_a(all.ulPhonemeA);
  470. validate_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning);
  471. validate_phoneme_b(all.ulPhonemeB);
  472. validate_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning);
  473. validate_waveform(all.ulWaveform);
  474. validate_rate(all.flRate);
  475. }
  476. void EaxVocalMorpherEffect::defer_phoneme_a(
  477. unsigned long ulPhonemeA)
  478. {
  479. eax_d_.ulPhonemeA = ulPhonemeA;
  480. eax_dirty_flags_.ulPhonemeA = (eax_.ulPhonemeA != eax_d_.ulPhonemeA);
  481. }
  482. void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning(
  483. long lPhonemeACoarseTuning)
  484. {
  485. eax_d_.lPhonemeACoarseTuning = lPhonemeACoarseTuning;
  486. eax_dirty_flags_.lPhonemeACoarseTuning = (eax_.lPhonemeACoarseTuning != eax_d_.lPhonemeACoarseTuning);
  487. }
  488. void EaxVocalMorpherEffect::defer_phoneme_b(
  489. unsigned long ulPhonemeB)
  490. {
  491. eax_d_.ulPhonemeB = ulPhonemeB;
  492. eax_dirty_flags_.ulPhonemeB = (eax_.ulPhonemeB != eax_d_.ulPhonemeB);
  493. }
  494. void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning(
  495. long lPhonemeBCoarseTuning)
  496. {
  497. eax_d_.lPhonemeBCoarseTuning = lPhonemeBCoarseTuning;
  498. eax_dirty_flags_.lPhonemeBCoarseTuning = (eax_.lPhonemeBCoarseTuning != eax_d_.lPhonemeBCoarseTuning);
  499. }
  500. void EaxVocalMorpherEffect::defer_waveform(
  501. unsigned long ulWaveform)
  502. {
  503. eax_d_.ulWaveform = ulWaveform;
  504. eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform);
  505. }
  506. void EaxVocalMorpherEffect::defer_rate(
  507. float flRate)
  508. {
  509. eax_d_.flRate = flRate;
  510. eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate);
  511. }
  512. void EaxVocalMorpherEffect::defer_all(
  513. const EAXVOCALMORPHERPROPERTIES& all)
  514. {
  515. defer_phoneme_a(all.ulPhonemeA);
  516. defer_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning);
  517. defer_phoneme_b(all.ulPhonemeB);
  518. defer_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning);
  519. defer_waveform(all.ulWaveform);
  520. defer_rate(all.flRate);
  521. }
  522. void EaxVocalMorpherEffect::defer_phoneme_a(
  523. const EaxEaxCall& eax_call)
  524. {
  525. const auto& phoneme_a = eax_call.get_value<EaxVocalMorpherEffectException,
  526. const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeA)>();
  527. validate_phoneme_a(phoneme_a);
  528. defer_phoneme_a(phoneme_a);
  529. }
  530. void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning(
  531. const EaxEaxCall& eax_call)
  532. {
  533. const auto& phoneme_a_coarse_tuning = eax_call.get_value<
  534. EaxVocalMorpherEffectException,
  535. const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeACoarseTuning)
  536. >();
  537. validate_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning);
  538. defer_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning);
  539. }
  540. void EaxVocalMorpherEffect::defer_phoneme_b(
  541. const EaxEaxCall& eax_call)
  542. {
  543. const auto& phoneme_b = eax_call.get_value<
  544. EaxVocalMorpherEffectException,
  545. const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeB)
  546. >();
  547. validate_phoneme_b(phoneme_b);
  548. defer_phoneme_b(phoneme_b);
  549. }
  550. void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning(
  551. const EaxEaxCall& eax_call)
  552. {
  553. const auto& phoneme_b_coarse_tuning = eax_call.get_value<
  554. EaxVocalMorpherEffectException,
  555. const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeBCoarseTuning)
  556. >();
  557. validate_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning);
  558. defer_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning);
  559. }
  560. void EaxVocalMorpherEffect::defer_waveform(
  561. const EaxEaxCall& eax_call)
  562. {
  563. const auto& waveform = eax_call.get_value<
  564. EaxVocalMorpherEffectException,
  565. const decltype(EAXVOCALMORPHERPROPERTIES::ulWaveform)
  566. >();
  567. validate_waveform(waveform);
  568. defer_waveform(waveform);
  569. }
  570. void EaxVocalMorpherEffect::defer_rate(
  571. const EaxEaxCall& eax_call)
  572. {
  573. const auto& rate = eax_call.get_value<
  574. EaxVocalMorpherEffectException,
  575. const decltype(EAXVOCALMORPHERPROPERTIES::flRate)
  576. >();
  577. validate_rate(rate);
  578. defer_rate(rate);
  579. }
  580. void EaxVocalMorpherEffect::defer_all(
  581. const EaxEaxCall& eax_call)
  582. {
  583. const auto& all = eax_call.get_value<
  584. EaxVocalMorpherEffectException,
  585. const EAXVOCALMORPHERPROPERTIES
  586. >();
  587. validate_all(all);
  588. defer_all(all);
  589. }
  590. // [[nodiscard]]
  591. bool EaxVocalMorpherEffect::apply_deferred()
  592. {
  593. if (eax_dirty_flags_ == EaxVocalMorpherEffectDirtyFlags{})
  594. {
  595. return false;
  596. }
  597. eax_ = eax_d_;
  598. if (eax_dirty_flags_.ulPhonemeA)
  599. {
  600. set_efx_phoneme_a();
  601. }
  602. if (eax_dirty_flags_.lPhonemeACoarseTuning)
  603. {
  604. set_efx_phoneme_a_coarse_tuning();
  605. }
  606. if (eax_dirty_flags_.ulPhonemeB)
  607. {
  608. set_efx_phoneme_b();
  609. }
  610. if (eax_dirty_flags_.lPhonemeBCoarseTuning)
  611. {
  612. set_efx_phoneme_b_coarse_tuning();
  613. }
  614. if (eax_dirty_flags_.ulWaveform)
  615. {
  616. set_efx_waveform();
  617. }
  618. if (eax_dirty_flags_.flRate)
  619. {
  620. set_efx_rate();
  621. }
  622. eax_dirty_flags_ = EaxVocalMorpherEffectDirtyFlags{};
  623. return true;
  624. }
  625. void EaxVocalMorpherEffect::set(const EaxEaxCall& eax_call)
  626. {
  627. switch(eax_call.get_property_id())
  628. {
  629. case EAXVOCALMORPHER_NONE:
  630. break;
  631. case EAXVOCALMORPHER_ALLPARAMETERS:
  632. defer_all(eax_call);
  633. break;
  634. case EAXVOCALMORPHER_PHONEMEA:
  635. defer_phoneme_a(eax_call);
  636. break;
  637. case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
  638. defer_phoneme_a_coarse_tuning(eax_call);
  639. break;
  640. case EAXVOCALMORPHER_PHONEMEB:
  641. defer_phoneme_b(eax_call);
  642. break;
  643. case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
  644. defer_phoneme_b_coarse_tuning(eax_call);
  645. break;
  646. case EAXVOCALMORPHER_WAVEFORM:
  647. defer_waveform(eax_call);
  648. break;
  649. case EAXVOCALMORPHER_RATE:
  650. defer_rate(eax_call);
  651. break;
  652. default:
  653. throw EaxVocalMorpherEffectException{"Unsupported property id."};
  654. }
  655. }
  656. } // namespace
  657. EaxEffectUPtr eax_create_eax_vocal_morpher_effect()
  658. {
  659. return std::make_unique<EaxVocalMorpherEffect>();
  660. }
  661. #endif // ALSOFT_EAX