Воспроизведение песни .wav на Java?

#java #audio #playback

#java #Аудио #воспроизведение

Вопрос:

Я пытаюсь воспроизвести песню в .формат wav в моей Java-игре, и вот часть кода SoundPlayer класса:

 private static HashMap<String, Clip> clips;
private static int gap;

public static void init() {
    clips = new HashMap<String, Clip>();
    gap = 0;
}

public static void load(String s, String n) {
    if(clips.get(n) != null) return;
    Clip clip;
    try {
        InputStream in = SoundPlayer.class.getResourceAsStream(s);
        InputStream bin = new BufferedInputStream(in);
        AudioInputStream ais = AudioSystem.getAudioInputStream(bin);
        AudioFormat baseFormat = ais.getFormat();
        AudioFormat decodeFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);
        AudioInputStream dais = AudioSystem.getAudioInputStream(decodeFormat, ais);
        clip = AudioSystem.getClip();
        clip.open(dais);
        clips.put(n, clip);
    } catch(Exception e) {
        e.printStackTrace();
    }
}
  

Когда я вызываю метод load (), он вылетает в строке clip.open(dais) , и я получаю эту ошибку:
javax.sound.sampled.LineUnavailableException: Failed to allocate clip data: Requested buffer too large.

Это работает с короткими звуковыми эффектами, поэтому я предполагаю, что это связано с тем, что файл длится более минуты. Есть ли какие-либо лучшие способы сделать это?

Спасибо!

Комментарии:

1. «итак, я предполагаю, что это потому, что файл длится более минуты» Я бы так не подумал, использовал что-то похожее для воспроизведения звука более 5 минут

2. Почему вы декодируете аудиоформат вручную?

3. @MadProgrammer Как бы мне сделать это лучше?

Ответ №1:

В прошлом у меня были некоторые проблемы с тем, чтобы заставить звук работать на Java. Вот хороший способ загрузки.звуковые клипы wav.

 private Clip clip;

public Sound(String fileName)
{
    try
    {
        File file = new File(fileName);
        if (file.exists())
        {
            AudioInputStream sound = AudioSystem.getAudioInputStream(file);
            clip = AudioSystem.getClip();
            clip.open(sound);
        }
        else
        {
            throw new RuntimeException("Sound: file not found: "   fileName);
        }
    }
    catch (UnsupportedAudioFileException e)
    {
        e.printStackTrace();
        throw new RuntimeException("Sound: Unsupported Audio File: "   e);
    }
    catch (IOException e)
    {
        e.printStackTrace();
        throw new RuntimeException("Sound: Input/Output Error: "   e);
    }
}

public void play()
{
    clip.setFramePosition(0);
    clip.start();
}
public void loop()
{
    clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void stop()
{
    clip.stop();
}
  

Я считаю, что это отлично работает! Вы также можете добавить дополнительные исключения, если хотите, например, исключение LineUnavailableException и исключение MalformedURLException. Чтобы создать звуковой клип, вы создаете что-то как таковое:

 private Sound sound = new Sound("/sounds/sound.wav");
  

затем делаем

 sound.play();
  

Комментарии:

1. Спасибо! Я попробую это

2.К вашему сведению: вы можете использовать DataLine.Info info = new DataLine.Info(Clip.class, format); Clip clip = (Clip) AudioSystem.getLine(info); в качестве меры предосторожности против неподдерживаемых аудиоформатов. AudioSystem.getAudioInputStream также принимает URL в качестве источника, что позволяет загружать встроенные ресурсы

3. У меня есть NullPointerException для clip ?

4. @sparklyllama Можете ли вы опубликовать свой класс звука на сайте, а затем связать меня с тем, где он находится?

5. @Boodog dropbox.com/s/4ku4ouurlwpljrr/sound.rtf Не уверен, что я импортирую правильные вещи…

Ответ №2:

Я не знаю, почему вы пытаетесь декодировать AudioFormat вручную.

Обычно я использую что-то вроде…

 try (InputStream is = new BufferedInputStream(new FileInputStream(SoundPlayer.class.getResourceAsStream(s)))) {
    AudioInputStream audioStream = AudioSystem.getAudioInputStream(is);

    AudioFormat format = audioStream.getFormat();
    DataLine.Info info = new DataLine.Info(Clip.class, format);
    Clip clip = (Clip) AudioSystem.getLine(info);
    clip.open(audioStream);
    clip.start();
    try {
        Thread.sleep(250);
    } catch (InterruptedException ex) {

    }
    clip.drain();
} catch (IOException | LineUnavailableException | UnsupportedAudioFileException ex) {
    ex.printStackTrace();
}
  

Обратите внимание, это будет блокироваться до тех Clip пор, пока не будет исчерпан, воспроизведение до конца. Я протестировал музыкальный файл продолжительностью 5 минут и 48 секунд. Я использовал приведенный выше код так же успешно, как и вы, но, честно говоря, код, который я использую, просто проще (менее сложный — простой == хороший :))

Сказав все это, try (InputStream is = new BufferedInputStream(new FileInputStream(SoundPlayer.class.getResourceAsStream(s)))) { на самом деле это не требуется, так как AudioSystem.getAudioInputStream(...); может принимать URL и File ссылки, например…

 try {
    AudioInputStream audioStream = AudioSystem.getAudioInputStream(
        SoundPlayer.class.getResourceAsStream(s))));