【问题标题】:Huge latency while playing sampled sound javax.sound.sampled播放采样声音 javax.sound.sampled 时的巨大延迟
【发布时间】:2013-06-05 05:42:44
【问题描述】:

我有一个可以正常工作的软合成器,它可以正确输出和播放样本,但是我有很大的延迟,大约一秒。我的代码基于此处找到的一篇文章:http://www.drdobbs.com/jvm/creating-music-components-in-java/229700113?pgno=2

我是否忽略了什么?样本的生成不是问题,它发生得很快而且很简单。

我尝试将缓冲区大小更改为几个不同的值,但均未成功。我目前正在 OSX 机器上进行测试,这可能是问题所在吗?

fyi,done 永远不会是假的。到了沉默的时候,我只需将 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();
        }
    }
}

【问题讨论】:

    标签: java audio signal-processing sound-synthesis javax.sound.sampled


    【解决方案1】:

    您似乎没有设置音频系统使用的音频缓冲区大小,而是使用SAMPLES_PER_BUFFER 来控制一次生成的样本数。

    这些不是一回事 - 操作系统将请求渲染它使用的任何缓冲区大小(在 MacOSX 上,样本通过回调)。

    这段代码:

            while ((bytesRead != -1) && !done) {
                bytesRead = osc.getSamples(sampleData);
    
                if (bytesRead > 0) {
                    audioLine.write(sampleData, 0, bytesRead);
    

    只会填满音频线的缓冲区,直到它阻塞。渲染请求将到达,清空缓冲区,然后再次解除阻塞。这将以音频缓冲区大小的速率发生。

    【讨论】:

    • 我明白了,那么我该如何找出缓冲区大小呢?它是 AudioFormat 类中某处的常量吗?
    猜你喜欢
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    • 1970-01-01
    相关资源
    最近更新 更多