How do I play the same sound more than once at any given time with numerous other sounds going on at the same moment? Right now I've got a "Clip" playing but it won't overlap with itself. ( I hear one bullet fire, the sound finishes then it plays again ). I'm writing a game with a fast bullet firing system but i can't get the sound to work nicely. It just doesn't sound "right" to hear only one bullet shot every half second when you spawn 20+ on the screen each second.
Any help? Pointers? :D
This seems to answer your question:
http://my.safaribooksonline.com/9781598634761/ch09lev1sec3
Quote:
"In other words, a single Clip object cannot mix with itself, only with other sounds. This process works quite well if you use short sound effects, but can sound odd if your sound clips are one second or more in length. [...] If you want to repeatedly mix a single clip, there are two significant options (and one other unlikely option):
1) Load the sound file into multiple Clip objects (such as an array), and then play each one in order. Whenever you need to play this specific sound, just iterate through the array and locate a clip that has finished playing, and then start playing it again."
So in principle Java does do mixing, just not inside a single clip.
Playing 20 bullit clips at once might be a little cpu intensive. It might be fine. I made a windchime once that played 7 chimes, overlapping (each was about 3 or 4 seconds long), and got away with setting it to play about 100 chimes per 5 second block. But the program wasn't doing anything else.
With Clips, to do this you would need to make multiple copies, and all that audio data would be sitting there, taking up RAM. If they are really short, it's not such a sacrifice. But for rapid fire, the solution most games use is to just cut off the sound and restart. You don't have to play the sound through to the end.
myClip.stop();
myClip.setFramePosition(0);
myClip.start();
with each bullit start. This is what is most often done. It uses a lot less CPU and less RAM than the overlapping Clip solution.
AudioClip might be what you're looking for - I use it in games playing short .wav sound effects, it's not perfect but it works fine most of the time.
Related
Clip clip = AudioSystem.getClip();
AudioInputStream a = AudioSystem.getAudioInputStream(new File(path));
clip.open(a);
This is the code that I'm using to play audio in my program. From Java profiling I can see that on average the clip.open() call takes less than 1ms. However, occasionally at random times it will block for a couple of seconds causing lag.
The screenshot below shows my Java profiler. As you can see, the exact same method is called 316 times with no issue. But one time it hangs for 2.4 seconds on Clip.open()
Notice how Clip.open doesn't even show in the bottom one because the time spent is less than 0.1ms.
The clips that I'm playing are all around 100KB in size, I don't understand why it works fine 316 calls but then one time it hangs.
I've also tried not closing the clips but leaving them all open, even then the problem still occurs.
Usually programmers .open() a Clip well in advance of when they want to play it. The moment of playback should only involve a .play() command and nothing else. If you both "open" and "play" the clip in consecutive commands, the play() can be delayed considerably because the file has to be loaded into memory in its entirety before the play() command will execute. For this reason, if you can't afford the memory for a Clip, then a SourceDataLine will execute more quickly as it only needs to load a buffer's worth into memory before the play() will execute.
Perhaps you already know about that aspect of Clips and that wasn't the issue. (You mention playing the Clips without having closed them.) Well another fact of Java is that there are no real-time guarantees. The system does do a good job of keeping a file or clip playing, but controlling the exact starting point is hard. This is because of several factors, one of which is the time spent juggling multiple threads and processes. For example, if a garbage collection command gets the call right before your sound call, the sound will have to wait until that segment is done and the processor gives the sound thread the priority.
There are other factors impacting real-time performance as well, which are well laid out in the following paper: Real Time Low Latency Processing in Java
Depending on what your goal is, there are ways to take advantage of the sound thread to improve timing accuracy, by "counting sound frames" and running events when a specific sound frame is up for processing, from the operation that is doing that processing. But in general, communications between the audio and other threads is going to be subject to some jitter.
In my game I have created many loops and methods inside render. The FPS range in my laptop ranges from 56 to 60, which is ok. However, when I run it in the Android OS on a Galaxy Note 4, the range of FPS ranges from 24 to 45, which is not ok.
Now I need a new render thread, to render synchronously with:
Gdx.app.getApplicationListener().render();
Can anyone help me solve this problem?
Even a low end laptop usually has much more processing power than a high end smartphone, thus what performs smoothly on your laptop can lag behind terribly on your Galaxy Note.
You've provided almost no information in the question, so the things I can suggest are general approaches;
Profile the game on your phone, and find possible bottlenecks, so you
can deal with them.
http://developer.android.com/tools/debugging/debugging-tracing.html
OpenGL profiling will also be very helpful, you can monitor context
switches and more with it.
https://github.com/libgdx/libgdx/wiki/Profiling
Also as a general rule of thumb, do not create new objects in the
render loop, or do it as little as possible if absolutely necessary.
Initializing a pool of reusable objects at start will help you a lot.
https://github.com/libgdx/libgdx/wiki/Memory-management
I'm making a game in Java. I want for there to be about 100 different samples and at any given time, 10 samples could be playing. However, for each of these 10 samples, I want to be able to manipulate their volume and pan.
As of right now, I request a line as follows: new DataLine.Info(Clip.class, format);
I do not specify the controls that I need for this line, but it appears that Clips always have MASTER_GAIN and BALANCE controls.
Is this correct?
Could I just create an array of 100 clips and preload all of the samples? I don't quite understand if Java's lines correspond with physical lines into a physical mixer or if they are virtualized.
If I am limited, then how can I swap samples in and out of lines? Is there a way to do this so that all of my say 100 samples are preloaded? Or, does preloading only help when you already have a line designated?
Again, if I am limited, is this the wrong approach? Should I either:
a. use a different programming language, and/or
b. combine audio streams manually and put them all through the same line.
Wow, that's a lot of questions. I didn't find answers in the documentation and I really hope that you guys can help. Please number your answers 1 to 4. Thank you very much!
1) I do NOT think it is safe to assume there will always be a BALANCE or even a MASTER_GAIN. Maybe there is. My experience with Java Controls for audio was vexing and short. I quickly decided to write my own mixer, and have done so. I'm willing to share this code. It includes basic provisions for handling volume and panning.
Even when they work, the Java Controls have a granularity that is limited by the buffer size being used, and this severely limits how fast you can fade in or out without creating clicks, if you trying to do fades. Setting and holding a single volume is no problem, though.
Another java library (bare bones but vetted by several game programmers at java-gaming.org) is "TinySound" which is available via github. I've looked it over but not used it myself. It also mixes all sounds down to a single output SourceDataLine. I can't recall how volume or panning is handled. He included provisions for ogg/vorbis files.
2) I'm not sure how you are envisioning using Clips work when you mention "Samples". Yes, you can preload an array of 100 Clips. And you would directly play one or another of these Clips on it's own thread (assuming using raw Java instead of an audio-mixing library), then reset them back to frame 0, then play them again. But you can only have one thread playing a given Clip at a time: they do not accommodate concurrent playback. (You can "retrigger" though by stopping a given playback and moving the position back to frame #0 then replaying.)
How long are the Clips? 100 of them could be a LOT of memory. If each is a second long, 100 seconds * 44100 frames per second * 4 bytes per frame = 17,640,000 bytes (almost 18MB just dedicated to RAM for sound!).
I guess, if you know you'll only need a few at a time and you can predict which ones will be needed, you can pre-load those and reuse them. But don't fall into the trap of thinking that Clips are meant to be loaded at the time of playback. If you are doing that, you should use SourceDataLines instead. They start playing back quicker since they don't have to wait until the entire external file has been put into memory (as Clips do). I'd recommend only using a Clip if you plan to reset it to the 0th frame and replay it (or loop it)!
3) Once it is loaded as a Clip, it is basically ready to go, there really isn't an additional stage. There really isn't any intermediate stage between an external file and a Clip in memory that I can think of that might be helpful.
Ah, another thought: You might want to create a thread pool ( = max number of concurrent sounds) and manage that. I don't know at what point the scaling justifies the extra management.
4) It IS possible to run concurrent SourceDataLines in many contexts, which relieves the need for holding the entire file in RAM. In that case, the only thing you can preload are the Strings for the File locations, I think. I may be wrong and you can preload the Files as well, but maybe not. Definitely can't reuse an AudioInputLine! On the plus side, an SDL kicks off pretty quick compared to an UNLOADED Clip.
HOWEVER! There are systems (e.g., some Linux OS) that limit you to a single output, which might be either a Clip or a SourceDataLine. That was the clincher for me when I decided to build my own mixer.
I think if only 8 or 10 tones are playing at one time, you will probably be okay as long as the graphics are not too ambitious (not counting the above mentioned Linux OS situation). You'll have to test it.
I don't know what alternative languages you are considering. Some flavor of C is the only alternative I know of. Most everything else that I know of, except Java, is not low-level or fast enough to handle that much audio processing. But I am only modestly experienced, and do not have a sound engineering background but am self-taught.
I've read here on StackOverflow that every time you play a clip in JavaSound, behind the scenes it creates a thread to play it. If it is true (and if it isn't please tell me, as I have not found any documentation/source on that), would it be considered as an expensive call, since creating threads is an expensive task in any OS/JVM? I am not sure yet, but I may need to play 10 to 20 clips concurrently, so I was wondering if that would be a problem.
PS: If it is an exoensive call for other reasons beside creating threads, please let me know.
Threads are NOT expensive, particularly. I've personally made a program that has over 500 running. Server programs can spawn considerably more than that.
Sound processing is not inexpensive, but I don't know that it is much more cpu-intensive than many graphics effects, like lighting in 3D. I made a program that both played a sound and made a "glow ball" that grew and faded while the sound was playing. The "glow ball" continually updated a RadialGradientPaint to achieve this effect. I ran into a ceiling of about 10 balls and sounds, and it was the graphical balls that were the bigger processing load.
Still, you might not be able to do a whole lot else with 17 Clips playing. You'll have to test it, and will hear dropouts if the cpu can't keep up.
Your 17 Clips may take up a huge amount of RAM. You know that they are all loaded into memory, yes? At 44100 samples for each second, and typically 4 bytes per sample (stereo, 16-bit PCM), that starts to add up quick.
So, there may be reasons to consider using SourceDataLine's instead, especially for the longer sounds.
Also, it seems some OS systems don't handle multiple sounds very well. I've had problems come up here with Linux in particular. I ended up writing a program to mix all the playing sounds into one output SourceDataLine as a way to handle this.
Another way I get some efficiency is that I load my own custom made Clip. I've giving this Clip multiple cursors (pointers) that can independently move through the audio data. This way, I can play a Clip multiple times (and at varying speeds) overlapping. To do this with a Java Clip, you have to load it into RAM multiple times. So, you might consider writing something like that. The output from the multiple cursors can be summed and played via a SourceDataLine.
I have been working on a childish little program: there are a bunch of little circles on the screen, of different colors and sizes. When a larger circle encounters a smaller circle it eats the smaller circle, and when a circle has eaten enough other circles it reproduces. It's kind of neat!
However, the way I have it implemented, the process of detecting nearby circles and checking them for edibility is done with a for loop that cycles through the entire living population of circles... which takes longer and longer as the population tends to spike into the 3000 before it starts to drop. The process doesn't slow my computer down, I can go off and play Dawn of War or whatever and there isn't any slow down: it's just the process of checking every circle to see if it has collided with every other circle...
So what occurred to me, is that I could try to separate the application window into four quadrants, and have the circles in the quadrants do their checks simultaneously, since they would have almost no chance of interfering with each other: or something to that effect!
My question, then, is: how does one make for loops that run side by side? In Java, say.
the problem you have here can actually be solved without threads.
What you need is a spatial data structure. a quad tree would be best, or if the field in which the spheres move is fixed (i assume it is) you could use a simple grid. Heres the idea.
Divide the display area into a square grid where each cell is at least as big as your biggest circle. for each cell keep a list (linked list is best) of all the circles whose center is in that cell. Then during the collision detection step go through each cell and check each circle in that cell against all the other circles in that cell and the surrounding cells.
technically you don't have to check all the cells around each one as some of them might have already been checked.
you can combine this technique with multithreading techniques to get even better performance.
Computers are usually single tasked, this means they can usually execute one instruction at a time per CPU or core.
However, as you have noticed, your operation system (and other programs) appear to run many tasks at the same time.
This is accomplished by splitting the work into processes, and each process can further implement concurrency by spawning threads. The operation system then switches between each process and thread very quickly to give the illusion of multitasking.
In your situation,your java program is a single process, and you would need to create 4 threads each running their own loop. It can get tricky, because threads need to synchronize their access to local variables, to prevent one thread editing a variable while another thread is trying to access it.
Because threading is a complex subject it would take far more explaining than I can do here.
However, you can read Suns excellent tutorial on Concurrency, which covers everything you need to know:
http://java.sun.com/docs/books/tutorial/essential/concurrency/
What you're looking for is not a way to have these run simultaneously (as people have noted, this depends on how many cores you have, and can only offer a 2x or maybe 4x speedup), but instead to somehow cut down on the number of collisions you have to detect.
You should look into using a quadtree. In brief, you recursively break down your 2D region into four quadrants (as needed), and then only need to detect collisions between objects in nearby components. In good cases, it can effectively reduce your collision detection time from N^2 to N * log N.
Instead of trying to do parallel-processing, you may want to look for collision detection optimization. Because in many situations, perforiming less calculations in one thread is better than distributing the calculations among multiple threads, plus it's easy to shoot yourself on the foot in this multi-threading business. Try googling "collision detection algorithm" and see where it gets you ;)
IF your computer has multiple processors or multiple cores, then you could easily run multiple threads and run smaller parts of the loops in each thread. Many PCs these days do have multiple cores -- so have it so that each thread gets 1/nth of the loop count and then create n threads.
If you really want to get into concurrent programming, you need to learn how to use threads.
Sun has a tutorial for programming Java threads here:
http://java.sun.com/docs/books/tutorial/essential/concurrency/
This sounds quite similar to an experiment of mine - check it out...
http://tinyurl.com/3fn8w8
I'm also interested in quadtrees (which is why I'm here)... hope you figured it all out.