Summary of the project:
I wanted to see if I could use Kismet to make a pseudo Doppler effect. My initial plan was to use the Doppler effect equation to adjust the pitch of a sound emitting object as it passed the player on any axis. However, it soon transpired that this was beyond the default functions in Kismet (I didn’t know at the time that I could write my own Kismet classes) so I decided to limit the direction of travel to the x-axis, and go for a something that sounded more or less like the frequency shift you’d get with a real life Doppler. I hope to go back to this sometime to get it working on all axes, and use the equation in real-time to affect the pitch; it should be achievable using UDK with SuperCollider for example.
Setting up the moving object, sound and player:
I started off by adding my moving object and sound to the world. I found a suitable static mesh in the content browser and added it to the world as an InterpActor, then I added a siren sound as an AmbientSoundMovable, overlaying it on top of the InterpActor.
Here they are together in the viewport:
To get the sound to move wherever the object moves, I hooked them up using the Attach to Actor node in Kismet and linked that to a Player Spawn event node, so that they link when the player spawns. I then created a matinee sequence to move the object between two points so that it would fly back and forth over the world. Finally, I placed a DynamicTriggerVolume over the player spawn point and attached it to the player, so that I could use it to get player location co-ordinates in Kismet later on (I don’t think it’s possible to get co-ordinates directly from the player in Kismet).
Here are the Kismet sequences for the player spawn actions and matinee trigger:
Gathering location and direction data
For simplicity, I’m only applying the pitch shift when the object is moving away from the player, as this is when it is most noticeable. Also, the shift amount is fixed, ie. I’m not taking into consideration the relative movement of the player. This project only aims to give the player an impression of a Doppler effect at this stage. To do it properly, here’s a list scenarios you’d need to consider:
• The object is moving away from the stationary player
• The player is moving away from the stationary object
• The object is approaching the stationary player
• The player is approaching the stationary object
• The object and the player are moving towards one another
• The object and the player are both moving away from each other
• The object and the player are moving in the same direction at different speeds
To know when to apply the pitch shift, I needed to know where the object was in relation to the player and in which direction it was travelling. With that information to hand I’d be able to tell when the object was moving toward the player; at the exact moment it started moving away from the player again, the pitch adjustment could be applied. To get the location co-ordinates, I used the Get Location and Delay nodes in Kismet to capture the player and object locations every 0.02 seconds. I used the Get Distance node to deduce the direction of travel by chaining two nodes together, separated by a delay of 0.01 seconds, and comparing the two figures (the object was attached to input A of the nodes and the DynamicTriggerVolume was attached to input B).
Now all I had to do was set up four Gates in Kismet for my reduced set of four possible scenarios, and hook the inputs up to the outcome of the calculations above:
• Object moving toward its point of origin and player = reset the pitch to normal
• Object moving away from its point of origin and player = lower the pitch
• Object moving away from player and toward its point of origin = lower the pitch
• Object moving toward player and away from its point of origin = reset the pitch to normal
You’ll notice a flaw in that after the pitch is lowered, there’s nothing bringing the pitch up again until the object stops, either at its point of origin or at the opposite end of the matinee track – again, something for a future project… (The attenuation on the sound cue is cunningly set so that the object is out of earshot before any noticeable pitching up would need to occur anyway :))
Here’s the Kismet sequence for getting the locations and direction:
Applying the pitch shift
I used the Modify Property node in Kismet to change the pitch multiplier of the siren sound cue. Ideally, you’d be able to calculate the amount of pitch adjustment required in real-time and set the property value in the Modify Property node dynamically – this last bit isn’t possible though. So instead, I pre-calculated what the pitch adjustment would be and applied it by chaining together five Modify Property nodes, separated by short, gradually lengthening, delays.
The Modify Property node can be fiddly at first – it took me a little whiler to get the right info in the right fields. Find the sound cue or (whatever you’re modifying) in the content browser, right click it and Copy Full Name to Clipboard – paste that into the target field. Then look at the properties of the sound cue, find the property you want to modify (e.g. Pitch Multiplier) right-click and Copy Selected Property to Clipboard – paste that into a text editor and it should be fairly obvious which bit you need to enter in the property name field – in this case it’s PitchMultiplier (note there’s no space).
Here’s the Kismet sequence for adjusting the pitch:
Improvements
As mentioned, this is a fairly limited Doppler, but it sounds pretty realistic in-game, and I learnt a lot about Kismet in the process! I’d like to get it working on all 3 axes for any speed, and add the player movements into the equation (not that that would make much difference to the pitch shift amount, unless maybe the player is buzzing around in a vehicle…).
There’s a video of this in action in the third reel of my game audio showreel.
Hope someone found this useful!