2014-04-10 2 views
0

스택 오버플로가 있습니다.자바 오디오 플레이어가 오디오를 끝냅니다.

저는 Java로 재생 목록 플레이어를 만들고 있습니다. 지금까지는 너무 좋았습니다. 모든 논리가 다운되었고 프로젝트가 완료 될 예정입니다. 우리는 큰 재생 목록을 만들어 처음부터 끝까지 재생하도록하여 재생을 테스트 해 왔습니다. 재생 사운드는 좋지만 때로는 오디오가 끝나는 경우가 있습니다. 이것은 거의 발생하지 않습니다. 마지막 x 초 (시간이 다름)는 재생되지 않습니다.

테스트 대상 파일은 모두 16 또는 24 비트 샘플링 크기의 모든 PCM 웨이브 파일입니다. 자바 사운드 엔진을 자바와 함께 사용하면 mp3 및 ogg spi를 확대하여 다른 유형의 오디오 파일을 지원할 수 있습니다.

지금까지이 로그를 몇 번 기록했으며 첫 번째 생각은 파일이 손상되었을 가능성이 있다는 것입니다. 나는 그 자체로 파일을 연주 해 보았고 완전히 연주했다!

나는 문제를 찾으려고했지만 그냥 찾을 수 없습니다. Idon't는 theres가 나의 오디오 플레이어 (생각에서 다 떨어지는 im)와 함께 무엇이라도 틀리게 생각한다라고 생각한다. 여기

내가 내 오디오 입력 스트림을 만드는 방법은 다음과 같습니다

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(); 
     } 
    } 
} 

당신은 내가 다음 줄을 배출, 그래서 내가 생각 해달라고 볼 수 있듯이 스트림에서 모든 것이 재생되기 전에 라인이 닫히는 문제가 있습니다.
누구든지이 코드에 어떤 문제가 있는지 확인할 수 있습니까?

+0

'drain '다음에'line.isActive()'를 체크하면 모든 출력이 완료되었는지 확인할 수 있습니다. –

+1

1) 더 빨리 도움을 받으려면 [MCVE] (http://stackoverflow.com/help/)를 게시하십시오. mcve) (최소 완료 및 검증 가능 예제). 2)이 작업을 위해 더 간단한 "Clip"을 사용해보십시오. –

+0

안녕하세요 앤드류, 할 수만 있다면 할 수 있겠지만 실제 버그를 정확히 찾아 낼 수는 없습니다. 그것을 재현하는 유일한 방법은 실제로 선수들이 하루 종일 뛰게하는 것입니다. – Terraego

답변

0

나는 명백한 답을 볼 수 없지만, 나를 위해 노란 깃발을 들고있는 몇 가지 것들이있다. 일반적으로 line.write() 메서드를 while 루프에 넣고 반복적으로 호출하지는 않습니다. 일반적으로 line.available()을 테스트하거나 행 잠금을 처리 할 필요가 없습니다. Line.write() 메서드는 사용 가능한 줄에 공백이 없으면 필요한 블로킹을 처리합니다. 나는 오디오 라인을 불필요하게 잠 그거나 막지 않도록 항상주의를 기울였다.

잠금 논리는 대기열 시퀀스 처리의 필수적인 부분입니까? 설명하는 오류가 해당 처리에있을 수 있습니다. (버퍼 크기와 비교하여 available() 테스트와 상호 작용이있을 수 있습니까? 컷오프 정도가 버퍼 크기와 대략 같습니다?)

큐 완성이 완료 될 때이를 알리기 위해 LineListener를 구현하는 것이 좋습니다. 그 이벤트를 다음 큐 재생의 트리거로 만드는 것입니다. 주어진 파일이 완료되면 STOP 유형의 LineEvent를 발행하여 대기열을 처리하여 다음 파일로 진행할 것을 알립니다.

+0

이 문제를 조사해 주셔서 감사합니다. 나는 분명히 뭔가 빠져 있다고 생각했습니다. Line.available()을 제거하고 il이 루프를 다소 재구성합니다. 어떻게 진행되는지보십시오! – Terraego

관련 문제