Огромная задержка при воспроизведении сэмплированного звука javax.sound.sampled

У меня есть работающий софт-синтезатор, который выводит и воспроизводит сэмплы правильно, однако у меня огромная задержка, около секунды. Мой код основан на статье, найденной здесь: http://www.drdobbs.com/jvm/creating-music-components-in-java/229700113?pgno=2

Я что-то проглядел? Генерация образцов не является проблемой, это происходит быстро и просто.

Я безуспешно пытался изменить размер буфера на несколько разных значений. В настоящее время я тестирую компьютер с OSX, может ли это быть проблемой?

к вашему сведению, сделано никогда не бывает ложным. Когда наступает время тишины, я просто загружаю в буфер сэмплы 0.

public class Player extends Thread {
    public static final int SAMPLE_RATE = 44100;
    public static final int BUFFER_SIZE = 2200;
    public static final int SAMPLES_PER_BUFFER = BUFFER_SIZE / 2;
    private static final int SAMPLE_SIZE = 16; // Don't change
    private static final int CHANNELS = 1;
    private static final boolean SIGNED = true;
    private static final boolean BIG_ENDIAN = true;
    private AudioFormat format;
    private DataLine.Info info;
    private SourceDataLine audioLine;
    private boolean done;
    private byte[] sampleData = new byte[BUFFER_SIZE];
    private Oscillator osc;

    public Player(Oscillator osc) {
        format = new AudioFormat(SAMPLE_RATE, SAMPLE_SIZE, CHANNELS, SIGNED, BIG_ENDIAN);
        info = new DataLine.Info(SourceDataLine.class, format);
        this.osc = osc;
    }

    public void run() {
        done = false;
        int bytesRead = 0;

        try {
            audioLine = (SourceDataLine) AudioSystem.getLine(info);
            audioLine.open(format);
            audioLine.start();

            while ((bytesRead != -1) && !done) {
                bytesRead = osc.getSamples(sampleData);

                if (bytesRead > 0) {
                    audioLine.write(sampleData, 0, bytesRead);
                }
            }
        } catch (LineUnavailableException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } finally {
            audioLine.drain();
            audioLine.close();
        }
    }
}

person Parth Mehrotra    schedule 05.06.2013    source источник


Ответы (1)


Похоже, вы не устанавливаете размер аудиобуфера, используемого аудиосистемой, — вместо этого вы используете SAMPLES_PER_BUFFER для управления количеством сэмплов, которые генерируются одновременно.

Это не одно и то же — операционная система будет запрашивать рендеринг любого размера буфера, который она использует (а в MacOSX образцы извлекаются через обратный вызов).

Этот код:

        while ((bytesRead != -1) && !done) {
            bytesRead = osc.getSamples(sampleData);

            if (bytesRead > 0) {
                audioLine.write(sampleData, 0, bytesRead);

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

person marko    schedule 05.06.2013
comment
Понятно, а как мне узнать размер буфера? Это константа где-то в классе AudioFormat? - person Parth Mehrotra; 09.06.2013