循环声Java

时间:2011-01-24 20:13:11

标签: java loops audio javasound

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

'我的'代码:

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

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

您应该在上一次结束后重新开始播放音乐。如何定义音乐何时停止播放?

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

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

最简单的方法是通过放入像playSoundFile(file)这样的块smt来重启它。

但这段代码闻起来。你应该考虑重构;)

另外,我认为,您可以尝试将此块放在不定式循环中

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

但是,这也不是最佳解决方案。

答案 2 :(得分:0)

问题是缓冲区大小。

所以你需要在“重新设置”之前“完成”播放线程,否则你会将声音与真正小的音频重叠(完全或小于缓冲区大小,例如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
       }
    }
  }
}