我正在玩麦克风来测试我的声音。为此,我使用javax.sound.sampled pacakge。
然而,当仅对麦克风进行采样时,我的CPU使用率非常高。 代码可在此处获取:
http://91.121.120.36:8081/root/gui-freq/blob/6b470aaf03038562578e4386c6774fbaca9f1fbc/src/main/java/fr/lelouet/audio/sampler/MicSampler.java
主要执行的唯一代码如下:
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使用率太贵了。在我看来,代码将在一段时间(真实)循环中主动寻找数据。我错了吗 ?我该如何更改我的代码?
编辑:
我在阅读数据之前添加了一个等待:
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();
}
我现在有超过5%的CPU使用率,大部分时间花在等待循环而不是read()上。它确认read()包含一个活动循环。