java ringbuffer没有读取正确的数据
我开始做一个项目,以产生不同频率的声音。在这个目标中,我使用了3个对象:
- 一个发生器,用于产生正弦信号并生成编号的声音包(带有一个简单的整数ID),以44100 Hz的频率采样,并使用“可观察”模式李>
- “环形缓冲器”是发电机的“观察者”。它将数据包存储在用作缓冲区的数组(而不是列表)中
- 读取器,用于将声音数据读入环形缓冲区
在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
read方法总是发送相同的数据包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
方法:是的,它们是。所以,它起作用了李> - 在修改了缓冲区之后,我检查了整个缓冲区中的数据(对于测试,我只使用了一个有10个值的缓冲区)。问题是:所有的值都是相同的,即使它们是在数组的前面引入的。换句话说,当我在数组中加载一个新值时,所有值都会被修改,并与最后一个值相等李>
多亏了托马斯的建议,让我能更准确地找出问题所在,但我还是解决不了
谁能帮我更多
谢谢大家
# 1 楼答案
我终于找到并解决了这个问题,借助托马斯的建议。事实上,当我通过
update()
方法接收数据时,我产生了副作用。 接收到的数据包是一个Object[2]
,其中的两个对象是另一个Object[]
用于报头,另一个byte[]
用于数据本身因此,我必须读取这个数据包的每个数组的每个值,才能将它们写入一个“单一使用”对象(
Object[] packet = new Object[2]
)因此
update()
方法的代码是:我希望我的回答能帮助别人。祝你今天愉快