In this lesson, you will learn how to create custom C++ classes that act as modulation sources to programmatically drive MetaSound parameters like gain or pitch based on your game’s internal state.
The Core Concept: Programmable Modulation
While MetaSounds are incredibly powerful for internal signal generation, sometimes your audio needs to react to complex gameplay data—such as a player’s current health, velocity, or proximity to an environmental hazard—that is best calculated in C++. Instead of manually calling SetFloatParameter on an AudioComponent every frame, we create a Modulation Source. This acts as a bridge, allowing your C++ game logic to push data into the MetaSound graph as a continuous, normalized stream.
Implementing the Modulation Source
To create a custom source, you inherit from USoundModulationSource (or a specific subclass if you are targeting specialized data). You then define a float or struct that holds your state data. The engine uses the Update lifecycle to poll these values.
Here is a simplified pattern for exposing a custom C++ value to the Modulation system:
// Your custom modulation source header
UCLASS()
class UHealthModulationSource : public USoundModulationSource
{
GENERATED_BODY()
public:
// This value is updated by your Character class
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float CurrentHealthRatio;
// Override the value provided to the modulation bus
virtual float GetValue() const override { return CurrentHealthRatio; }
};
By defining this class, you can create a Modulation Bus in the editor, assign your UHealthModulationSource to it, and then link that Bus directly to a parameter in your MetaSound graph.
Why Use This Approach?
Using a formal USoundModulationSource is cleaner than generic Blueprint-to-MetaSound communication because it decouples your logic. The MetaSound doesn't need to know where the "Health" value comes from; it only knows it is subscribed to a modulation bus. This allows you to swap your C++ implementation or add complex smoothing logic within the Modulation settings without ever touching the MetaSound graph itself. It turns your game state into an "audio-ready" variable that the engine handles with high-precision threading.
Key Takeaway: Custom Modulation Sources allow you to feed C++ game data into MetaSound graphs as a persistent, decoupled data stream, abstracting game logic away from individual audio component updates.