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