//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	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;
	}
}
示例#2
0
	/**
	 * Adds a radio distortion to the input buffer if the radio effect is enabled. 
	 *
	 * @param	InputProcessParameterCount	Number of elements in pInputProcessParameters.
	 * @param	pInputProcessParameters		Input buffer containing audio samples. 
	 * @param	OutputProcessParameterCount	Number of elements in pOutputProcessParameters. 
	 * @param	pOutputProcessParameters	Output buffer, which is not touched by this xAPO. 
	 * @param	IsEnabled					true if this effect is enabled; false, otherwise. 
	 */
	STDMETHOD_( void, Process )(	UINT32 InputProcessParameterCount,
									const XAPO_PROCESS_BUFFER_PARAMETERS *pInputProcessParameters,
									UINT32 OutputProcessParameterCount,
									XAPO_PROCESS_BUFFER_PARAMETERS *pOutputProcessParameters,
									BOOL IsEnabled )
	{
		// Verify several condition based on the registration 
		// properties we used to create the class. 
		check( IsLocked() );
		check( InputProcessParameterCount == 1 );
		check( OutputProcessParameterCount == 1 );
		check( pInputProcessParameters[0].pBuffer == pOutputProcessParameters[0].pBuffer );

		// Check the global volume multiplier because this effect 
		// will continue to play if the editor loses focus.
		if (IsEnabled && FApp::GetVolumeMultiplier() != 0.0f)
		{
			FAudioRadioEffect* RadioParameters = ( FAudioRadioEffect* )BeginProcess();
			check( RadioParameters );

			// The total sample size must account for multiple channels. 
			const uint32 SampleSize = pInputProcessParameters[0].ValidFrameCount * WaveFormat.nChannels;

			const float ChebyshevPowerMultiplier = Radio_ChebyshevPowerMultiplier->GetValueOnAnyThread();
			const float ChebyshevPower = Radio_ChebyshevPower->GetValueOnAnyThread();
			const float ChebyshevCubedMultiplier = Radio_ChebyshevCubedMultiplier->GetValueOnAnyThread();
			const float ChebyshevMultiplier = Radio_ChebyshevMultiplier->GetValueOnAnyThread();

			// If we have a silent buffer, then allocate the samples. Then, set the sample values 
			// to zero to avoid getting NANs. Otherwise, the user may hear an annoying popping noise.
			if( pInputProcessParameters[0].BufferFlags == XAPO_BUFFER_VALID )
			{
				float* SampleData = ( float* )pInputProcessParameters[0].pBuffer;

				// Process each sample one at a time
				for( uint32 SampleIndex = 0; SampleIndex < SampleSize; ++SampleIndex )
				{
					float Sample = SampleData[SampleIndex];

					// 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( Sample == 0.0f )
					{
						continue;
					}

					// Waveshape it
					const float SampleCubed = Sample * Sample * Sample;
					Sample = ( ChebyshevPowerMultiplier * FMath::Pow( Sample, ChebyshevPower ) ) - ( ChebyshevCubedMultiplier * SampleCubed ) + ( ChebyshevMultiplier * Sample );

					// Again with the bandpass
					Sample = GFinalBandPassFilter.Process( Sample );

					// Store the value after done processing
					SampleData[SampleIndex] = Sample;
				}

				EndProcess();
			}
		}
	}