2012-04-03 2 views
3

에 클립 : MR.sounds 유형 AudioInputStream과 MR의 배열입니다노래가 처음 재생하지만, 한 번 중지 재생되지 않습니다 : 나는 다음과 같이 노래를 재생하기 위해 자바 클립을 사용하고 자바

 MR.clip= (Clip) AudioSystem.getLine(MR.info[docIdOfSelectedSong]); 
     MR.clip.open(MR.sounds[docIdOfSelectedSong]); 
     MR.clip.setMicrosecondPosition(5* 1000000); 
     MR.clip.start(); 

. info는 DataLine.info 유형의 배열입니다. 버튼을 누르면 위의 코드가 호출되어 노래가 재생됩니다. 또한, 나는 아래의 코드

public static void stopSong(){ 

    MR.clip.close(); 

} 

문제는 내가 처음 노래, 재생을 재생 버튼을 중지 할 때 잘 작동한다는 것이다에게 호출하는 곡을 정지하는 또 다른 버튼이 있습니다. 하지만 두 번째로 노래를 연주하려고하면 노래를들을 수 없습니다. 무엇이 잘못 될지에 대한 제안?

답변

6

다른 모든 InputStream와 마찬가지로 AudioInputStream은 .reset()이 될 수있는 경우에만 한 번 읽을 수 있습니다. 사운드 재생을 시도하기 전에 AudioInputStream에서 .reset()을 호출 해 볼 수는 있지만 AudioInputStream은 .reset()을 지원하지 않을 수 있습니다. InputStream는, 리 셋트를 서포트 할 필요는 없습니다. 또한 markSupported()을 참조하십시오.

.reset()이 작동하지 않는 경우, 재생을 시작해야 할 때마다 새 AudioInputStream을 구성하는 것이 좋습니다.


업데이트 : 메모리에 사운드 데이터를 캐싱하고 Clip을 사용하여 사운드를 재생하는 예를 만들었습니다. 이 예제는 AudioInputStream.reset()을 사용합니다. 그러면 어떻게 작동할까요? 실제로, AudioInputStream 이 인 경우에만 reset() 을 지원합니다. 그 기본 InputStream은 .reset()을 지원합니다. 그래서 내 예제에서는 ByteArrayInputStream에 의해 뒷받침되는 AudioInputStream을 생성합니다. ByteArrayInputStream는 리 셋트를 지원하기 위해 (때문에), 캐쉬 된 AudioInputStream도 .reset()를 서포트하므로 재사용 할 수 있습니다. 당신이 동시에 하나 캐시 사운드를 연주 위하여려고하는 경우에, 당신은 아마 AudioInputStream의 캐시가 아니라 캐시 byte[]들과 별 재생 AudioInputStream을 구성해서는 안

참고. AudioInputStream은 상태 저장이므로 두 개의 동시 실행 클립에 단일 인스턴스를 전달하거나 한 클립이 재생되는 동안 스트림을 재설정하면 상태가 충돌하기 때문입니다.

public class CachedSoundClipTest 
{ 
    static ArrayList<AudioInputStream> cachedSounds = 
     new ArrayList<AudioInputStream>(); 

    public static void main(String[] args) throws Exception 
    { 
     File[] audioFiles = new File("/audio_storage_directory").listFiles(); 
     for (File file : audioFiles) 
     { 
      AudioInputStream reusableAudioInputStream = 
       createReusableAudioInputStream(file); 
      cachedSounds.add(reusableAudioInputStream); 
     } 

     while(true) 
     { 
      System.out.println("Press enter to play next clip"); 
      BufferedReader br = 
       new BufferedReader(new InputStreamReader(System.in)); 
      br.readLine(); 
      playCachedSound(0); 
     } 
    } 

    private static void playCachedSound(int i) 
     throws IOException, LineUnavailableException 
    { 
     AudioInputStream stream = cachedSounds.get(i); 
     stream.reset(); 
     Clip clip = AudioSystem.getClip(); 
     clip.open(stream); 
     clip.start(); 
    } 

    private static AudioInputStream createReusableAudioInputStream(File file) 
     throws IOException, UnsupportedAudioFileException 
    { 
     AudioInputStream ais = null; 
     try 
     { 
      ais = AudioSystem.getAudioInputStream(file); 
      byte[] buffer = new byte[1024 * 32]; 
      int read = 0; 
      ByteArrayOutputStream baos = 
       new ByteArrayOutputStream(buffer.length); 
      while ((read = ais.read(buffer, 0, buffer.length)) != -1) 
      { 
       baos.write(buffer, 0, read); 
      } 
      AudioInputStream reusableAis = 
       new AudioInputStream(
         new ByteArrayInputStream(baos.toByteArray()), 
         ais.getFormat(), 
         AudioSystem.NOT_SPECIFIED); 
      return reusableAis; 
     } 
     finally 
     { 
      if (ais != null) 
      { 
       ais.close(); 
      } 
     } 
    } 
} 
+0

예, 재설정이 지원되지 않습니다. 새로운 AudioInputStream를 구축하는 것을 고려하면 무엇을 의미합니까? CLIP을 사용하여 예제를 줄 수 있습니까? – Programmer

+0

AudioInputStreams를 처음 만들려면 어떻게해야합니까? AudioInputStream [] 배열을 초기화하기 위해 한 일을 다시하십시오. 그러나 클립을 재생하기 바로 전에하십시오. –

+0

오! 프로그램 시작 부분에서 AudioInputStream을 읽고 다시 사용할 수 있다고 생각했습니다. – Programmer

3

코드 예제에서 Clip을 사용하는 경우 close() 메서드 대신 stop() 메서드를 사용해야합니다. 그런 다음 다시 시작하면 중단 된 부분부터 다시 시작됩니다. 처음부터 다시 시작하려면 setMicrosecondPosition() 또는 setFramePosition()을 0으로 사용하고 start()를 사용할 수 있습니다.

자세한 내용은 아래 튜토리얼의 "클립 사용"을 참조하십시오!

http://docs.oracle.com/javase/tutorial/sound/playing.html

은 SourceDataLine는 한 번만 사용할 수 있으며 재설정 할 수 없습니다. 예?

1

OS X에서 클립이 재생되는 동안 멈추려 고 시도한 경우 클립이 재생되지 않는 것과 비슷한 문제가 있었는데 처음부터 다시 시작했습니다. 그것은 바로 stop()flush()를 호출하여 수정되었습니다 :

if(clip.isActive() || clip.isRunning()) { 
    clip.stop(); 
    clip.flush(); 
} 

은 확실히 당신이 다시 클립을 재생 할 수 있도록하려면 stop()를 사용 close() 사용하지 마십시오.

5

트릭은 클립의 현재 위치를 처음으로 재설정하는 것입니다.

clip.stop(); 
clip.setMicrosecondPosition(0); 
clip.start(); 

이 방법을 사용하면 동일한 리소스를 여러 번로드 할 필요가 없습니다. 클립은 한 번만로드하고 인스턴스 변수 또는 다른 것으로 저장해야합니다.

관련 문제