Как воспроизвести wav файл без задержек?

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

Примечание. Я также непрерывно рисую фон:

public class DrawThread extends Thread {

    JFrame j;

    public DrawThread(JFrame frame) {
        j = frame;
    }

    public void run() {
        while (!(isInterrupted())) {
            if (j.isDisplayable() && j.isActive() && j.isEnabled())
            j.update(j.getGraphics());
        }
    }

}

и обновление просто вызывает краску, которая:

public void paint(Graphics g) {
            Graphics2D bg = (Graphics2D) g;
    bg.setBackground(Color.black);
    int w = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
    int h = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
    if (time < 500) {
        x[time] = r.nextInt(w) + 150;
        y[time] = h;
        z[time] = r.nextInt(w) + 150;
        time++;
    }
    for (int i = 0; i < time; i++) {
        y[i] -= forward;
        x[i] -= right;
        if (y[i] < 1) {
            x[i] = r.nextInt(400) - 200;
            y[i] = 300;
            z[i] = r.nextInt(400) - 200;
        } else if (y[i] > 300) {
            x[i] = r.nextInt(400) - 200;
            y[i] = 1;
            z[i] = r.nextInt(400) - 200;
        }
        if (x[i] > 200)
            x[i] = -200;
        else if (x[i] < -200)
            x[i] = 200;
        bg.setColor(color);
        bg.drawLine(
                getWidth() / 2 + (int) Math.round(x[i] * 200 / y[i]),
                getHeight() / 2 + (int) Math.round(z[i] * 200 / y[i]),
                getWidth()
                        / 2
                        + (int) Math.round((x[i] + right) * 200
                                / Math.abs(y[i] + forward)),
                getHeight()
                        / 2
                        + (int) Math.round((z[i]) * 200
                                / Math.abs(y[i] + forward)));
    }
}

EDit: добавление класса музыкального проигрывателя, который я использую (я переключился на BigClip):

import java.io.File;
import java.util.Collection;
import java.util.HashMap;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

import org.crystalix.util.SoundListener;

public class MSHandler {
public static boolean pause = false;
public static boolean stop = false;
private static HashMap<String, BigClip> clips = new HashMap<String, BigClip>();

public static void stopAll() {
    Collection<BigClip> c = clips.values();
    for (BigClip b : c) {
        System.out.println("Stopping "+b.toString());
        b.stop();
        System.out.println("Stopped "+b.toString());
    }
}

public static void playMusic(File file) {
    try {
        AudioInputStream audioIn = AudioSystem.getAudioInputStream(file);
        BigClip clip = new BigClip();
        clip.open(audioIn);
        clip.addLineListener(new SoundListener());
        clip.loop(1);
        clip.start();
        clips.put(file.getName(), clip);
    } catch (Exception e) {
        System.err.println("Sound could not be started!");
        e.printStackTrace(System.err);
    }
}
}

person Octavia Togami    schedule 24.11.2012    source источник
comment
1) j.update(j.getGraphics()); Не делай этого. Вероятно, это вызывает множество других проблем. 2) Чтобы быстрее получить помощь, опубликуйте SSCCE. 3) Используйте Clip для звука, как показано в вики тега Java Sound.   -  person Andrew Thompson    schedule 24.11.2012
comment
Как бы вы посоветовали мне стараться рисовать как можно чаще? Это единственный способ заставить его рисовать повторно, так как он не делает этого по умолчанию. Кроме того, файл является музыкой, а не звуком, поэтому клип не работает, потому что он слишком большой. Я на самом деле использовал Clip, и это не удалось.   -  person Octavia Togami    schedule 24.11.2012
comment
Как бы вы посоветовали мне рисовать как можно чаще? Используйте язык, который напрямую взаимодействует с видеокартой. ..это слишком большой. На самом деле я использовал Clip, и это не удалось В этом случае используйте BigClip.   -  person Andrew Thompson    schedule 25.11.2012
comment
Ок, попробую BigClip. Любые предложения по использованию API, помимо LWJGL, для взаимодействия с графической картой с Java? Мне нужно использовать Java, потому что у меня нет другого выбора.   -  person Octavia Togami    schedule 25.11.2012
comment
РЕДАКТИРОВАТЬ: Thread.join() по какой-то причине ждет бесконечно, какое-то исправление?   -  person Octavia Togami    schedule 25.11.2012


Ответы (1)


Вы не показали код, который вы используете для воспроизведения файла wav. Это немного затрудняет диагностику того, что может пойти не так!

1) wav должен быть просто в отдельном потоке. Если вы сделаете это правильно, он больше ничего не заблокирует. Учебники по звуку Java не особенно хорошо указывают на это. Итак: поместите код, который вызывает воспроизведение wav, в свой собственный исполняемый файл, и все будет в порядке.

2) Вы можете "открыть" wav до того времени, когда захотите его воспроизвести. Затем он должен «запуститься» сразу же, как только вы, наконец, скажете ему идти.

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

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

person Phil Freihofner    schedule 25.11.2012
comment
Я поставил код, который воспроизводит файлы wav, в вопросе. Проблема, с которой я сталкиваюсь, заключается в том, что звук обрывается и прыгает в некоторых точках, затем сглаживается, а затем снова начинает прыгать. - person Octavia Togami; 25.11.2012
comment
Включение и выключение обычно происходит из-за того, что аудиоданные не подаются на выходную линию достаточно быстро, чтобы не отставать от воспроизведения. Попробуйте использовать SourceDataLine для вашего wav-файла, а не BigClip, для которого требуется много оперативной памяти. Может быть, BigClip при неправильном использовании вызывает переключение страниц? Также поместите воспроизведение в отдельную ветку. Я пока не вижу, где вы это делаете. Я бы попробовал запустить звук сам по себе, чтобы убедиться, что он настроен правильно, затем начал добавлять графику и посмотреть, когда он сломается. Ваша графика может просто потреблять слишком много ресурсов процессора, чтобы обеспечить одновременный звук. - person Phil Freihofner; 27.11.2012
comment
Это BigClip Эндрю? Если это так, он использует SourceDataLine и запускает новый поток. - person Octavia Togami; 27.11.2012
comment
Хорошо, вы пытаетесь решить проблему, верно? При поиске и устранении неполадок стараются все упростить, а не усложнять. Самое простое воспроизведение wav-файла — это прочитать его через ais и вывести через sdl, и сделать это в своем собственном потоке, чтобы другие элементы могли продолжать работать. Вы знаете, как это сделать? Насколько я понимаю, BigClip загружает в память весь wav перед воспроизведением. Если это 30 секунд, вы потребляете 30 * 44100 * 2 * 2 байта = 53 МБ. Как долго ваш wav? Сколько у вас оперативной памяти? Когда начинается переключение страниц? Переключение страниц сделает звук прерывистым. - person Phil Freihofner; 27.11.2012
comment
Я не знаю, что такое подкачка страниц, но эта проблема также существует при использовании sdl и ais. Я начал это в новой теме - person Octavia Togami; 27.11.2012
comment
Кроме того, файл составляет около 1:36 сек. а у меня 5 гб ОЗУ. - person Octavia Togami; 27.11.2012
comment
Подкачка страниц — это когда процессор использует пространство на жестком диске в качестве виртуальной памяти, потому что ему не хватает оперативной памяти. С 5 ГБ ОЗУ, возможно, 150 МБ звука, потребляющего эту ОЗУ, не проблема. Можете ли вы запустить звук без проблем, когда фоновая графика не работает? Есть ли способ запустить только часть вашей графики и проверить звук? Я смотрю на вашу графику - вы делаете только очистку фона и рисуете линии? Это не должно вызвать проблемы. Возможно, проблема заключается в цикле while или «получении графики», как было предложено ранее. - person Phil Freihofner; 27.11.2012
comment
Большинство людей используют либо игровой цикл (цикл while с количеством thread.sleep()), либо util.Timer для запуска перерисовки графики со скоростью, возможно, 60 кадров в секунду. Ваш графический цикл while может перегружать процессор. Вы можете попробовать добавить небольшое количество сна, например, 5 или 10 мс, и посмотреть, поможет ли это. Цикл можно настроить позже, чтобы сделать количество сна переменным. - person Phil Freihofner; 27.11.2012
comment
Я могу запустить программу без проблем со звуком, когда рисунок деактивирован. - person Octavia Togami; 28.11.2012
comment
Я отредактировал цикл, чтобы захватить графическую переменную перед циклом, и добавил задержку в 20 миллисекунд, но он все еще дрожит. Я собираюсь перестать использовать BigClip, потому что он все еще испорчен с задержкой в ​​​​2000 милли. - person Octavia Togami; 28.11.2012