• 15
• 15
• 11
• 9
• 10

# [SDL] 2D positional sound

This topic is 3211 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey. I'm curious about the best way to manage 2D positional sounds in SDL. I already have a class that caches loaded sounds so that only one is ever loaded from the same file name. Each time someone wants to play a sound, they pass the name of the sound to the audio player and it plays the sound at that file name in the cache.
1. Is it ok for every entity that can emit sound to share the same sound chunk and change the channel's volume that it is playing on (e.g. use the system I already have going)? I don't want to run out of channels but at the same time, every entity having a loaded sound chunk seems a bit excessive.
2. Adding on to the question above, would I have to loop through all the channels until I find one that isn't playing and set the volume of it before I play the sound?
3. Which effects function should I prefer for a 2D tile-based game: Mix_SetDistance or Mix_SetPosition?
4. If the answer to the above is Mix_SetPosition, how would I call it if I had the player's position and direction they are facing and the entity's position and direction they are facing, taking into account that some entities don't have a direction they are facing, and that my direction type is just an enum (NORTH, SOUTH, EAST, WEST). This is how I'm roughly imagining it to work out, sans the maths for normalising the distance into the 0-255 range and the angle of course, which I'm not sure of:
int get_free_channel()
{
int allocated_chans = Mix_AllocateChannels(-1);
for(int i = 0; i < allocated_chans; ++i)
{
if(Mix_Playing(i) != 1)
return i;
}
return -1;
}

void play_positional_sound(const Entity& player, const Entity& source, const std::string& fn)
{
Point player_pos = player.Get_Position();
Point source_pos = source.Get_Position();
Point distance = player.Get_Position() - source.Get_Position();
int average = distance.x + distance.y / 2;
int distance = 0;
// calculate distance by normalising into 0-255 range

int angle = 0;
// calculate direction of source in relation to player

int channel = get_free_channel();
Mix_SetPosition(channel, angle, distance)
Mix_PlayChannel(channel, cache.Sound_At(fn), 0);
}


Cheers.

##### Share on other sites
Couple of specific critiques and some advice on sound positions.

You are using 'distance' as a Point, then as an Int. Also you are missing parentheses in your 'average' calculation.

I used SDL_Audio for Ancient Galaxy, but eventually switched to irrKlang. With both, I had position audio issues that caused me to do my own volume & panning calculations, and forced all sound positions to be on a straight line 1 meter away from the listener, perpendicular to the listener facing direction. This way I can precisely control the amount of panning, etc.

I ended up creating a level of indirection from sound tag name like 'fire_001'
to sound file name 'media/sounds/foley/fire/fire1.ogg'. This way you don't have to change scripts etc. if you change the name of a audio file name.

##### Share on other sites
Quote:
 Original post by SimmerDCouple of specific critiques and some advice on sound positions.You are using 'distance' as a Point, then as an Int. Also you are missing parentheses in your 'average' calculation.
Oops... yeah, it was very quickly written, but thanks for clearing that up haha.

Quote:
 Original post by SimmerDI used SDL_Audio for Ancient Galaxy, but eventually switched to irrKlang. With both, I had position audio issues that caused me to do my own volume & panning calculations, and forced all sound positions to be on a straight line 1 meter away from the listener, perpendicular to the listener facing direction. This way I can precisely control the amount of panning, etc.
After reading that, I'm thinking that I won't really need Mix_SetPosition as I think that Mix_SetDistance should do the job fine. I'm not really after advanced positional sound, just something basic.

Quote:
 Original post by SimmerDI ended up creating a level of indirection from sound tag name like 'fire_001' to sound file name 'media/sounds/foley/fire/fire1.ogg'. This way you don't have to change scripts etc. if you change the name of a audio file name.
Not sure what you mean by this... :s

What about the maths? Anyone know how to get normalise a distance into 0-255?

Edit: Also, playing the same sound chunk on two different channels any less than 200 milliseconds apart sounds pretty crap... just like the sound is echoing. Is this normal?

Cheers.