嘿,有堆棧溢出。Java音頻播放器最後削減音頻
我在Java中創建了一個播放列表播放器,到目前爲止這麼好,我得到了所有邏輯,項目即將完成。我們一直在通過創建一些大型播放列表來測試播放,並讓它從開始到結束。播放聽起來不錯,但有時音頻在最後切斷。這很少發生。最後x秒(時間變化)不播放。
im測試的文件都是16位或24位採樣大小的PCM波形文件。 Im將Java聲音引擎與Java結合使用可以縮放mp3和ogg spi以支持其他類型的音頻文件。
到目前爲止,我已經記錄了幾次,我的第一個想法是該文件可能已損壞,情況並非如此。我嘗試過自己播放這個文件,並且它完全播放了!
我試圖找到問題,但我只是無法找到它。我不認爲我的音頻播放器存在任何問題,即將失去想法。
這裏是我創造我的音頻輸入流:
public static AudioInputStream getUnmarkableAudioInputStream(Mixer mixer, File file)
throws UnsupportedAudioFileException
{
if (!file.exists() || !file.canRead()) {
return null;
}
AudioInputStream stream;
try {
stream = getAudioInputStream(file);
} catch (IOException e) {
logger.error("failed to retrieve stream from file", e);
return null;
}
AudioFormat baseFormat = stream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, baseFormat);
boolean supportedDirectly = false;
if (mixer == null) {
supportedDirectly = AudioSystem.isLineSupported(info);
} else {
supportedDirectly = mixer.isLineSupported(info);
}
// compare the AudioFormat with the desired one
if (baseFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED || !supportedDirectly) {
AudioFormat decodedFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(), 16, baseFormat.getChannels(),
baseFormat.getChannels() * 2, baseFormat.getSampleRate(),
false);
// convert the audio format to the supported one
if (AudioSystem.isConversionSupported(decodedFormat, baseFormat)) {
stream = AudioSystem.getAudioInputStream(decodedFormat, stream);
} else {
logger.debug(
"Audio format {} is not supported "
+ "and can not be converted to default format",
baseFormat.toString());
return null;
}
}
return stream;
}
這是我的音頻播放器螺紋:
final class PlayerThread extends Thread
{
private byte[] buffer;
/**
* Initialize the buffer
*/
public void initBuffer()
{
linelock.lock();
try {
buffer = new byte[line.getBufferSize()/5];
} finally {
linelock.unlock();
}
}
public void run()
{
initBuffer();
while (!isInterrupted()) {
checkState();
// if the line is just cleared go to the start of the loop
if (line == null || isInterrupted()) {
continue;
}
write();
}
// clean up all resources
close();
// change the state
state = Player.State.STOPPED;
}
private void checkState()
{
if (state != Player.State.PLAYING) {
if (line != null) {
line.flush();
}
try {
synchronized (this) {
this.wait();
}
} catch (InterruptedException e) {
// reset the interupt status
interrupt();
}
}
}
private void write()
{
// how much bytes could be written on the line
int available = line.available();
// is the space on the line big enough to write the buffer to
if (available >= buffer.length) {
// fill the buffer array
int read = 0;
try {
read = audioStream.read(buffer, 0, buffer.length);
} catch (Throwable ball) {
logger.error("Error in audio engine (read)", ball);
}
// if there was something to read, write it to the line
// otherwise stop the player
if (read >= 0) {
try {
linelock.lock();
line.write(buffer, 0, read);
} catch (Throwable ball) {
logger.error("Error in audio engine (write)", ball);
} finally {
linelock.unlock();
}
bytesRead += read;
} else {
line.drain();
MoreDefaultPlayer.this.stop();
}
}
}
private void close()
{
// invoke close on listeners
invokePlayerClosedOnListeners();
// destroy the volume chain
vc.removeVolumeListener(MoreDefaultPlayer.this);
// close the stream
try {
audioStream.close();
} catch (IOException e) {
logger.error("failed to close audio stream");
}
clearAllListeners();
linelock.lock();
try {
// quit the line
line.stop();
line.close();
line = null;
} finally {
linelock.unlock();
}
}
}
正如你可以看到我後瀝乾行了,所以我不認爲問題是線路在播放流的所有內容之前關閉。
任何人都可以看到什麼可能是錯誤的這段代碼?
您可以在'drain'之後檢查'line.isActive()'以查看是否所有輸出都已完成 –
1)爲了更好地幫助您,請發佈[MCVE] mcve)(最小完整和可驗證示例)。 2)你可以嘗試使用更簡單的'剪輯'這個任務。 –
嘿安德魯,我會盡我所能,但我似乎無法查明實際的錯誤。重現它的唯一方法是讓玩家實際跑完整整一天。 – Terraego