我开始研究一个项目,以不同的频率生成声音。在那个目标中,我使用了3个对象:
在Main
类中,我在创建缓冲区和创建阅读器之间创建了一个中断(Thread.sleep
)。它允许我在讲座开始之前填充一些环形缓冲区(我也希望看到会发生什么......)
问题在于环形缓冲区(代码如下)。如果休息时间足够短,无法在讲座开始时填满环形缓冲区,那么一切似乎都或多或少都可以。 但是,如果我的缓冲区被填满(以及许多其他无法解释的情况),我的声音有很多寄生虫。如果我分析读取数据包ID的结果,这就是我得到的:
Buffer.load - packet ID : 63 - buffer pos. = 62
Buffer.load - packet ID : 64 - buffer pos. = 63
Buffer.load - packet ID : 65 - buffer pos. = 64
Buffer.read - packet ID : 65 - buffer pos. = 2
Buffer.read - packet ID : 65 - buffer pos. = 3
Buffer.read - packet ID : 65 - buffer pos. = 4
Buffer.read - packet ID : 65 - buffer pos. = 5
读取方法始终发送相同的数据包ID,无论读取器的位置如何。但是,加载方法似乎正常工作,并在以下位置加载以下ID。
public class Buffer2 implements Observer {
private Object[] buffer;
/*
* important note about the buffer :
* It is an array and not a list.
* So, it will be impossible to shift on the left or on the right the elements
* (a method like deleteFirst or similar doesn't exsits for arrays)
* in case of lecture (then suppression) or adding of en element.
* So, I'll use three variables : one to know the lecture position in the buffer
* one for the writing position
* a last one to know the volume data into the buffer.
*/
private int inBuffer, bufferSize, first, last;
public Buffer2 (int bufferSize) {
buffer = new Object[bufferSize];
inBuffer=0;
last=0;
this.bufferSize=bufferSize;
}
public synchronized byte[] read () {
while (inBuffer==0) {
try {
wait();
System.out.println("Buffer.read = null");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// See the method "load()" for the explanation of the next line
first=(first+1)%bufferSize;
inBuffer--;
/*
* This method awake the threads which were sleeping because of the load() method
* when the buffer is full
*/
notifyAll();
Object[] temp = (Object[]) buffer[first];
System.out.println("Buffer.read - packet ID : "+(int)temp[0]+" - buffer pos. = "+first);
return (byte[]) temp[1];
}
public synchronized void load (Object[] data) {
while (inBuffer==bufferSize) {
try {
System.out.println("Buffer.load : full !");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*
* Method to calculate the position to add the new value :
* Ex : buffer size = 10 and we just read the 3rd position
* (3+1)%10 = 4 => the new value will be added in the 4th position of the array
* Ex2 : if the position was 9 :
* (9+1)%10=0 => the value would be added at the position 0 of the array.
*/
last = (last+1)%bufferSize;
inBuffer++;
System.out.println("Buffer.load - packet ID : "+(int)data[0]+" - buffer pos. = "+last);
buffer[last]=data;
/*
* Awake for all waiting threads locked
* because the buffer was empty
*/
notifyAll();
}
@Override
public void update(Observable observable, Object obj) {
if (observable instanceof Generator) {
load((Object[]) obj);
}
}
}
有什么问题?谢谢你的所有答案。
经过几次测试和检查,我发现了一些事情:
update()
方法接收不同的值,并使用这些值调用load()
方法。所以,它似乎按要求工作。buffer[last]=data;
更改缓冲区之前,我检查了数据是否来自update
方法:是的,它们是。所以,它有效。感谢Thomas提供了更准确地识别问题的技巧,但是,我仍然无法解决它。
谁会帮助我更多?
谢谢大家。
答案 0 :(得分:0)
我终于找到并修复了问题,帮助了托马斯的提示。实际上,当我通过update()
方法收到我的数据时,我有一个副作用。
收到的数据包是Object[2]
,其中的2个对象是标题的另一个Object[]
和数据本身的byte[]
。
因此,我必须读取此数据包的每个数组的每个值,以便将它们写入“一次性”对象(Object[] packet = new Object[2]
)中。
因此,update()
方法的代码是:
@Override
public synchronized void update(Observable observable, Object obj) {
if (observable instanceof Generator) {
// A packet contain a header (header) and datas (data)
Object[] packet = new Object[2];
/*
* The header contain 3 datas :
* [0] ID
* [1] The number of byes in the array of bytes
* [2] the AudioFormat
*/
Object[] header = new Object[3];
header[0]= ((Object[]) ((Object[]) obj)[0])[0];
header[1]= ((Object[]) ((Object[]) obj)[0])[1];
header[2]= ((Object[]) ((Object[]) obj)[0])[2];
// I reconstruct the hehader in the position [0] in the packet
packet[0]=header;
byte[] data = new byte[(int) header[1]*4];
for (int i=0; i< data.length ; i++) {
/*
* Reading each byte in the [i] position of the bytes[]
* This array of bytes is in the position [1] of the array which is the Object[] obj
*/
data[i] = ((byte[]) ((Object[]) obj)[1])[i];
}
// I reconstruct the data in the position [1] of the packet
packet[1]=data;
// I feed the load() method with the packet
load(packet);
}
}
我希望我的回答可以帮助别人。祝你有个美好的一天。