4

我有一个程序创建一个线程,该线程以 48 KHz 从声卡捕获数据并将其写入缓冲区以进行收集。核心线程代码如下..

    public void run()   {
    // Run continously
    for (;;)    {
        // get data from the audio device.
        getSample();
    }
}

// Read in 2 bytes from the audio source combine them together into a single integer
// then write that into the sound buffer
private void getSample ()   {
    int sample,count,total=0,fsample;
    byte buffer[]=new byte[2];
    try {
            while (total<1) {
                count=Line.read(buffer,0,2);
                total=total+count;
                }
            } catch (Exception e)   {
                String err=e.getMessage();
            }
    sample=(buffer[0]<<8)+buffer[1];

            etc etc etc 
}

该程序可以正常工作,只是该进程似乎占用了 100% 的 CPU 时间。我认为这是因为线程正在等待数据到达 Line.Read 行。我尝试在线程的各个点插入 Thread.yield() ,但似乎没有什么区别。

谁能建议我可以减少该线程占用的 CPU 时间的方法?

谢谢你的时间

伊恩

4

3 回答 3

3

确保线程阻塞输入。

The thread takes up 100% of the CPU time if it doesn't block. Blocking will cause the thread to go to sleep until there is some external stimulus to wake it up. Whenever you have a dedicated thread to process input, you need to make sure that it's blocking on that input so that it will sleep like this, exactly in order to avoid the thread taking up 100% of the CPU time in its loop.

In this specific case, if Line is a javax.sound.sampled.TargetDataLine, then the read() method is where you should be doing your blocking. According to the API, "This method blocks until the requseted amount of data has been read," but "if the data line is closed, stopped, drained, or flushed before the requested amount has been read, the method no longer blocks, but returns the number of bytes read thus far."

So, there are a couple of possibilities. I don't see your definition of Line, so it's possible that you are flushing or draining the line in some code that you didn't include. If you did that, you should refactor your solution to not use those methods.

The other possibility is that, since you're always reading only two bytes at a time, you're not reading enough to cause it to block. Basically, there are always two bytes available because it takes too long to process the two bytes you read, that there are always another two bytes available. Try increasing the size of the buffer to read more like 4kb at a time. See if that causes the loop to run less frequently, and block more frequently.

于 2010-10-25T13:48:42.273 回答
1

You need to use a read-buffer much larger than size 2. Using a reasonably large buffer size is almost always advisable in any situation, but for some reason javax.sound is particularly inefficient when using small buffer sizes. I learned this when implementing a Java-based VU-meter.

于 2010-11-20T22:40:47.743 回答
0

将 aThread.sleep(a few ms);放入无限循环中,或使用 ajava.util.Timer每隔几毫秒调用一次 getSample()。

于 2010-10-25T13:23:58.537 回答