2011-01-24 106 views
0

我正在使用一个我基于声音播放方法拼凑自己的类,然后使用一些自定义代码。唯一的问题是,我不能100%确定在playSoundFile()方法中复制到输出流的while循环是如何工作的。我会非常感谢它的快速解释,以及有关如何设置它循环的任何建议(最好不设置定时器,以重复调用它在声音文件的长度)循环声音Java

'My '代码:

import java.io.File; 
import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.SourceDataLine; 

// Plays sounds passed to it. Loop stop etc to be supported later, maybe... 
public class SoundPlayer { 

    File filSound; 
    boolean isFileThere; 

    public void loop() { 
     throw new UnsupportedOperationException("Create something first... DUH");//http://stackoverflow.com/questions/2205565/java-clean-way-to-automatically-throw-unsupportedoperationexception-when-calling 
    } 

    public void play() { 
     if (isFileThere) { 
      playSoundFile(filSound); 
     } 
    } 

    public void play(File file) { 

     playSoundFile(file); 

    } 
    public static void playSoundFile(String sFile) { 
     playSoundFile(new File(sFile)); 
    } 

    public static void playSoundFile(final File file) {//http://java.ittoolbox.com/groups/technical-functional/java-l/sound-in-an-application-90681 
     new Thread(//http://stackoverflow.com/questions/4708254/how-to-play-audio-in-java-application 
       new Runnable() { 

      public void run() { 

       try { 
//get an AudioInputStream 
        AudioInputStream ais = AudioSystem.getAudioInputStream(file); 
//get the AudioFormat for the AudioInputStream 
        AudioFormat audioformat = ais.getFormat(); 

//ULAW format to PCM format conversion 
        if ((audioformat.getEncoding() == AudioFormat.Encoding.ULAW) 
          || (audioformat.getEncoding() == AudioFormat.Encoding.ALAW)) { 
         AudioFormat newformat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
           audioformat.getSampleRate(), 
           audioformat.getSampleSizeInBits() * 2, 
           audioformat.getChannels(), 
           audioformat.getFrameSize() * 2, 
           audioformat.getFrameRate(), true); 
         ais = AudioSystem.getAudioInputStream(newformat, ais); 
         audioformat = newformat; 
        } 

//checking for a supported output line 
        DataLine.Info datalineinfo = new DataLine.Info(SourceDataLine.class, audioformat); 
        if (!AudioSystem.isLineSupported(datalineinfo)) { 
         //System.out.println("Line matching " + datalineinfo + " is not supported."); 
        } else { 
         //System.out.println("Line matching " + datalineinfo + " is supported."); 
//opening the sound output line 
         SourceDataLine sourcedataline = (SourceDataLine) AudioSystem.getLine(datalineinfo); 
         sourcedataline.open(audioformat); 
         sourcedataline.start(); 
//Copy data from the input stream to the output data line 
         int framesizeinbytes = audioformat.getFrameSize(); 
         int bufferlengthinframes = sourcedataline.getBufferSize()/8; 
         int bufferlengthinbytes = bufferlengthinframes * framesizeinbytes; 
         byte[] sounddata = new byte[bufferlengthinbytes]; 
         int numberofbytesread = 0; 
         while ((numberofbytesread = ais.read(sounddata)) != -1) { 
          int numberofbytesremaining = numberofbytesread; 
          System.out.println(numberofbytesread); 
          sourcedataline.write(sounddata, 0, numberofbytesread); 
         } 
        } 

       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }).start(); 
    } 

    public void stop() { 
     throw new UnsupportedOperationException("Create something first... DUH");//http://stackoverflow.com/questions/2205565/java-clean-way-to-automatically-throw-unsupportedoperationexception-when-calling 

    } 

    public void setSoundFile(File file) { 
     isFileThere = true; 
     filSound = file; 
    } 
    public void setSoundFile(String sFile) { 
     isFileThere = true; 
     filSound = new File(sFile); 
    } 
} 

回答

1

您应该重新开始音乐播放之前的结束。如何定义音乐什么时候停止播放?

//... 
         System.out.println(numberofbytesread); 
         sourcedataline.write(sounddata, 0, numberofbytesread); 
        } 
       } 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } finally { //added 
       /*here it stops*/ 
      }    //added 

esyest的方式将重新启动它通过放入该块smt像playSoundFile(file)

但是这段代码有异味。你应该想想重构;)

另外,我觉得,你可以试试把这个块不定式环

while(true){ 
        SourceDataLine sourcedataline = (SourceDataLine) AudioSystem.getLine(datalineinfo); 
        sourcedataline.open(audioformat); 
     /... 
         sourcedataline.write(sounddata, 0, numberofbytesread); 
        } 
} 

但是,这是不是最好的解决办法了。

2

对于循环简单(短)声音,我会避免所有更复杂的javax.sound类并使用Clip。一些sample code using Clip

0

问题是缓冲区大小。

,所以你需要让“完成”,“正在重置为”前播放线程,否则,你将不得不overlaping声音非常小的声音(准确或小于缓冲区大小如0:01)

所以在你的演奏螺纹

class SomeLoopPlayer implements Runnable 
{ 
    private boolean loop=true; 

    public void play() 
    { 
    new Thread(this).start(); 
    } 

    public void run() 
    { 
    try 
    { 
     while(true) 
     { 
     try //eos catch 
     { 
      //init sourcedataline or aif if null 
      //read or drain the source buffer in cycle 
     } 
     catch(IOException e) 
     { /* stream ended or other exception -> ignore for now */ } 
     finally 
     { 
     if(loop) 
      play(); 
     return;// terminate current thread 
     } 
    } 
    } 
}