I’m getting annoying clicks and pops with my sound playback using SourceDataLines (not using Clips since i want to manipulate sound data dynamically).
My initialization code looks like this:
// use a short, 100ms (1/10th sec) buffer
int bufferSize = playbackFormat.getFrameSize() * (int)(playbackFormat.getFrameRate() / 10);
// create the buffer
byte[] buffer = new byte[bufferSize];
// create, open, and start the line
SourceDataLine line;
DataLine.Info lineInfo = new DataLine.Info(SourceDataLine.class, playbackFormat);
try
{
line = (SourceDataLine)AudioSystem.getLine(lineInfo);
line.open(playbackFormat, bufferSize);
}
catch (LineUnavailableException ex)
{
// the line is unavailable - signal to end this thread
Thread.currentThread().interrupt();
return;
}
line.start();
And my playback (in a seperate Thread) looks like this:
while (numBytesRead != -1)
{
....
// copy data
numBytesRead =
source.read(buffer, 0, buffer.length);
if (numBytesRead != -1)
{
//line.write(buffer, 0, numBytesRead);
int offset = 0;
while(offset < numBytesRead)
offset+=line.write(buffer, offset, numBytesRead - offset);
}
}
If I initialize line.open() with a LARGER buffer size, the problem is minimized. However, doing this results in latency problems and is especially apparent and ugly with continously looping sound effects. I’m guessing it’s a buffer overflow problem wherein the data in the buffer gets overwritten before it can be used for playback. But then again, line.write() is supposed to block or at least supposed to check for available space before writing so I’m not 100% sure of the cause.
I’m wondering if anyone has got a solution for this?
I’d appreciate any suggestions.Thanks
EDIT: I’m avoiding object creation overhead and sound latency by using a pre-defined number of Threads (in a ThreadPool) initialized with Thread-local SourceDataLine objects and byte array buffers to play my sounds. When I limit the amount of Threads (and therefore the amount of reused SourceDataLine objects) used to a smaller number, the sound problems occur sooner. Calling line.drain() and line.stop() doesn’t remedy the situation also. But if I just created new Threads and SourceDataLines each time to play the sound effects, the problems simply disappear… I wonder what’s up.