/** Evaluates the LegendrePolynomial for L,M at X */ FORCEINLINE FLOAT LegendrePolynomial(INT L,INT M,FLOAT X) { switch(L) { case 0: return 1; case 1: if(M == 0) return X; else if(M == 1) return -SafeSqrt(1 - X * X); break; case 2: if(M == 0) return -0.5f + (3 * X * X) / 2; else if(M == 1) return -3 * X * SafeSqrt(1 - X * X); else if(M == 2) return -3 * (-1 + X * X); break; case 3: if(M == 0) return -(3 * X) / 2 + (5 * X * X * X) / 2; else if(M == 1) return -3 * SafeSqrt(1 - X * X) / 2 * (-1 + 5 * X * X); else if(M == 2) return -15 * (-X + X * X * X); else if(M == 3) return -15 * appPow(1 - X * X,1.5f); break; case 4: if(M == 0) return 0.125f * (3.0f - 30.0f * X * X + 35.0f * X * X * X * X); else if(M == 1) return -2.5f * X * SafeSqrt(1.0f - X * X) * (7.0f * X * X - 3.0f); else if(M == 2) return -7.5f * (1.0f - 8.0f * X * X + 7.0f * X * X * X * X); else if(M == 3) return -105.0f * X * appPow(1 - X * X,1.5f); else if(M == 4) return 105.0f * Square(X * X - 1.0f); break; case 5: if(M == 0) return 0.125f * X * (15.0f - 70.0f * X * X + 63.0f * X * X * X * X); else if(M == 1) return -1.875f * SafeSqrt(1.0f - X * X) * (1.0f - 14.0f * X * X + 21.0f * X * X * X * X); else if(M == 2) return -52.5f * (X - 4.0f * X * X * X + 3.0f * X * X * X * X * X); else if(M == 3) return -52.5f * appPow(1.0f - X * X,1.5f) * (9.0f * X * X - 1.0f); else if(M == 4) return 945.0f * X * Square(X * X - 1); else if(M == 5) return -945.0f * appPow(1.0f - X * X,2.5f); break; }; return 0.0f; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // RadioEffectUnit::RadioEffectKernel::Process // // pass-through unit //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void RadioEffectUnit::RadioEffectKernel::Process( const AudioUnitSampleType * InSourceP, AudioUnitSampleType * InDestP, UInt32 InFramesToProcess, UInt32 InNumChannels, bool & IOSilence ) { // we should be doing something with the silence flag if it is true // like not doing any work because: // (1) we would only be processing silence and // (2) we don't have any latency or tail times to worry about here // // So, we don't reset this flag, because it is true on input and we're not doing anything // to it so we want it to be true on output. // BUT: your code probably will need to take into account tail processing (or latency) that // it has once its input becomes silent... then at some point in the future, your output // will also be silent. UInt32 NumSampleFrames = InFramesToProcess; const AudioUnitSampleType *SourceP = InSourceP; AudioUnitSampleType *DestP = InDestP; const FLOAT ChebyshevPowerMultiplier = GetParameter(RadioParam_ChebyshevPowerMultiplier); const FLOAT ChebyshevPower = GetParameter(RadioParam_ChebyshevPower); const FLOAT ChebyshevCubedMultiplier = GetParameter(RadioParam_ChebyshevCubedMultiplier); const FLOAT ChebyshevMultiplier = GetParameter(RadioParam_ChebyshevMultiplier); while (NumSampleFrames-- > 0) { AudioUnitSampleType InputSample = *SourceP; SourceP += InNumChannels; // advance to next frame (e.g. if stereo, we're advancing 2 samples); // we're only processing one of an arbitrary number of interleaved channels // here's where you do your DSP work // Early-out of processing if the sample is zero because a zero sample // will still create some static even if no audio is playing. if( InputSample != 0.0f ) { // Waveshape it const FLOAT SampleCubed = InputSample * InputSample * InputSample; InputSample = ( ChebyshevPowerMultiplier * appPow( InputSample, ChebyshevPower ) ) - ( ChebyshevCubedMultiplier * SampleCubed ) + ( ChebyshevMultiplier * InputSample ); // Again with the bandpass InputSample = GFinalBandPassFilter.Process( InputSample ); } *DestP = InputSample; DestP += InNumChannels; } }