I have a 3D game. The sound engine supports:
- playing ambient music to the player (two channels always the same)
- playing static sounds from a single position in space
- playing mobile sounds from a moving entity
There are some machines in game. Each one makes some noise. When there are one or two of them they should behave like point audio sources. But when the amount of machines increases, I want to play some "mechanical humm" ambient sound "in the area".
And so I am struggling terribly in coming up with any reliable way to implement it.
I'm particularly interested in the following cases:
There is a big area audio source and player stands outside of it - like a player standing on a beach and ocean making a general noise. When player walks along the beach line, the ocean still sounds the same if he doesn't move the head, but when he, for example, stands sideways (one ear towards ocean and one towards beach) he hears ocean on his one side. When he enters ocean he hears ocean ambience everywhere. The key thing is that I don't want him to pinpoint an exact location like "oh, here in this point is the audio source".
For this case I don't have any good idea. The only one was to create a mobile audio source in the point closest to player inside the zone (that would be ocean). When player gets sufficiently close to the ocean, the mobile audio source would convert to an ambient one (both channels the same intensity, and louder the more you go into the ocean)
Player is inside a cluster of sound sources. He can hear a general humm, but when he get's closer to one specific machine he can also hear this one machine. In this case there is also a question of how to (efficiently) determine a cluster from points.
I don't know how to implement that. I was thinking of adapting the ocean idea - when you are farther than some critical radius from a single machine you don't hear it -- you hear only ambience. When you are near a machine you hear ambience+machine. How to determine the cluster though? I was thinking of an average position among all machines as a center of a sphere and farthest point as the radius of the sphere, but single machines that are far can move the average center very far outside of the actual center of a cluster. I was looking at medoids, but they are representants of a set, and I also don't know how to determine which machines should be included in a set and which should not. Maybe some clustering algorithm should be used here (k-means?)? But if so, how do I efficiently determine clusters and later if player is inside one and a point in the cluster closest to the player? Maybe using center of cluster with higher attenuation distance would work?
Player moves out of/into the cluster OR a cluster moves. In this case when player is inside the cluster it should behave like in case 2, but when he exits it should work like in case 1. What should I do when I approach the boundary of a cluster?
I assume that playing a cacophony of single audio sources is a very, very bad idea. I was trying too look for help online but it either boils down to basic question like "how to add multiple audio sources in unity" or references to 500 paged books about audio programming and design (Which I don't get, because I'm not specializing in audio). It's probably also worth noting, that the sounds I play are rather synchronized - either all machines start playing at the same time or the are playing separately.
I work with custom game engine and I'd rather not use external dependencies. The sound engine uses OpenAL under the hood. I could take a look at reference though to implement it myself. I would be happy if the only thing I would have to use were existing functions - to play audio as ambience, to play mobile or point audio source. Fiddling with mixing L+R channels by hand would be problematic for me, but I'm willing to tinker if there are no easy ways out.
Do you guys know or have existing code for making this kind of cluster souds?
@EDIT I didn't mention it earlier, but cases 2 and 3 differ from case 1, because in case 1 the area sound source is mainly static - I could just select a large box as an area emitter for ocean or select a big ship as a big mobile area. Cases 2 and 3 are more dynamic. Machines can move at any given time as a group or as separate entities. They are static most of the time, but sometimes a bunch of them will move away or some new ones would come. If this was a static setup, then that would be a lot easier. That will force me to update clusters dynamically somehow, which I have no good idea how to implement.
Expected # of machines that make up a cluster is ~10 machines for small cluster, ~100 for medium and ~2k for big cluster.
Another Idea I came up with for case 2 and 3 would be periodically sampling all machines in some given radius around player and updating clusters only when player is in the vicinity.