我正在玩麦克风来采样例如我的声音。为此,我使用 javax.sound.sampled 包。
但是,仅对麦克风进行采样时,我的 CPU 使用率非常高。该代码可在此处获得:
http://91.121.120.36:8081/root/gui-freq/blob/6b470aaf03038562578e4386c6774fbaca9f1fbc/src/main/java/fr/lelouet/audio/sampler/MicSampler.java
在 main 中执行的唯一代码如下:
line = (TargetDataLine) AudioSystem.getLine(info);
line.open();
line.start();
float[] newSamples = new float[samplesBufferSize];
byte[] copybuffer = new byte[newSamples.length * SAMPLE_SIZE_BYTE];
long lastTime = System.currentTimeMillis();
while (run) {
// synchronized so we don't have a problem of collecting the data when
// we should be stopped.
synchronized (LISTENLOCK) {
long begin = System.currentTimeMillis();
line.read(copybuffer, 0, copybuffer.length);
long read = System.currentTimeMillis();
for (int i = 0; i < newSamples.length; i++) {
// convert the buffer of 2 bytes to an int
newSamples[i] = copybuffer[SAMPLE_SIZE_BYTE * i] << 8
| copybuffer[SAMPLE_SIZE_BYTE * i + 1] & 0xFF;
}
long convert = System.currentTimeMillis();
addSamples(newSamples);
long add = System.currentTimeMillis();
System.err.println("delay=" + (begin - lastTime) + " read="
+ (read - begin) + " convert=" + (convert - read) + " add="
+ (add - convert));
lastTime = add;
}
}
我使用 System.err 来调试 CPU 使用率值,这给了我类似的东西:
delay=1 read=788 convert=0 add=0
这意味着代码大部分时间都在 line.read 调用中使用。
同时 top 为 java 返回 120% 的 CPU 时间。
我发现这种高 CPU 使用率太昂贵了。在我看来,代码将在 while(true) 循环中主动寻找数据。我错了吗 ?我应该如何更改我的代码?
编辑 :
我在读取数据之前添加了一个等待:
long remaining = copybuffer.length - line.available();
while (remaining > 0) {
long ms = (long) (1000 * remaining / format.getSampleRate() / SAMPLE_SIZE_BYTE);
if (ms > 5) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
}
}
remaining = copybuffer.length - line.available();
}
我现在的 CPU 使用率 <5%,大部分时间都花在等待循环而不是 read() 上。它确认 read() 包含一个活动循环。