Как остановить воспроизведение клипа WAV в JAVA

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

File introPath = new File("src/BattleshipGUI/423499__soundflakes__epic-heroic-orchestral- 
                                                                      dramatic.wav");
File buttonPressedPath = new File("src/BattleshipGUI/sfx_patcher_button_launch.wav");
static Clip introWAV;


    Menu() {


    super("BattleBoard");


    this.setContentPane(this.panelMain);
    this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    this.setLocationRelativeTo(null);
    this.pack();
    
    play(introPath); // playing when launching 


    // when the game starts, the sound should stop

    ButtonStartGame.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            super.mouseClicked(e);
            play(buttonPressedPath);

            try {
                if (random) {

                    currentCols = (Integer) spinnerColumns.getValue();
                    currentRows = (Integer) spinnerRows.getValue();
                    if (currentCols < 5 || currentRows < 5) {
                        
                        throw (new IllegalArgumentException());
                    } else {
                        BoardFrame b = new BoardFrame(currentRows, currentCols);
                        b.SetFrame(currentRows, currentCols);
                        b.AddRandomShips(currentRows, currentCols);
                        b.ScoreMethod(adjustedScoreMethod);
                        introWAV.stop();
                        introWAV.flush();
                        introWAV.close();
                        dispose();



public static void SetIntroWAV(Clip clip){

    introWAV=clip;
}

public static void play(File file) {
    try {
        Clip sound = AudioSystem.getClip();
        sound.open(AudioSystem.getAudioInputStream(file));
        SetIntroWAV(sound);
        sound.start();

    } catch (Exception e) {
        System.out.println(e);
    }
}

Я пробовал другие способы, такие как использование циклов while в классе Play, операторов if-else,... Кто-нибудь знает, как это исправить? Заранее спасибо!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
340
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Виновником является часть вашего play метода. Всякий раз, когда вы хотите воспроизвести какой-либо звук, вы также вызываете SetIntroWAV внутренне. Это приводит к установке вашей переменной introWAV.

Вот почему это проблема: При первом вызове play воспроизводится вступительный звук, а introWAV имеет правильное значение. Однако, как только вы запустите игру и воспроизведете другой звук (а именно, используя buttonPressedPath), ваша переменная introWAV будет установлена ​​на другое значение: звук, который был запущен последним. Затем, когда вы пытаетесь остановить воспроизведение своего звука, вы используете introWAV, который на самом деле больше не содержит отсылки к вашему вступительному звуку. Вместо этого это приведет к остановке вашего последнего воспроизведенного звука, поскольку это то, что сейчас удерживает introWAV.

Чтобы исправить это, просто задайте переменную introWAV только один раз, а не каждый раз, когда вызывается play. Есть несколько способов сделать это, включая следующие:

  1. Вы можете позволить своему методу play вернуть результирующий Clip, который будет воспроизведен впоследствии:

    public static Clip play(File file) {
        Clip sound = null;
        try {
            sound = AudioSystem.getClip();
            sound.open(AudioSystem.getAudioInputStream(file));
            sound.start();
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            return sound;
        }
    }
    

Затем вы можете использовать это возвращаемое значение для вызова SetIntroWAV один раз: SetIntroWAV(play(introPath)); Вы также можете использовать это возвращаемое значение для других целей, таких как сохранение локальных ссылок на ваши звуки. Однако вам не нужно использовать его каждый раз, и вы все равно можете игнорировать его, когда вам не нужна эта ссылка.

  1. Вы можете переписать свой метод play, чтобы он также содержал параметр, сообщающий методу, является ли звук, который вы пытаетесь воспроизвести, звуком вступления:

    public static void play(File file, boolean intro) {
        try {
            Clip sound = AudioSystem.getClip();
            sound.open(AudioSystem.getAudioInputStream(file));
            if (intro) {
                SetIntroWAV(sound);
            }
            sound.start();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
    

Это также приведет к тому, что SetIntroWAV будет вызываться только один раз.

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

ИМХО, лучшая практика с переменными Clip - загрузить и открыть, а затем удерживать их в памяти. Это можно сделать в классе, который управляет вашими звуковыми эффектами. В этом классе используйте Clip в качестве переменной экземпляра, предварительно загрузите и откройте его в конструкторе.

Этот класс также может иметь два метода, которые вызываются из вашей игры.

public void play() {
    clip.setFramePosition(0); // ensures Clip will start from the beginning
    clip.start();
}

public void stop() {
    clip.stop();
}

С такой структурой также стало проще управлять несколькими звуками. Например, у вас может быть два экземпляра этого класса управления звуком, и каждый из них может быть назначен на другой источник звука. Затем вы можете легко остановить один и начать другой.

Другие вопросы по теме