Differences between FMOD & Wwise: Part 1

After working with FMOD everyday for a couple of years, I started a new job where we are using Wwise. This change give me the chance to think about the differences between the two.

Let me be clear, I don’t particularly advocate for either of them but it is interesting to think about their different concepts and workflow. You can also consider these notes a companion if you are migrating from FMOD to Wwise like I did.

Event Workflow: separating content and action

Events are the minimal functional unit for playing audio. This is is a concept that is shared by both softwares but the workflow is quite different.

On FMOD, events are self-contained in the sense that the event itself has a timeline where you can add any audio that you want. I think this is more straightforward and DAWish which is very novice friendly. You also have an audio bin where all your audio assets sit, ready to be added to events. All the rules that determine how audio will play at runtime can also be found on each event, on the Event Macros section. Have a look at this article if you want to know how these work.

An FMOD event allows you to clearly set different tracks, parameters and plugins to affect the sound during gameplay.
You also set the general event behaviour in terms of 3D positioning, envelopes and parameters.

Wwise does this very differently, which might be confusing at first. To start with, there is no audio bin per se, but we use a “Sound SFX”. These don’t represent a single audio file necessarily, but a “channel” that plays audio. But don’t really think about Sound SFXs as channels in the sense of a mixing desk or DAW, they are more like containers with a set of rules to describe how to play audio. So things like pitch, volume, looping or insert effects live on Sound SFXs on Wwise. On FMOD, these would live on each track within an event. But Wwise Sound SFXs also contain things like positioning settings which in the case of FMOD live on the event level.

A Sound SFX feels like a weird concept at the start but it makes sense if you think about it as a “behaviour container” for audio.

But if we want to play audio from our game with Wwise, Sound SFXs are not the thing we need to call. We need to create an event which in turn can play our Sound SFX. In other words, Wwise separates content and action, while FMOD keeps them together. Is one better than the other? I don’t think so, they are just different approaches to solve the same problem and you just need to get used to each way of them.

Actor-Mixers that don’t mix but kinda

These guys are also a bit weird, specially at first. Despite their name, they are NOT the main way you want to mix your game. Actor-Mixers don’t act as a bus for all the Sound SFXs that they contain, so their audio signals are not really combined at this level. That happens on buses and auxiliars on the Master-Mixer Hierarchy, which are the best option for actually mixing your game.

So Actor-Mixers act as a yet another container, they are useful for setting effects, positioning or parameter curves for a bunch of Sound SFXs at the same time. Remember when I said Sound SFXs were behaviour containers? Well Actor-Mixers are kind of the same thing, they are basically a group of Sound SFXs that share the same behaviour.

Actor-Mixers can be confusing. They have “mixer” in their name, they have faders in their icon… but they don’t actually bus any audio. They just dictate behaviour. Not very intuitive.

Grouping SFXs like this is useful if you want to tweak things in the same way for a bunch of Sound SFXs and also if maybe you want to do general mix tweaks but they are probably not the best option for most mixing work, particularly dynamic mixing based on states.

Is hard to find an equivalent on FMOD to the Actor-Mixer, the closest thing could be a mix between VCAs and effect chain presets but it is fundamentally a very different way to organize things.

Game Calls: a radical difference in philosophy

This illustrates yet again the difference in approach on each middleware. Is going to sound odd but bare with me.

So Wwise uses this concept of “Game Calls” which are basically orders that the game sends to Wwise. These usually match event names like for example “Play_Jump” or “Stop_MainMusic” but if you think about it, game calls are in reality generic and ambiguous in the sense that they don’t have to do what their names suggests.

So an approach that maybe makes more sense with Wwise is to give game calls names like “Protagonist_Jump”. We know that the character jumped so now is our job to decide what audio should do to reflect that action. Usually, this means playing a Sound SFX but it could also mean stopping or pausing other Sound SFX, maybe even changing some other audio’s settings. This philosophy gives you more flexibility but it takes a bit to wrap your head around it. That’s why, when you set up a Wwise event, you can do all sorts of actions in there, although 90% of the time, you probably just want to play or stop audio.

Events offer many types of actions. For me, it helps to think about events not as a “Play this audio” order but as a “Something happened” piece of information. Our job as sound designers is to decide what to do with this information.

Contrast this with FMOD, where the game engine is always explicit in how it sends orders. When using the FMOD API, we directly and explicitly say “play this event” or “stop that event” so, for the most part, there is no room to do anything else, although you can break this workflow a bit by using command instruments.

This difference in philosophy is something that I don’t usually hear people talking about. Is subtle but I think is one of the keys to understand how Wwise and FMOD do things differently. The net result is that Wwise keeps a bit more logic control on the middleware side but pays the price of being a bit more confusing. FMOD, on the other hand, is more straightforward but more control resides on the game engine side since the calls are always specific. To summarize this point:

Wwise: Game calls are ambiguous, not necessarily tied to an specific action like playing audio.

FMOD: Game calls are unambiguous and very specific: tied to an specific event and action.

Work Units & Source Control

On Wwise, everything resides on a container called “Work Unit” from Sound SFXs to events and parameters. YES, another container! This is a bit weird, since it feels like the type of thing that is not usually user facing but an internal system to organize files. Work Units are really .xml files which is funny because FMOD also uses this format but the files are not as visible to the user.

The idea is to organize things in these different containers, so different people can work on the same project. They won’t conflict as long as they work on different units.

This makes a lot of sense until you realize that FMOD doesn’t have anything similar to this and it works nicely anyway when sharing a project with others, at least in my experience. I have used SVN source control, not even the official implementation that FMOD has (this gave me issues), just plain sharing the FMOD project files with SVN. You won’t conflict as long as you don’t work on the same event or mixer bus so FMOD is actually more granular than a work unit, is like each element is its own working unit!

Containers vs instruments

Wwise containers work in a kind of similar way to FMOD instruments. Roughly, you can make the following comparisons:

Wwise FMOD Notes
Sound SFX Single Instrument They work in the same way.
Random Container Multi Instrument Similar randomization options.
Sequence Container -- FMOD allows this by allowing many instruments on an event. Is probably easier to setup too.
Switch Container -- Om FMOD, you woud just use a parameter sheet or trigger conditions on instruments.
Blend Container -- FMOD does this natively on its timeline since you can crossfade instruments based on time or parameter values.
-- Event Instrument Wwise doesn't allow nested events in the same way as FMOD does but you have more flexible event actions.
-- Scatterer Instrument Can be recreated in Wwise!
-- Programmer Instrument Nothing like this on Wwise, but there is no need since game calls are ambiguous.
-- Command Instrument Same as above.
-- Snapshot Instrument On Wwise, you can always trigger states from an event an achieve the same result.

So as you can see, between Wwise and FMOD, there is no perfect option. I particularly miss the scatterer instrument in Wwise but is true that it has its limits and annoying things in FMOD anyway. For example, the fact that it always plays a sound the first time you enter the instrument, without respecting the spawning time.

On the other hand, on Wwise, you don’t have these specific instruments like the programmer or command instruments but there is no need really, since you can add as many actions as you want to an event.

I just think you need to get used to the differences and learn to think in a different way for each piece of software. Advantages and disadvantages on both sides for sure. In engineering, every decision is a trade off.

More thoughts coming on part 2!

How (and how much) to charge as a game audio freelancer

If you are into game audio, chances are you are a creative person and probably negotiating rates and studying the market is not the kind of thing you enjoy. I have been there. So here are a few tips on how to make these things a bit easier. Most of these basic ideas also apply to negotiating salaried positions.

Costs and prices directionality

Before we get into it, some economic concepts. There are basically two perspectives: Costs inform prices or vice versa. Let’s see both cases:

  • Costs inform prices: This view first looks at the costs we have to incur to do our job plus our “salary” that we use to just live. So some people recommend calculating your living and working expenses taking into account taxes, holidays, sick days plus some extra margin for safety. Once you come with a number, you can do the math to know how much you should charge (your price as a professional).

  • Prices inform costs: We go the other way around. The very first thing we determine is how much our expertise and time is worth. Not how much we think is worth, how much the outside world thinks is worth and that’s a key distinction. Once we have an approximation, we know our rate and we can now consider if it is enough to cover our expenses.

Which one is better? Which one is true? Is a matter of perspective but in my opinion, the second option is superior. I prefer it because, in the short-medium term you will probably have more control of your costs than of your real market worth. In other words, it is easier to cut costs than to improve your professional profile, at least in the short term. If you start off with a wrong assumption about your worth (because you think about costs first), you will handicap your career from the start.

So let’s see how we can infer how much value our work really has.

Figuring out your worth

I want to stress again that it doesn’t matter if you think you are great and should be paid like one of those high profile lawyers, it is the people who need your services who determine your worth. That’s the ugly truth but there is a silver lining.

If you are starting out or in the first years of your career you most likely have the opposite problem: you are undervaluing your worth. So the great news is that people that potentially want to hire would probably pay you more than you think. Awesome. Now let’s figure out how to enter these conversations with something to guide us.

Prices are lights that guide us in the darkness of uncertainty. Without them, you would not know if it is better to go somewhere by helicopter, car or bus. They are needed to calculate and make decisions. If you enter a conversation with a potential client and you don’t really know how much your work is worth, you are starting off with a hand tied behind your back.

The best thing to do is to look around, study the market Check out salary surveys and polls. Also have a look at sites like Glassdoor or Payscale. Talking to audio peers is also a good idea. Take all these numbers into account carefully. To start with, salaries vary enormously per country and per city so try to adapt the numbers to your situation. Same applies with years of experience and the technologies or skills that you are comfortable with. Try to calculate a number that roughly matches your case. It will never be 100% accurate because there is no true accurate number. Is only an approximation but a very useful one.

Once you have a number, you can do the math to get an idea of your hourly rate and your yearly rate. Both are useful to calculate things later. Take into account that these rates should be pre-tax and should include a “freelance premium” of about 15-25% to account for the uncertainty of gig based work. If you want a salaried position in a studio, your rate should probably be lower.

Now that we have our basic rate, let’s see how we can charge for our work. I think all these methods are valid, it all depends on the circumstances so it is good to have all of them under your belt.

Charging per time worked

This is common in a lot of professional disciplines. The good part is that if the job takes more time than expected, you will get paid for that extra workload, which gives you a lot of power. The bad part is that it creates the incentive of “wasting time” or at least that’s what your client may think is going to happen.

Put on your client shoes. Imagine you are paying for a wall to be built in your house and they want you to pay them by the hour. In a certain way, that’s like signing a blank check since you don’t exactly know how much time it would take. Your client could also have no idea how much time it takes to make 12 sound effects or 3 minutes of music. So what would you do? Probably ask for an estimate, right? That’s why charging per hour or per day is tricky.

I personally haven’t used this method much, I think it is best suited for short jobs that are not easy to measure in any other way. It could also be a good option if the client trusts you and knows how you work.

Charging per asset

Usually, this means charging per sound effect and/or per minute of music. Implementation and music mix/recording/production could be included or not. I feel this is a good middle ground method and I have used it quite a bit. It is very flexible since it accounts for additional work that may come up in the development process.

Having said that, it also suffers from the same issue as charging per hour, although the effect is softened. A client could think: ok, I pay per asset but I’m not sure how many assets I need, how much is this going to cost me really? To continue with the analogy, imagine they charge you per brick laid and you know you need a wall but you are not sure how many bricks you will end up needing.

If we think this through, I believe the responsibility lays mostly on the client here. I’m telling you how much I charge per asset so if you don’t know how many you need, that’s understandable but you should at least have an approximation. Since you know my rates, it would not be hard to calculate a final cost range, at least.

The other side of this coin and one of the drawbacks of this method is that it often happens that you feel a certain feature needs a SFX but since the client didn’t specifically ask for it, now it “ could look” like you just want to make that extra SFX for the extra money. 100% of the time in my case I’m just thinking it would be cool to have a sound there and I’m not thinking about the money but you need to consider your client’s perspective. Creating a trusting professional relationship is the best solution to this but that takes time.

Additionally, sometimes in the past I have charged a different rate depending on the complexity of the asset. I have tried things like a 3 tier system: easy, medium & hard and keep track of everything on a spreadsheet. This is something you can try but I don’t think is very useful. In my mind, that way I charge more precisely for my work but in reality what happened is that the easy stuff cancelled out the hard stuff and you end up more or less charging the medium price on average. So I would just charge one price but maybe take this idea into account for some parts of the job that are particularly complicated.

Charging a flat rate per project

With this method we eliminate all uncertainty on the client side but in the process, we move it to our side. I feel this is the easiest way to land a job but at the same time you will probably end up under charging.

There are a few ways to mitigate this. You can make clear how many revisions are included. You can set time limits on certain parts of the job or on the whole thing. You can also try to limit time used (or wasted) on meetings, briefings and emailing back and forth.

In general, your goal with this method is to arrive at a price that is fair and this takes practice. You would need an estimation on the amount of work ahead (number of SFXs or minutes of music) and then you can use your rate to do the math. Adding contingency and at least one revision into the price is a good idea too.

Bidding

Negotiating is an art that is hard to learn but my rule of thumb is to always charge more rather than less. Is better for a client to say no because you are too expensive, rather than say no because they think you are so cheap, you must be a bad choice. Trying to quote higher prices also mitigates the usual tendency creative people have of undervaluing ourselves, particularly at the beginning of our careers.

If you don’t really want to do a gig or you are too busy, it could be a good idea to quote a price that is a bit crazy high. You win either way: if they say no, you didn’t want to do it anyway. If they say yes, maybe at that price it is worth the effort.

On the other hand, sometimes it could be a good idea to under charge a bit if for example you are offered a longer contract and you know there will be a steady influx of work coming. Be careful with this though, nothing is permanent when you are a contractor.

Final note on working for free

Should you work for free? Very controversial topic so I will be brief: never work for nothing. Maybe you won’t always get money out of a project but you must get something. Sometimes learning or networking is worth more than money, especially learning but be extremely careful with this. Working for exposure is usually not worth it though, at least in my opinion.

Doing things like an unpaid internship, participating in a jam or on a small indie project are good ways of learning or networking and they can be a good use of your time, in my opinion. Always ask yourself, is this good for my career? Never forget that your work has value.

Using Fmod Preset Effects & Chains

Hi there, just wanted to share an overview on the FMOD’s preset system and an example on how I personally use it.

About Preset Effects in general

You can save any insert or send values on a preset which is very handy for things that you always want to do in the same way, like for example a high-pass filter.

To do this, just right click on the insert and choose “Convert to Preset”. This will create a new preset that you can find on the Preset browser. Is probably a good idea to name them and organize them in folders. You can also create a new preset from scratch on the Preset Browser.

If you want to then use the same preset somewhere else, you just need to click on add effect, choose “Preset Effect” and choose the preset. Something to keep in mind is that If you then modify the values on the plugin you are modifying the values for ALL the instances.

So generally, don’t use a preset if you think you are going to need to fine tune the values on particular events. Notice that next to the bypass icon there is a preset icon (small arrow) that indicates that this is part of a preset. If you need to modify a certain instance of a preset, you should first do right click, “Detach from Preset”.

Something else to keep in mind is that presets can’t be used on the mixer, only on the events’ process chain. Not sure why this is the case but this could be fixed in the future.

Effects Chains

We can apply the same concept of presets to more than one plugin. This is useful for situations where you have many events of the same type (like footsteps or ambiences) to which you want to apply the same processing. I personally use it a lot for automation curves that use parameters, like custom distance attenuation curves.

To make an effect chain, you can create them on the Preset Browser with right click, "New Preset” and “New Effect Chain”. Then you can add or drag and drop effects from an event,

Keep in mind that the same rules effects presets have, apply here so you should detach from the preset if you want a particular instance to be different.

A great advantage of creating effects chains is that you don’t only save the plugins values but also automation and modulation like envelopes and LOFs. Even parameter usage is saved.

Usage Example

Let’s use an effect chain for our footsteps events. We have two different parameters that affect the footsteps: normalized distance and intensity. Since we want to have a custom distance attenuation curve, we turn distance attenuation off on the spatializer and we create our own curve. Similarly, we want to affect the event level as different intensity values are used.

So we add both parameters to the effect. Now, a normal approach would be to automate the master volume of the event using our two parameters. The problem with this approach is that we won’t be able to save the automation on an effect chain because an event master fader can’t be included in a preset (since it’s not really a plugin).

So to solve this, we are going to create new gain inserts after fader, that we will use to automate the volume. Another advantage of this approach is that we can then keep the master fader as an overall level control that is not affected by any parameters.

We create these two gain inserts and now we just need to automate each of them with our parameters. We could also use a single insert but sometimes I like to have two separate ones to avoid maxing out its headroom, since they can only do +10 dB.

Now that we have our automation curves, we can create a new chain effect preset, and drag and drop our curves there. See how our chain saves everything: modulation curves, parameters used and any other values. Now you just need to add this to all your other footsteps events by using right click > “Add Effect” > “Preset Effect” and choosing your chain.

If you then need to tweak the curves, the changes will affect all your footsteps events, keeping them in sync and saving tons of time, especially on big projects. Of course, if you need to have different curves on a particular footstep event, you can always detach it from the preset.

Using Fmod Doppler on Unity without a rigidbody

As I mentioned on this article, Fmod includes a built-in doppler feature but unfortunately it requires two things in order to work on Unity:

  • A rigidbody on the game object where the emitter is.

  • The game object needs to be moving via the physics engine, like for example using Rigidbody.AddForce or just using gravity.

This limitation has prevented me from really using the doppler effect since, on the games I have worked on, we usually move objects by code or using animations which means that Unity’s physics engine has no clue what the object’s velocity is, so in turn, Fmod doesn’t know either.

Additionally, we would also need to know the listener’s velocity, since in nature the doppler effect always takes into consideration the relative velocity between the listener (you and your ears driving in a car) and the emitter (another car’s horn).

So let’s jump into Unity and try to find a solution for this problem. I took most of the code from this thread on the Fmod forums.
Note: this work was done on the following versions so as time goes by, it could get more and more outdated:

  • Fmod Studio & Fmod Unity implementation plugin version: 2.02.04

  • Unity version: 2020.3.19f1

You can get this project on GitHub so you can copy the code more easily or play around with it. Here is the zipped project in case you prefer that.

Using Doppler with a rigidbody and the physics engine

Before we do anything else, let’s see how the system was intended to be used by default. As you can see in the video below, I have a very basic setup: I created a new, clean Unity project, integrated Fmod into it and created an Fmod project.

The Fmod project simply contains a 3D event with a looping testing sine wave tone. On the Unity project I just have a camera with the Fmod studio listener, a plane with no collisions and a cube. On the cube, I added a rigidbody and an Fmod emitter. As you can hear, at first we hear no doppler effect but activating the doppler feature on the event macro section and re-building banks makes the doppler effect work.

So now that we can see that Doppler is working when using gravity, let’s try switching the movement to just animation. As you can see, I disabled gravity, added an Animator to the cube and made an animation so it falls in a similar way as it does with the physics engine. You can clearly hear that there is no doppler in this case and we only get it back when we switch the gravity back on and disable the animator. So this is basically the problem we need to solve.

How Fmod receives velocity information

If we look at Fmod’s documentation, we can see that: “The Doppler property requires velocity in order to calculate how much Doppler adjustment needs to be applied. Velocity can be provided by the game engine or by calling EventInstance::set3DAttributes. In the case of the Unity and Unreal Engine integrations, this is usually set automatically to match the velocity of the associated Rigidbody or RigidBody.”

So this is how we are currently sending the velocity to Fmod, via the rigibody. But as the docs say, we can also provide this information manually which means we need to calculate the velocity ourselves but at least we don’t depend on the physics engine anymore. Let’s call this manually calculated velocity, “kinematic velocity”, since it doesn’t care about the forces applied, just the movement itself.

Let’s adapt the default Fmod emitter. I personally don’t use it since I have my own emitters but the default one is a good example to learn what’s going on.

Modifying StudioEventEmitter

First, let’s think about when we want to use kinematic velocity. In theory, everytime there is no rigidbody, we want to potentially use it but it would be a waste to do it if the event in Fmod is not even using doppler. On the other hand, sometimes we will have a rigidbody and we still want to use kinematic velocity since the object could be moved by just animation or code.

First, I thought about reading the event description to see if the event in question had doppler activated and turn on kinematic velocity based on that. The problem with this approach is that sometimes we may have doppler turned off, but we still want to send kinematic velocity information to Fmod to use it as a parameter for other things.

So my solution was to add a new option to StudioEventEmitter where you can set if you want to calculate kinematic velocity. This would be independent of having a rigidbody and also independent of the event having doppler activated. So firstly, let’s add a new bool variable to the public settings within StudioEventEmitter:

Since this class uses a custom made editor, we need to modify the editor class too:

As you can see, the class now has an additional option on the inspector.

We then declare a couple of variables on StudioEventEmmiter that we need to calculate the game object’s velocity:

As you can see, I’m using a VelocityVector3 class that is new to both Unity and Fmod. Let’s create this class on RuntimeUtils:

Next, let’s create a method to calculate the velocity on a given frame and update our velocity related variables:

On Update(), we want to call the previous method, but we only do it if we are using kinematic velocity for this particular event:

We are almost finished with StudioEventEmitter. The last thing we want to do is make sure that we attach the Fmod instance to the gameobject in a slightly different way when we want to use kinematic velocity. This is done within the PlayInstance() method.

So we modify the code to be:

As you can see, we are making sure we only attach the rigidbody if it exists AND we don’t want to use kinematic velocity. Otherwise, we use our new kinematic velocity. Here we are using a new overload on AttachInstanceToGameObject() that we don’t have yet. We will fix this in the next section.

RuntimeManager

This script takes care of updating things at runtime. We need to do a few modifications for our kinematic velocity to work. We first add two new variables to the AttachedInstance class. We do this so we can keep track of the velocities without a rigidbody.

Next, we create the overload we were missing before. As you can see, this attaches the Fmod instance to the game object and uses our kinematic velocity class instead of a rigidbody.

We now need to make sure we are updating the values on each frame. As mentioned earlier, this is accomplished by setting the 3D attribute by hand. So we look for the Update() method and we modify it like so:

Essentially, we are making sure we only update the attributes based on the rigidbody when it exists AND we are not using kinetic velocity. Otherwise, we update the values including kinetic velocity.

Notice that to be able to do this we need to overload the To3DAttributes() method on RuntimeUtils like so:

StudioListener

The last thing we need to do is also modify the Fmod listener. We need this since the Doppler effect is always based on the relative velocity of the emitter and listener. So we need to tweak StudioListener (or you could also create a child from it) to be able to measure its kinematic velocity.

We first add the same variables we added to StudioEventEmiiter. We also make sure we initialize the kinematic velocity variable if no rigidbody is found. You may need to modify this if your listener lives on a game object that has a rigidbody and you still want to use kinematic velocity.

We now copy the same method we used before for calculating speed in real time and we make sure we call it each frame if we are using kinematic speed.

The last thing we need to do here is to modify SetListenerLocation() so we can also use kinematic velocity as an option:

To make this work, we also need to overload SetListenerLocation() on the RuntimeManager:

And that’s all the code work finished!

Final Results

If everything went well, we should now be able to hear the doppler effect with no rigidbody and just moving the object via animations. As you can see, Fmod can now also get velocity values, which could also be useful to modify the audio based on them.

Success! These modifications could be done in many different ways depending on your needs so take my take as inspiration. If this doesn’t work for you or you have questions, feel free to contact me.

Remember that you can get this project on GitHub to play around with. Here is the zipped project in case you prefer that.

Fmod Event Macros

Here is an overview at how you can control each event in fmod, what the limitations are and what you can achieve by programming your own systems on top.

I’m going to cover a bit of the same content you can read about on the Fmod documentation but I will also be adding my own comments from the perspective of someone using them in the real world.

Persistent

By default, Fmod events stop after they don’t have anything else to play. This notion of “anything else to play” includes any timeline markers or regions. Once the event reaches the last item on the timeline it will stop by itself.

If you want to avoid this, you can make the event persistent which will mean that it will only stop when explicitly told. I usually use this when I’m not playing the event based on the timeline but based on parameters values. Just remember that you need to stop the event later somehow.

Pitch

This is a general pitch control for the whole event which works on top of the instruments pitch values. Remember that both this pitch control and the one on instruments changes the playback speed, so the length of the sound will be altered.

Having a macro control is useful when you want to control multiple instruments within an event. I often use it together with modulation, usually an envelope, to make the event’s pitch raise when played and drop when stopped, which is very handy to create power on and power off type sounds programmatically.

Doppler & Doppler Scale

Fmod has a built-in doppler effect. As you probably know, this effect occurs when there is a difference between the emitter and listener speeds. If you turn this option on, Fmod automatically calculates how this relative speed would affect the event’s pitch. The scale property allows to exaggerate or reduce the effect, allowing for fine tuning for each individual event.

All this sounds great but if you are using Fmod with Unity, it is quite possible that this is not going to work out of the box. The problem is about how Unity gets this speed data. By default, the speed is automatically fed to Fmod through the object’s rigidbody so in principle you need one of these for doppler to work by default.

But the real problem is that you also need the object to move via the Unity physics engine for the speed to be passed correctly. That’s a big hurdle since most often, game objects are not moved solely by physics, it is common to change their location directly using their transform, via animation or code.

So you will usually find that your fmod event attached to a game object, even with a rigidbody, won’t have any doppler effect at all. The same applies, by the way, to the built-in speed parameters. To fix this, what we essentially need to do is use the event instance to transmit the velocity manually by code. This can be achieved with EventInstance::set3DAttributes. The supplied velocity needs to be measured in metres per second, although this can be changed as a general Fmod engine setting.

So I haven’t been able to use the Fmod built-in doppler system yet but it is something I want to add to my Fmod implementation soon. See my article about how to get doppler working in Unity.

Some thoughts about Instances and Voices

Before continuing, I wanted to highlight the difference between these two concepts. To play any event in Fmod, we need to instantiate its description. Each of these instances is like an incarnation of the description. This is a bit similar to how classes work in programming: you instantiate a non static class so you can use it.

So each of these instances is independent of each other for the most part. When are these instances created? If you are using the StudioEventEmitter class in Unity, a look at the code reveals that it creates a new instance every time we play a given event from the emitter. But there is an important consideration: this is only the case if the event itself is a One Shot. Fmod defines a One Shot as an event that would stop by itself, which usually means that there is no loop or sustain point.

In my opinion this behaviour is a bit limiting. Sometimes, I want to send parameters to events that happen to be One Shots, for example. And there is another fundamental problem. You generally want to be economical with the amount of instances you use since each of them consumes resources. Creating new instances everytime you play a One Shot seems like a good default behaviour, think about a shotgun firing: you don't want to restart the instance each time you shoot since you would miss its tail. But at the same time, this means that any emitter which is prone to play very frequently, is going to create a huge amount of instances which will remain alive until they finish playing.

So my recommendation, and what I have actually done myself is to code your own emitter classes which create a pool of instances to use in sequence. Sometimes, I do want to just restart the same instance again and again if the sound is short, simple and not very important like a broken cable producing sparks.

In conclusion: instances are created so we can play Fmod events and ideally you should create your own emitter classes if you want to have more flexibility in terms of how to control them.

Voices are simpler. Each instance uses one voice per instrument. So if you just have a single instrument, that event is only going to use one voice. Is important to remember that even if you are playing only a few event instances, you may be using too many voices if your events contain many different instruments.

Max instances

This value limits the amount of instances in total that can play at the same time. At first, I thought that this value meant something like ”Event Polyphony” but this is only kind of true if you use the vanilla event emitter AND your event is a one shot, so it can be a bit deceiving if you don't know what's going on under the hood.

In my case, since I have my own emitter classes, I don't really use this value much, since my own code controls the amount of instances created in a more flexible way.

Stealing

Let's say you set your max instances to be 3. What happens after you play a fourth instance while the other three are still playing? This is where you define that behaviour. Let´s have a look at the options:

  • Oldest: Stop the instance that started the longest time ago. This is useful for very frequent events.

  • Furthest: Stop the instance that is the furthest from the listener.

  • Quietest: Stop the least audible instance.

  • Virtualize: Works like the quietest but the instance is not stopped but virtualized. This means that it produces no audio but its timeline is still running. This is most useful for environmental SFXs, with many emitters on the same scene.

  • None: No stealing, so the new instances just don´t play until an existing instance stops.

Cooldown

This option allows you to have a minimum time between instances. This is very useful to prevent spamming. In general, I think this setting is nice to have as a safety net but if you have to use it, there is probably something wrong with the way audio is played in code, so fixing that first should be the first approach.

Priority

This is not the instance priority but the voice priority, which means this value would affect each of the event´s instruments, instead of the event as a whole. This priority comes into play when we reach the game´s engine voice limit. Once this happens, Fmod will start to steal voices: higher priority voices will be able to steal lower priority voices. The “Highest” priority will never be stolen.

Min and Max Distance

Now these values live on the event level instead of on the spatializer which I think is a very good change. Between 0 and the min distance, the event will always play at its full level. From the min to the max, volume will drop to 0 following the spatializer curve.

Having these values on the event level allows us to use a built-in parameter, normalized distance, to be able to do distance based automation in a very flexible way. I use this to create bespoke attenuation curves that I can then save as presets.