У меня проблема с одновременным воспроизведением нескольких аудиозаписей

#java #audio

#java #Аудио

Вопрос:

 package me.Warrior;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
public class SoundPlayer {
    static URL path=null;
    static AudioInputStream inputStream; 
    public static Clip clip;
    public static synchronized void Play(final String url,float Volume) { 
          new Thread(new Runnable() {
            public void run() {
              try {
                  clip = AudioSystem.getClip();
                  URL resource = getClass().getClassLoader().getResource(url);
                path=resource;
                inputStream = AudioSystem.getAudioInputStream(path);
                clip.open(inputStream);
                setVolume(Volume,clip);
                clip.start();
              } catch (Exception e) {
              }
            }
          }).start();
        }

    public static void setVolume(float Volume,Clip clip) {
         FloatControl gainControl = 
                    (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
         float dB=(float)(Math.log(Volume)/Math.log(10)*20);
                gainControl.setValue(dB);
    }
}
  

** Итак, я играю много аудиозаписей в своей игре, и я думаю, что есть проблема, тогда как, если я проигрываю две аудиозаписи в одну и ту же шестидесятую долю секунды, появляется ошибка и игра зависает на полсекунды

  1. Могу ли я как-то определить, когда начнется воспроизведение клипа, чтобы я мог остановить следующий клип (я хочу видеть, когда клип начнет воспроизводиться, а не когда он воспроизводится) (но это было бы интересно и для меня)

  2. Есть ли лучший способ воспроизведения звука, чем этот

Ответ №1:

Клипы НЕ были предназначены для одновременного открытия и запуска. Они даже не начнут воспроизводиться, пока весь файл не будет загружен с диска. Я предполагаю, что если вы попытаетесь воспроизвести два практически одновременно с кодом, который вы показываете, проблемы с задержкой загрузки файлов усугубятся.

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

 public void playMyAudioFX() {
    myAudioFX.setFramePosition(0);
    myAudioFX.start();
}
  

Установив положение кадра в начало, вы можете повторно использовать Clip его без необходимости загружать его снова и снова.

Но если вы не хотите использовать свою память для хранения аудио, тогда используйте SourceDataLine для воспроизведения. Данные только одного буфера загружаются с диска до SourceDataLine начала воспроизведения (в отличие от ожидания загрузки всего файла).

Ни один из этих типов файлов не работает хорошо при одновременном воспроизведении (воспроизведение дважды или более одновременно), но если вы сделаете все правильно, звуки должны начинаться нормально. Если все еще есть проблемы, или если вы недовольны тем, насколько неуклюжей является строка MASTER_GAIN, есть пара простых библиотек, которые можно попробовать. Один называется TinySound, другой AudioCue. Я неравнодушен к последнему (поскольку я его написал), и он обрабатывает одновременное воспроизведение и имеет гораздо более точный контроль громкости в реальном времени, чем Clip .

Это действительно распространенная проблема, и во многом причина в том, что учебные пособия по Java со звуком трудно читать, поэтому люди упускают эти важные детали. Я думаю, что многие другие авторы учебных пособий-добровольцев не очень хорошо подчеркивают лучшие практики, довольствуются тем, что просто воспроизводят звук и оставляют его на этом.

РЕДАКТИРОВАТЬ: перечитывая ваш вопрос — существует класс с именем a LineListener , который может получать уведомления о том, когда a Clip запускается или останавливается, если вы хотите продолжить этот аспект.

Кроме того, если вы получаете фактические сообщения об ошибках, пожалуйста, опубликуйте их! Это поможет определить причины и решения.

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

1. Спасибо, я этого не знал, я попробую

2. и да, я не против потратить немного памяти, в конце концов, это небольшая игра

3. это означает, что я должен предварительно открыть / загрузить все аудиозаписи и начать воспроизведение с самого начала, когда это необходимо (поскольку загрузка занимает много времени, поэтому моя игра зависает, если я правильно понял)

4. Трудно сказать наверняка, но из того, что вы описали, мне кажется, что это может быть проблемой. Вам нужно будет попробовать и посмотреть, поможет ли это. Клипы были разработаны для хранения в памяти открытыми, поэтому вы перейдете к лучшей практике. Я бы подумал о том, чтобы сделать FloatControl переменной поля уровня класса, а не локальной. Но повторная инициализация этого не так дорого, как повторная инициализация клипа. Кроме того, я добавил пару незначительных изменений, касающихся отслеживания звуковых событий и сообщений об ошибках.