00001 00002 // 00003 // Copyright (c) 2006 Audiokinetic Inc. / All Rights Reserved 00004 // 00006 00007 #ifndef _AKFXTAILHANDLER_H_ 00008 #define _AKFXTAILHANDLER_H_ 00009 00010 #include <AK/SoundEngine/Common/AkTypes.h> 00011 #include <AK/SoundEngine/Common/AkCommonDefs.h> 00012 #include <AK/Tools/Common/AkPlatformFuncs.h> 00013 00015 #define AKFXTAILHANDLER_NOTINTAIL 0xFFFFFFFF 00016 00020 class AkFXTailHandler 00021 { 00022 public: 00024 inline AkFXTailHandler() 00025 : uTailFramesRemaining( AKFXTAILHANDLER_NOTINTAIL ) 00026 , uTotalTailFrames(0) {} 00027 00029 inline void HandleTail( 00030 AkAudioBuffer * io_pBuffer, 00031 AkUInt32 in_uTotalTailFrames ) 00032 { 00033 bool bPreStop = io_pBuffer->eState == AK_NoMoreData; 00034 if ( bPreStop ) 00035 { 00036 // Tail not yet finished processing 00037 if ( uTailFramesRemaining > 0 00038 || io_pBuffer->uValidFrames > 0 // <-- there are valid frames, so last (maybe partially filled) buffer. 00039 ) 00040 { 00041 // Not previously in tail, compute tail time 00042 if (uTailFramesRemaining == AKFXTAILHANDLER_NOTINTAIL 00043 || io_pBuffer->uValidFrames > 0 // <- ANY valid frames in the buffer should reset the tail. 00044 ) 00045 { 00046 uTailFramesRemaining = in_uTotalTailFrames; 00047 uTotalTailFrames = in_uTotalTailFrames; 00048 } 00049 // Tail time changed, augment if necessary but preserve where we are so that effect will 00050 // still finish when constantly changing this based on RTPC parameters 00051 else if ( in_uTotalTailFrames > uTotalTailFrames ) 00052 { 00053 AkUInt32 uFramesElapsed = uTotalTailFrames - uTailFramesRemaining; 00054 uTailFramesRemaining = in_uTotalTailFrames - uFramesElapsed; 00055 uTotalTailFrames = in_uTotalTailFrames; 00056 } 00057 // Always full buffers while in tail 00058 AkUInt32 uNumTailFrames = (AkUInt32)(io_pBuffer->MaxFrames()-io_pBuffer->uValidFrames); 00059 uTailFramesRemaining -= AkMin( uTailFramesRemaining, uNumTailFrames ); 00060 io_pBuffer->ZeroPadToMaxFrames(); 00061 if ( uTailFramesRemaining > 0 ) 00062 io_pBuffer->eState = AK_DataReady; 00063 } 00064 } 00065 else 00066 { 00067 // Reset tail mode for next time if exits tail mode (on bus only) 00068 uTailFramesRemaining = AKFXTAILHANDLER_NOTINTAIL; 00069 } 00070 } 00071 00072 #ifdef __SPU__ 00073 00074 00076 AkForceInline void HandleTailChannelPre( AKRESULT in_eAudioBufferState, AkUInt32 in_uTotalTailFrames ) 00077 { 00078 bool bPreStop = in_eAudioBufferState == AK_NoMoreData; 00079 if ( bPreStop ) 00080 { 00081 // Tail not yet finished processing 00082 if ( uTailFramesRemaining > 0 ) 00083 { 00084 // Not previously in tail, compute tail time 00085 if ( uTailFramesRemaining == AKFXTAILHANDLER_NOTINTAIL ) 00086 { 00087 uTailFramesRemaining = in_uTotalTailFrames; 00088 uTotalTailFrames = in_uTotalTailFrames; 00089 } 00090 // Tail time changed, augment if necessary but preserve where we are so that effect will 00091 // still finish when constanly changing this based on RTPC parameters 00092 else if ( in_uTotalTailFrames > uTotalTailFrames ) 00093 { 00094 AkUInt32 uFramesElapsed = uTotalTailFrames - uTailFramesRemaining; 00095 uTailFramesRemaining = in_uTotalTailFrames - uFramesElapsed; 00096 uTotalTailFrames = in_uTotalTailFrames; 00097 } 00098 } 00099 } 00100 else 00101 { 00102 // Reset tail mode for next time if exits tail mode (on bus only) 00103 uTailFramesRemaining = AKFXTAILHANDLER_NOTINTAIL; 00104 } 00105 } 00106 00108 AkForceInline void HandleTailChannel( AkAudioBuffer * in_pAudioBuffer, AkReal32 * io_pfChannelData ) 00109 { 00110 bool bPreStop = in_pAudioBuffer->eState == AK_NoMoreData; 00111 if ( bPreStop && (uTailFramesRemaining > 0) ) 00112 { 00113 // Always full buffers while in tail 00114 AkUInt32 uNumTailFrames = (AkUInt32)(in_pAudioBuffer->MaxFrames()-in_pAudioBuffer->uValidFrames); 00115 AkZeroMemLarge( io_pfChannelData + in_pAudioBuffer->uValidFrames, uNumTailFrames * sizeof(AkReal32) ); 00116 in_pAudioBuffer->uValidFrames = in_pAudioBuffer->MaxFrames(); 00117 } 00118 } 00119 00121 AkForceInline void HandleTailChannelPost( AkAudioBuffer * io_pBuffer ) 00122 { 00123 bool bPreStop = io_pBuffer->eState == AK_NoMoreData; 00124 if ( bPreStop && (uTailFramesRemaining > 0) ) 00125 { 00126 uTailFramesRemaining -= AkMin( uTailFramesRemaining, (AkUInt32)(io_pBuffer->MaxFrames()-io_pBuffer->uValidFrames) ); 00127 if ( uTailFramesRemaining > 0 ) 00128 io_pBuffer->eState = AK_DataReady; 00129 } 00130 } 00131 #endif 00132 00133 protected: 00134 00135 AkUInt32 uTailFramesRemaining; // AKFXTAILHANDLER_NOTINTAIL, otherwise value represents number of frames remaining in tail 00136 AkUInt32 uTotalTailFrames; 00137 00138 } AK_ALIGN_DMA; 00139 00140 00141 00142 00143 00144 #endif // _AKFXTAILHANDLER_H_