The reference is what makes the parameter reference the original object being passed instead of making a local copy.
bool Fmod_LoadSound(char *filename, FMOD::Sound &pSound)
{ ... }
FMOD::Sound sound_shoot;
Fmod_LoadSound("data/sound/_shoot.wav", sound_shoot);
The asterisk should rather be seen being a part of the type itself than acting as a reference. If you are having troubles wrapping your head around pointers, just wrap them in a typedef and treat them as any other value. Pointers are no different than, say, integers when it comes to being passed as arguments.
typedef FMOD::Sound *fmod_sound_ptr;
bool Fmod_LoadSound(char *filename, fmod_sound_ptr &pSound)
{ ... }
fmod_sound_ptr sound_shoot;
Fmod_LoadSound("data/sound/_shoot.wav", sound_shoot);
Here, you have a variable of some type, it is being passed by reference to the Fmod_LoadSound object, and you can then get a pointer to the original variable being passed by taking the address of the parameter; &pSound.
The fact that it is a pointer and not an object of some class type, or another primitive type, is not relevant. But the pointer is hidden behind a typedef to not confuse the pointer belonging to the original type and the pointer as a result of taking its address.
If you want to understand how pointers and references, and pass by pointer and pass by reference, work, then don't learn it with a type that is already a pointer. Just learn it with a regular integer, and progressively change the integer to a typedef:ed custom type, and to a pointer type, and then remove the typedef. This is essentially the core of your problem:
void foo(int v)
{
v = 42;
}
int main()
{
int v = 0;
foo(v);
std::cout << v;
}
Go from here, and gradually replace the integer with other types, and with typedefs, and with pointer types.
Not Telling