Same sound overlapping making it very loud. Tips/Tricks? - c#

I've got multiple object in a game I'm making, and I'm having major issues figuring out how to play sounds without playing the same sound twice or more. I'm wondering if you have any tricks/tips on how to make the sound play only once no matter how many instances of it is made and be balanced, rather than having it played 50 times being mega loud.
I'm using the XNA.Framework.Audio.SoundEffectInstance to play sounds.

This is more of a mixing issue than a programming issue. Playing a sample twice will always result in a fuller effect.
From a programmatic perspective, you can make sure the sound is never playing twice at the same time. To accomplish this, set a boolean value every time a sound is about to play. Before you play the sound, make sure the boolean value is false or cancel the event. Set the boolean value to false once the sound is played.

This is a pretty generic answer, but maybe you can create different sound classes (for example, shooting sounds, moving sounds, environment sounds).
When you play your sounds, you could play the current sound of each class while muting all the other sounds of that class.
For example, for every gunshot, it might be the case that the time in between each shot is shorter than the time it takes to play the sound. For each new gunshot, just mute all the other sounds in the pool of shooting sounds.
To do this, you might add a shooting sound object into a shooting sounds array, and for every game frame, check to make sure that there is no new sound. If there's a new sound, iterate through the array of sounds to mute everything before playing your new sound.
You can then make multiple arrays of sounds (walking/environment) so that your shooting sounds don't cut out walking sounds/environment sounds.

In the instance class you could make a static variable that is a boolean.
When an instance goes to make the sound, first have it check the static variable. If the variable is true, don't play the sound. If it is false, play the sound.
When the sound is done playing, turn the static variable to false so the next instance can play the sound.
example:
public static bool is_playing = false;

Related

Edit Unity InputAction interactions during runtime

I am facing some issues with working with the "new" Unity input system. I am working on an FPS prototype, where the player can pick up different guns with different windup times. I do not want to keep track of how long the player has held the shoot key, as the Hold interaction can do that by itself.
Looking around Unity documentation, MS Intellisense suggestions, and Stackoverflow, I have not seen a single instance of something around the lines of "Override interactions of InputAction". It is simply something not being talked about. Should I take that as a red flag for what I am doing is wrong? Probably.
I can see the interactions field for an InputAction, but it is marked with the readonly keyword. There is no internal setter for it either. Otherwise, the solution would be trivial, though unusual to the Unity™ way.
float duration = 0.04f;
controls.Main.Shoot.interactions = $"Hold(duration={duration})";
// Error: "Interactions" is readonly
Is there really not a way to edit the interactions for an InputAction during runtime with code?

PUN 2 Audiosource plays multiple times

I have animation events linked up to my characters that play a random footstep noise when they step. I'm trying to set it up for multiplayer, but I'm having some issues. With one person, the sounds only play once when they're supposed to. However, as tested with 2 people, it plays each footstep twice at the same time when one player steps. Each player has an audiosource component. Both footsteps sounds come from the audiosource of the player running, so it's not a case of both players playing the same sound. Any ideas as to why the sound is duped and played at the same time? The double sound comes from the same client, but only when that client is in multiplayer. And it's not when other people are walking, only the client. I must be setting up something wrong or putting something in the wrong place with my RPC.
1 player with 1 audiosource: sounds plays once
2 players with their own audiosource: sounds duplicates and plays at the same time
2 players with audiosource enabled for only the one walking: sounds still plays twice
From my player code
public void PlayFootstep()
{
int clipPick = Random.Range(0, footstepArray.Length);
GetComponent<AudioSource>().clip = footstepArray[clipPick];
photonView.RPC("PlayFootstepRPC", RpcTarget.All);
}
[PunRPC]
private void PlayFootstepRPC()
{
if (GetComponent<AudioSource>().isActiveAndEnabled && GetComponent<PlayerMovement>().ySpeed > 1.15)
{
GetComponent<AudioSource>().Play();
}
}
If PlayFootstep is called via an animation event, and you have animations synchronized via PhotonAnimatorView, then the PlayFootstepRPC() gets called several times, once per each connected client.
PhotonAnimatorView makes an object to play the same animations on every client. The PlayFootstep function gets called on every client, and every client sends RPC to itself and other clients, and that RPC plays the sound.
I suggest you should either not play footstep sounds via RPC, playing it locally instead (because animation event handles it for you), or add a check of PhotonView.IsMine before calling an RPC.

XNA SoundEffect Distortion

So I am currently making a game where you are running and defeating enemies. When you get to the boss and kill him he has a death sound, but what happens is that is plays the death sound all distorted. I don't know what is going on, sometimes are better than others but they are all distorted. MonsterA is my boss Monster and enemy health is his health. here is my code(This is in the Draw() Method):
if (enemyHealth == 0)
{
sprite.PlayAnimation(deathAnimation);
if (spriteSet != "MonsterA")
{
killedSound.Play();
}
if (spriteSet == "MonsterA")
{
bossKilledSound.Play();
}
isDead = true;
}
Put your code in the Update method. The Draw method is ment (pretty much) only for drawing. Also, it's not very clear to me, but the Draw function does't fire just every time after Update. I think it's kind of async, but watis for Update. It's a foggy topic for me, but try putting that code in Update instead of Draw. If that's not the case, try running the game on another PC that is much slower or much faster than the one you are debugging on. That should lead you to the next clue why is this happening.
EDIT:
... assuming that you are not starting the sound on every fire of Draw/Update, witch is not likely because from your explanation, other sounds play well, and only this one is the problem.

Diposal of SoundPlayer and Resource in C#

I am working on a kind of (at least closely related) Virtual Keyboard and want to include some clicking Sound. For testing I have just used
SoundPlayer player = new SoundPlayer(Resource2.click);
player .PlaySync();
Now I obviously do not want it to be Sync since it would freeze the keyboard.
Instead, if a new button gets clicked while the previous click-Sound is still playing, I would prefer the first one to stop and just start over with the new click. It is always the same sound for every button, approx. 1 sec long, but there might be a lot of events (typing speed)
So I planned to just go with
//Startup
SoundPlayer player = new SoundPlayer(Resource2.click);
player.Load();
and
//ButtonClickEvent
player.Stop()
player.Play()
//More stuff
Though while looking around I found this thread:
How to use System.Media.SoundPlayer to asynchronously play a sound file?
My way of doing it would be his Attempt #1, but he seems to have a problem:"SoundPlayer and the embedded resource stream are not immediately disposed".
Now I am not quite sure what is meant by this. Does this only concern memory issues if I have many different SoundPlayer objects? Or is this something else which might give me problems on the long term, which I did not see in my first tests. This is my main question. Additionally: Is there something else I overlooked that might give problems once in a while? E.g. stopping the player while it is not running multiple times?

FMOD gapless loop and sequence playback

I started using FMOD library, because I need to play sounds without gaps in C# application (both one sound in a loop and many sounds in a sequence). Can anyone show me the correct way to do it? I tried make something based on examples, but it's not working as I would like it to work.
Firstly, when I try to set if the sound is looped, while it's playing,
if (value)
sound1.setMode(FMOD.MODE.LOOP_NORMAL);
else
sound1.setMode(FMOD.MODE.LOOP_OFF);
nothing is going on. It only works fine, when I set th mode, before I start playback.
The second issue is: how can I be notified that the sound has reached the end? I tried to do it this way:
channel.setCallback(eofCallback);
where eofCallback is a reference to SoundEndCallback
private FMOD.RESULT SoundEndCallback(IntPtr channelraw, FMOD.CHANNEL_CALLBACKTYPE type, IntPtr commanddata1, IntPtr commanddata2)
{
FMOD.RESULT result;
if (type == FMOD.CHANNEL_CALLBACKTYPE.END)
{
//logic here
}
return FMOD.RESULT.OK;
}
But this callback is reached only when I manually invoke stop() on channel, not when the track ends.
Or eventually do you know any other library that would give me easily what I need? I chose FMOD, because it's quite popular, but I don't like its oldschool C++-like way of coding (no events, no exceptions, etc.).
And I have teh answer for my second question: to get notified you have to firstly set callback as mentioned before, and after that you've got to use System.update() method (it must be called periodically in a loop). This is a kind of polling,
To set the loop mode of a sound at runtime use Channel::setMode, Sound::setMode is like setting the defaults for any channels played from that sound (it won't affect currently playing sounds).
As for Channel::setCallback, make sure you are calling System::update regularly to have the callbacks fire for events like the sound playing to the end.

Categories