What is the best way of playing audio (multiple, realtime) in a java game only using the native libraries? Mp3 is not supported so compressed files are out the window and mostly .wav used, this leads to huge jars and files I don’t want to load into memory so Clip is also not an option.
I am currently using a dataline to read into a buffer and play the audio but reading from a buffer requires a loop, this loop means I can only play one audiofile in the same thread as else the audios won’t be “realtime”. By this I mean that if I force the loop to go through multiple buffers, in the case that 100 sounds must be played, the 100th sound won’t play untill all the others have played, this will be very noticeable in such a case.
The solutions?
- JavaFX- http://stackoverflow.com/questions/6045384/playing-mp3-and-wav-in-java
but this requires the JavaFX library and I want to use as much native code as possible (for learning) and I THINK javaFX spawns a new thread on media.play - Use clip, this means that if I use .wav I might have to load hundreds of megs into memory, BAD choice, this also assumes that Clip.play() spawns a new thread
- Use an executorservice, set a max limit of concurrent audioplaying (like 20) and every time a play is requested, send the bufferedaudiostream into a new thread to the executor and play
I may have to go with the third option but I am afraid of threadoverheads and the cost of recreating the same dataline over and over again but if I limit the number of datalines I can’t for instance implement the effect of ambient sound where you can hear multiple crickets. Here is the source for reading from a buffer, might be of some interest to some.
public void playSound() {
SourceDataLine line;
int audioBufferByteSize = 1024;
long streamLengthBytes;
try {
// URL url = getClass().getResource("forest.wav");
// AudioInputStream inputStream =
// AudioSystem.getAudioInputStream(url);
InputStream iStream = getClass().getResourceAsStream("forest.wav");
InputStream buffered = new BufferedInputStream(iStream, 1);
AudioInputStream aStream = AudioSystem
.getAudioInputStream(buffered);
AudioFormat audioFormat = aStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class,
audioFormat, audioBufferByteSize);
line = (SourceDataLine) AudioSystem.getLine(info);
line.open(audioFormat);
streamLengthBytes = audioFormat.getFrameSize()
* aStream.getFrameLength();
aStream.mark((int) streamLengthBytes);
while (true) {
aStream.reset();
line.start();
int nBytesRead = 0;
byte[] sampledData = new byte[audioBufferByteSize];
while (nBytesRead != -1) {
nBytesRead = aStream.read(sampledData, 0,
sampledData.length);
if (nBytesRead >= 0) {
line.write(sampledData, 0, nBytesRead);
}
}
Thread.sleep(10);
}