After making that "No Sound" helicopter applet and running it, I immediately noticed that it is running at quite a bit faster framerate than the one with sound. That means SoundManager has some significant overhead, which prompted me to think of ways to streamline and optimize. I took a really close look at the class and how things work, and wrote down a full page of notes on some minor changes I could make to speed things up. There is one major change I am going to make as well:
As things are now, in cases where all the sources change position each frame (such as when the camera is moving), the source manager thread is getting woke up every frame to re-sort the list. Because the source-manager thread calls AL functions (to cull and reactivate sources), it is synchronized with the command thread which also calls AL functions. The user's game thread is synchronized with the command thread, because the user calls "tick()" every frame to queue commands for moving sources. THEREFORE the game thread has to potentially wait for the source-manager thread to re-sort the threads list every frame.
Now I can't think of any way around this three-thread synchronization. Even if I had absolutely all AL calls running in one thread, all three threads would still need to be synchronized with each other. For example, when the user says "Play my source", a command must be queued (synchronization between game thread and command thread), then that command has to run by the source-management thread to see if that source is able to play or if it should be culled(synchronization between command thread and source-management thread). This dependency occurrs regardless of which thread actually plays the source.
So basically, potentially each frame, the user has to wait to access the command queue, while the the command thread is in the middle of executing the queued "move source" commands, which requires the command queue to wait to access the source list, which the source-management thread is using during the re-sort cycle. I know, my head is aching, too (did I mention I hate threads?)
Anyway, I did think of a (really obvious) way to reduce the sort time, which should improve overall performance. Right now, there is a source map (sources stored by name) and a source list (used for sorting, culling, reactivating). Since the only purpose of the source list is to play the closest sources, there is no reason for it to contain inactive sources (except for culled looping-sources). All I need to do is to only put sources into the list when they are playing, then when they finish playing or are stopped, or when non-looping sources are culled, remove them from the list. That should greatly reduce the time it takes to re-sort the source list (Except in cases where all the sources were looping-sources - there would be no improvement then).
I did notice another potential problem. Right now, the user can dynamically change MANAGEMENT_MODEL in their program at any time. However, this variable is used in the source-management thread, so I need to make sure updating MANAGEMENT_MODEL is done in a synchronized method rather than letting the user acces the varriable directly. This is true for a couple of other varriables as well. Easy fix - I just need to make these varriables private and create synchronized "get" and "set" interface methods.