AkModulatorProcess.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*******************************************************************************
  2. The content of this file includes portions of the AUDIOKINETIC Wwise Technology
  3. released in source code form as part of the SDK installer package.
  4. Commercial License Usage
  5. Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
  6. may use this file in accordance with the end user license agreement provided
  7. with the software or, alternatively, in accordance with the terms contained in a
  8. written agreement between you and Audiokinetic Inc.
  9. Apache License Usage
  10. Alternatively, this file may be used under the Apache License, Version 2.0 (the
  11. "Apache License"); you may not use this file except in compliance with the
  12. Apache License. You may obtain a copy of the Apache License at
  13. http://www.apache.org/licenses/LICENSE-2.0.
  14. Unless required by applicable law or agreed to in writing, software distributed
  15. under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
  16. OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
  17. the specific language governing permissions and limitations under the License.
  18. Copyright (c) 2023 Audiokinetic Inc.
  19. *******************************************************************************/
  20. #ifndef _AK_MODULATOR_PROCESS_H_
  21. #define _AK_MODULATOR_PROCESS_H_
  22. #include <AK/SoundEngine/Common/AkSimd.h>
  23. #include "AkModulatorParams.h"
  24. #include "PrivateStructures.h"
  25. class CAkEnvelopeProcess
  26. {
  27. public:
  28. inline static void Process(const AkModulatorParams& in_Params, AkUInt32 in_uSamples, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer);
  29. private:
  30. template< typename tPolicy >
  31. inline static void _Process(const AkModulatorParams& in_Params, AkUInt32 in_uFrameSize, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer );
  32. };
  33. class CAkLFOProcess
  34. {
  35. public:
  36. inline static void Process(const AkModulatorParams& in_Params, AkUInt32 in_uSamples, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer);
  37. };
  38. class CAkTimeModProcess
  39. {
  40. public:
  41. inline static void Process(const AkModulatorParams& in_Params, AkUInt32 in_uSamples, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer);
  42. private:
  43. template< typename tPolicy >
  44. inline static void _Process(const AkModulatorParams& in_Params, AkUInt32 in_uFrameSize, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer );
  45. };
  46. inline void CAkLFOProcess::Process(const AkModulatorParams& in_Params, const AkUInt32 in_uFrameSize, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer)
  47. {
  48. const AkLFOParams& params = (const AkLFOParams&) in_Params;
  49. ValidateState(params.m_eState);
  50. out_pOutput.m_eNextState = AkModulatorState_Invalid;
  51. AkLFOOutput& output = static_cast<AkLFOOutput&>(out_pOutput);
  52. DSP::LFO::State state;
  53. params.m_lfo.GetState(state);
  54. output.m_lfo.PutState(state);
  55. AkReal32 fDepthBegin = params.m_fDepth;
  56. AkUInt32 uStartFrame = in_Params.m_uElapsedFrames - in_uFrameSize;
  57. if (uStartFrame < params.m_uAttack)
  58. fDepthBegin = params.m_fDepth * ((AkReal32)uStartFrame)/((AkReal32)params.m_uAttack);
  59. DSP::ModulatorLFOOutputPolicy outputPolicy;
  60. if (in_Params.m_uBufferSize > 0)
  61. {
  62. AkReal32 fDepthEnd = params.m_fDepth;
  63. if (in_Params.m_uElapsedFrames < params.m_uAttack)
  64. fDepthEnd = params.m_fDepth * ((AkReal32)in_Params.m_uElapsedFrames)/((AkReal32)params.m_uAttack);
  65. output.m_lfo.ProduceBuffer(out_pOutputBuffer, in_uFrameSize, fDepthEnd, fDepthBegin, params.m_DspParams.fPWM, outputPolicy );
  66. out_pOutput.m_fOutput = out_pOutputBuffer[in_uFrameSize-1];
  67. out_pOutput.m_fPeak = fDepthEnd;
  68. }
  69. else
  70. {
  71. out_pOutput.m_pBuffer = NULL;
  72. output.m_lfo.SkipFrames(in_uFrameSize-1);
  73. output.m_lfo.ProduceBuffer(&out_pOutput.m_fOutput, 1, fDepthBegin, fDepthBegin, params.m_DspParams.fPWM, outputPolicy );
  74. out_pOutput.m_fPeak = out_pOutput.m_fOutput;
  75. }
  76. }
  77. class CommonOutputPolicy
  78. {
  79. public:
  80. inline static AkReal32 CalcDelta( AkReal32 in_fLevel, AkUInt32 in_uFrames )
  81. {
  82. AkReal32 fFrames = (AkReal32)in_uFrames;
  83. return AK_FSEL( -fFrames, 0.f, (in_fLevel/fFrames) );
  84. }
  85. };
  86. class BufferOutputPolicy: public CommonOutputPolicy
  87. {
  88. public:
  89. inline static AkUInt32 RoundNumFrames(AkUInt32 in_uNumFrames)
  90. {
  91. return ((in_uNumFrames + 2) & ~3);
  92. }
  93. inline static AkReal32 Ramp( AkReal32*& io_pBuffer, AkUInt32 in_uNumFrames, AkReal32 fStart, AkReal32 fDelta, AkReal32& io_fPeak )
  94. {
  95. if (in_uNumFrames != 0)
  96. {
  97. AKASSERT((AkUIntPtr)io_pBuffer % 4 == 0);
  98. AKASSERT(in_uNumFrames % 4 == 0);
  99. AK_ALIGN_SIMD( AkReal32 f4Ramp[4] ) = {0.f, fDelta, 2.f*fDelta, 3.f*fDelta};
  100. AKSIMD_V4F32* pStart = (AKSIMD_V4F32*)io_pBuffer;
  101. AKSIMD_V4F32* pEnd = (AKSIMD_V4F32*)(io_pBuffer + in_uNumFrames);
  102. AKSIMD_V4F32 s4Start = AKSIMD_LOAD1_V4F32(fStart);
  103. AkReal32 f4Delta = fDelta*4.f;
  104. AKSIMD_V4F32 s4Delta = AKSIMD_LOAD1_V4F32(f4Delta);
  105. *pStart = AKSIMD_ADD_V4F32( AKSIMD_LOAD_V4F32( f4Ramp ), s4Start);
  106. AKSIMD_V4F32* pPrev = pStart;
  107. pStart++;
  108. while(pStart < pEnd)
  109. {
  110. *pStart = AKSIMD_ADD_V4F32(s4Delta, *pPrev);
  111. pStart++;
  112. pPrev++;
  113. }
  114. union{ AkReal32 f4Value[4]; AKSIMD_V4F32 vValue; };
  115. vValue = AKSIMD_ADD_V4F32(s4Delta, *pPrev);
  116. //AKASSERT( f4Value[0] >= 0.0f && f4Value[0] <= 1.0f );
  117. io_pBuffer += in_uNumFrames;
  118. AkReal32 fOutput = AkClamp( f4Value[0], 0.0f, 1.0f);
  119. io_fPeak = AkMax( AkMax( fOutput, fStart ), io_fPeak);
  120. return fOutput;
  121. }
  122. return fStart;
  123. }
  124. inline static AkReal32 Set( AkReal32*& io_pBuffer, AkUInt32 in_uNumFrames, AkReal32 fVal, AkReal32& io_fPeak )
  125. {
  126. AKASSERT((AkUIntPtr)io_pBuffer % 4 == 0);
  127. AKASSERT(in_uNumFrames % 4 == 0);
  128. const AKSIMD_V4F32 vValue = AKSIMD_LOAD1_V4F32( fVal );
  129. for(AKSIMD_V4F32 *pStart = (AKSIMD_V4F32*)io_pBuffer, *pEnd = (AKSIMD_V4F32*)(io_pBuffer+in_uNumFrames);
  130. pStart < pEnd; pStart++)
  131. {
  132. *pStart = vValue;
  133. }
  134. io_fPeak = AkMax( fVal, io_fPeak);
  135. io_pBuffer += in_uNumFrames;
  136. return fVal;
  137. }
  138. };
  139. class SingleOutputPolicy: public CommonOutputPolicy
  140. {
  141. public:
  142. inline static AkUInt32 RoundNumFrames(AkUInt32 in_uNumFrames)
  143. {
  144. return in_uNumFrames;
  145. }
  146. inline static AkReal32 Ramp( AkReal32*, AkUInt32 in_uFrames, AkReal32 fStart, AkReal32 fDelta, AkReal32& io_fPeak )
  147. {
  148. AkReal32 fOutput = fStart + fDelta * (AkReal32)(in_uFrames);
  149. io_fPeak = AkMax( AkMax(fOutput, fStart), io_fPeak);
  150. return fOutput;
  151. }
  152. inline static AkReal32 Set( AkReal32*, AkUInt32, AkReal32 fVal, AkReal32& io_fPeak )
  153. {
  154. io_fPeak = AkMax( fVal, io_fPeak);
  155. return fVal;
  156. }
  157. };
  158. template< typename tPolicy >
  159. inline void CAkEnvelopeProcess::_Process(const AkModulatorParams& in_Params, const AkUInt32 in_uFrameSize, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer )
  160. {
  161. const AkEnvelopeParams& params = (const AkEnvelopeParams&) in_Params;
  162. AKASSERT(params.m_fStartValue >= -0.0f && params.m_fStartValue <= 1.0f);
  163. AKASSERT(params.m_fCurve >= -0.0f && params.m_fCurve <= 1.0f);
  164. ValidateState(params.m_eState);
  165. out_pOutput.m_eNextState = AkModulatorState_Invalid;
  166. out_pOutput.m_fPeak = params.m_fStartValue;
  167. const AkUInt32 uStartOffset = (params.m_uStartOffsetFrames & ~(0x3));
  168. const AkUInt32 uHalfAttack = tPolicy::RoundNumFrames(params.m_uAttack / 2);
  169. const AkUInt32 uDecay = tPolicy::RoundNumFrames(params.m_uDecay);
  170. const AkUInt32 uRelease = tPolicy::RoundNumFrames(params.m_uRelease);
  171. AkUInt32 uReleaseFrame = uStartOffset + tPolicy::RoundNumFrames(params.m_uReleaseFrame);
  172. AkUInt32 uCurrentFrame = in_Params.m_uElapsedFrames - in_uFrameSize;
  173. if (params.m_fStartValue > 0.f)
  174. {
  175. AkUInt32 uEffectiveStartFrame = 0;
  176. if (params.m_fStartValue < params.m_fCurve && params.m_fCurve > 0.f)
  177. {
  178. uEffectiveStartFrame = (AkUInt32)((AkReal32)uHalfAttack * (params.m_fStartValue/params.m_fCurve));
  179. }
  180. else
  181. {
  182. uEffectiveStartFrame = uHalfAttack + (AkUInt32)((AkReal32)uHalfAttack * ((params.m_fStartValue - params.m_fCurve)/( 1.0f - params.m_fCurve )));
  183. }
  184. uEffectiveStartFrame = tPolicy::RoundNumFrames(uEffectiveStartFrame);
  185. uCurrentFrame += uEffectiveStartFrame;
  186. uReleaseFrame += uEffectiveStartFrame;
  187. }
  188. AkReal32 fValue = uCurrentFrame > 0 ? params.m_fPreviousOutput : params.m_fStartValue;
  189. AkReal32* pBuffer = out_pOutputBuffer;
  190. AkUInt32 uRemainingFrames = in_uFrameSize;
  191. // START OFFSET
  192. if ( uCurrentFrame < uStartOffset )
  193. {
  194. //Zero out the offset part of the first buffer
  195. AkUInt32 uStartOffsetFrames = AkMin( uStartOffset-uCurrentFrame, in_uFrameSize );
  196. tPolicy::Set( pBuffer, uStartOffsetFrames, 0.f, out_pOutput.m_fPeak );
  197. uCurrentFrame += uStartOffsetFrames;
  198. uRemainingFrames -= uStartOffsetFrames;
  199. }
  200. //ATTACK -- part 1
  201. AkUInt32 uAttackP1End = AkMin( uStartOffset + uHalfAttack, uReleaseFrame );
  202. if (uCurrentFrame < uAttackP1End)
  203. {
  204. AkReal32 fAttackP1Delta = tPolicy::CalcDelta( params.m_fCurve , uHalfAttack );
  205. AkUInt32 uNumAttackP1Frames = AkMin(uRemainingFrames, uAttackP1End-uCurrentFrame);
  206. fValue = tPolicy::Ramp( pBuffer, uNumAttackP1Frames, fValue, fAttackP1Delta, out_pOutput.m_fPeak);
  207. uCurrentFrame += uNumAttackP1Frames;
  208. uRemainingFrames -= uNumAttackP1Frames;
  209. }
  210. //ATTACK -- part 2
  211. AkUInt32 uAttackP2End = AkMin( uStartOffset + 2*uHalfAttack, uReleaseFrame );
  212. if (uCurrentFrame < uAttackP2End)
  213. {
  214. AkReal32 fAttackP2Delta = tPolicy::CalcDelta( (1.0f - params.m_fCurve), uHalfAttack );
  215. AkUInt32 uNumAttackP2Frames = AkMin(uRemainingFrames, uAttackP2End-uCurrentFrame);
  216. fValue = tPolicy::Ramp( pBuffer, uNumAttackP2Frames, fValue, fAttackP2Delta, out_pOutput.m_fPeak);
  217. uCurrentFrame += uNumAttackP2Frames;
  218. uRemainingFrames -= uNumAttackP2Frames;
  219. }
  220. //DECAY -- pre release
  221. AkUInt32 uDecayEndNormal = (uAttackP2End + uDecay);
  222. AkUInt32 uDecayEndPreRelease = AkMin( uDecayEndNormal, uReleaseFrame );
  223. if (uCurrentFrame < uDecayEndPreRelease)
  224. {
  225. AkReal32 fDecayDelta = tPolicy::CalcDelta( params.m_fSustain - 1.0f, uDecay );
  226. AkUInt32 uNumDecayFrames = AkMin(uRemainingFrames, uDecayEndPreRelease-uCurrentFrame);
  227. fValue = tPolicy::Ramp( pBuffer, uNumDecayFrames, fValue, fDecayDelta, out_pOutput.m_fPeak);
  228. uCurrentFrame += uNumDecayFrames;
  229. uRemainingFrames -= uNumDecayFrames;
  230. }
  231. AkReal32 fLevelAtDecayEnd = params.m_fSustain;
  232. //DECAY -- post release
  233. AkUInt32 uPostReleaseDecayDur = 0;
  234. if ( uDecayEndNormal > uReleaseFrame )
  235. {
  236. AkReal32 fLvlAfterAttack = 1.f;
  237. if ( uHalfAttack > 0 )
  238. {
  239. // See how far the attack progressed, before we got the note-off.
  240. AkReal32 fAttackP1Delta = tPolicy::CalcDelta(params.m_fCurve, uHalfAttack);
  241. AkReal32 fAttackP2Delta = tPolicy::CalcDelta(1.0f - params.m_fCurve, uHalfAttack);
  242. fLvlAfterAttack = (fAttackP1Delta)*((AkReal32)(uAttackP1End - uStartOffset)) + (fAttackP2Delta)*((AkReal32)(uAttackP2End - uAttackP1End));
  243. }
  244. AkReal32 fLvlAboveSusAtAttackEnd = fLvlAfterAttack - params.m_fSustain;
  245. // See if we got to the point in the attack where we are above the sustain level.
  246. if (fLvlAboveSusAtAttackEnd > 0.0f)
  247. {
  248. AkReal32 fDecayDelta = tPolicy::CalcDelta( params.m_fSustain - 1.0f, uDecay );
  249. AkUInt32 uReleaseFromAttack = fDecayDelta != 0.f ? ((AkUInt32)(-fLvlAboveSusAtAttackEnd / fDecayDelta)) : 0;// release time taking into account a possibly truncated attack
  250. // the divide the release duration by two and use a steeper slope to get to the release slope faster.
  251. uPostReleaseDecayDur = tPolicy::RoundNumFrames( AkMin( uRelease, AkMin( (uDecayEndNormal-uReleaseFrame), uReleaseFromAttack )) / 2 );
  252. AkUInt32 uDecayEndPostRelease = uDecayEndPreRelease + uPostReleaseDecayDur;
  253. AkReal32 fReleaseDelta = tPolicy::CalcDelta( -(params.m_fSustain), uRelease );
  254. AkReal32 fLvlBelowSusAtDecayEnd = -1.f*(fReleaseDelta)*((AkReal32)(uPostReleaseDecayDur));
  255. //Update this for release slope calc
  256. fLevelAtDecayEnd = params.m_fSustain + fLvlBelowSusAtDecayEnd;
  257. if (uCurrentFrame < uDecayEndPostRelease )
  258. {
  259. AkReal32 fLvlAboveSusAtRelease = fLvlAboveSusAtAttackEnd + (fDecayDelta)*((AkReal32)uDecayEndPreRelease - (AkReal32)uAttackP2End);
  260. AkReal32 fDecayPostReleaseDelta = tPolicy::CalcDelta( -(fLvlAboveSusAtRelease + fLvlBelowSusAtDecayEnd), uPostReleaseDecayDur );
  261. AkUInt32 uNumDecayFrames = AkMin(uRemainingFrames, uDecayEndPostRelease-uCurrentFrame);
  262. fValue = tPolicy::Ramp( pBuffer, uNumDecayFrames, fValue, fDecayPostReleaseDelta, out_pOutput.m_fPeak);
  263. uCurrentFrame += uNumDecayFrames;
  264. uRemainingFrames -= uNumDecayFrames;
  265. }
  266. }
  267. else
  268. {
  269. fLevelAtDecayEnd = params.m_fSustain + fLvlAboveSusAtAttackEnd;
  270. }
  271. }
  272. //SUSTAIN
  273. AkUInt32 uNumSustainFrames = AkMax( (AkInt32)0, AkMin((AkInt32)uRemainingFrames, (AkInt32)uReleaseFrame-(AkInt32)uCurrentFrame) );
  274. if( uNumSustainFrames > 0 )
  275. {
  276. fValue = tPolicy::Set( pBuffer, uNumSustainFrames, params.m_fSustain, out_pOutput.m_fPeak );
  277. uCurrentFrame += uNumSustainFrames;
  278. uRemainingFrames -= uNumSustainFrames;
  279. }
  280. //RELEASE
  281. AkUInt32 uActualReleaseDur = uRelease - uPostReleaseDecayDur;
  282. AkUInt32 uReleaseEnd = uReleaseFrame + uActualReleaseDur;
  283. if (uCurrentFrame < uReleaseEnd)
  284. {
  285. AkReal32 fReleaseDelta = tPolicy::CalcDelta( -(fLevelAtDecayEnd), uActualReleaseDur );
  286. AkUInt32 uNumReleaseFrames = AkMin(uRemainingFrames, uReleaseEnd-uCurrentFrame);
  287. fValue = tPolicy::Ramp( pBuffer, uNumReleaseFrames, fValue, fReleaseDelta, out_pOutput.m_fPeak);
  288. uCurrentFrame += uNumReleaseFrames;
  289. uRemainingFrames -= uNumReleaseFrames;
  290. }
  291. //END
  292. if (uRemainingFrames > 0 && uCurrentFrame >= uReleaseEnd)
  293. {
  294. fValue = tPolicy::Set(pBuffer, uRemainingFrames, 0.f, out_pOutput.m_fPeak );
  295. out_pOutput.m_eNextState = AkModulatorState_Finished;
  296. }
  297. out_pOutput.m_fOutput = fValue;
  298. }
  299. inline void CAkEnvelopeProcess::Process(const AkModulatorParams& in_Params, const AkUInt32 in_uFrameSize, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer)
  300. {
  301. if ( in_Params.m_uBufferSize == 0 )
  302. _Process<SingleOutputPolicy>(in_Params, in_uFrameSize, out_pOutput, out_pOutputBuffer );
  303. else
  304. _Process<BufferOutputPolicy>(in_Params, in_uFrameSize, out_pOutput, out_pOutputBuffer );
  305. }
  306. template< typename tPolicy >
  307. inline void CAkTimeModProcess::_Process(const AkModulatorParams& in_Params, const AkUInt32 in_uFrameSize, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer)
  308. {
  309. const AkTimeModParams& params = (const AkTimeModParams&)in_Params;
  310. ValidateState(params.m_eState);
  311. out_pOutput.m_eNextState = AkModulatorState_Invalid;
  312. out_pOutput.m_fPeak = 0.0;
  313. AkUInt32 uCurrentFrame = in_Params.m_uElapsedFrames;
  314. AkReal32* pBuffer = out_pOutputBuffer;
  315. const AkUInt32 utotalFrames = params.m_uDuration;
  316. const AkUInt32 uloopFrames = params.m_uLoopsDuration;
  317. if (uCurrentFrame > utotalFrames)
  318. {
  319. if (uCurrentFrame < uloopFrames)
  320. uCurrentFrame = uCurrentFrame % utotalFrames;
  321. }
  322. AkReal32 fValue = (AkReal32)AkTimeConv::SamplesToSeconds(uCurrentFrame);
  323. AkReal32 finalValue = (AkReal32)AkTimeConv::SamplesToSeconds(utotalFrames);
  324. fValue = AkMin(fValue, finalValue);
  325. if (uCurrentFrame < in_Params.m_uReleaseFrame)
  326. tPolicy::Set(pBuffer, in_uFrameSize, fValue, out_pOutput.m_fPeak);
  327. else
  328. {
  329. // avoid a spike at end by specifying to use the last value
  330. fValue = tPolicy::Set(pBuffer, in_uFrameSize, finalValue, out_pOutput.m_fPeak);
  331. out_pOutput.m_eNextState = AkModulatorState_Finished;
  332. }
  333. out_pOutput.m_fOutput = fValue;
  334. }
  335. inline void CAkTimeModProcess::Process(const AkModulatorParams& in_Params, const AkUInt32 in_uFrameSize, AkModulatorOutput& out_pOutput, AkReal32* out_pOutputBuffer)
  336. {
  337. if (in_Params.m_uBufferSize == 0)
  338. _Process<SingleOutputPolicy>(in_Params, in_uFrameSize, out_pOutput, out_pOutputBuffer);
  339. else
  340. _Process<BufferOutputPolicy>(in_Params, in_uFrameSize, out_pOutput, out_pOutputBuffer);
  341. }
  342. #endif