Зацикливание звука Java - PullRequest
       12

Зацикливание звука Java

0 голосов
/ 24 января 2011

Я использую класс, который я сам собрал вместе на основе метода воспроизведения звука, а затем какой-то специальный код. Единственная проблема заключается в том, что я не уверен на 100%, как работает цикл while, который копирует в выходной поток в методе playSoundFile (). Я был бы чрезвычайно признателен за быстрое объяснение этого, а также за любые предложения о том, как настроить его на цикл (желательно без установки таймера для повторного вызова его по длине звукового файла)

Код "Мой":

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");///1457932/java-chistyi-sposob-avtomaticheski-generirovat-unsupportedoperationexception-pri-vyzove-hashcode-i-equals
    }

    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");///1457932/java-chistyi-sposob-avtomaticheski-generirovat-unsupportedoperationexception-pri-vyzove-hashcode-i-equals

    }

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

Ответы [ 3 ]

2 голосов
/ 25 января 2011

Для зацикливания простых (коротких) звуков я бы избегал всех более сложных классов javax.sound и использовал бы Clip. Пример кода с использованием Clip .

1 голос
/ 24 января 2011

Вы должны возобновить воспроизведение музыки после предыдущих концов.Как вы можете определить, когда музыка перестает воспроизводиться?

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

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

Самый простой способ - перезапустить его, вставив в этот блок smt, как playSoundFile(file).

Но этот код пахнет.Вы должны подумать о рефакторинге;)

Также, я думаю, вы можете попробовать поместить этот блок в бесконечный цикл

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

Но это тоже не лучшее решение.

0 голосов
/ 02 августа 2013

Проблема в размере буфера.

так что вам нужно дать "завершить" воспроизводящую нить перед "перезагрузкой", иначе у вас будет перекрывающийся звук с очень маленьким звуком (точно или меньше размера буфера, например 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
       }
    }
  }
}
...