Java 中音频的循环 ShortBuffer
我正在实现一个音轨类,并且需要一个良好的循环缓冲区实现。我在音频样本中使用 Shorts,因此我更愿意对实际缓冲区使用 ShortBuffer 类。该轨道需要是线程安全的,但我可以保证只有一个线程会读取该轨道,另一个线程会写入该轨道。 我当前的实现如下所示(它不处理包装)。
public class Track {
//sample rate 44100, 2 channels with room for 4 seconds
private volatile ShortBuffer buffer = ShortBuffer.allocate((44100 * 2) * 4);
//keep count of the samples in the buffer
private AtomicInteger count = new AtomicInteger(0);
private ReentrantLock lock = new ReentrantLock(true);
private int readPosition = 0;
public int getSampleCount() {
int i = count.get();
return i > 0 ? i / 2 : 0;
}
public short[] getSamples(int sampleCount) {
short[] samples = new short[sampleCount];
try {
lock.tryLock(10, TimeUnit.MILLISECONDS);
int writePosition = buffer.position();
buffer.position(readPosition);
buffer.get(samples);
//set new read position
readPosition = buffer.position();
// set back to write position
buffer.position(writePosition);
count.addAndGet(-sampleCount);
} catch (InterruptedException e) {
System.err.println("Exception getting samples" + e);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
return samples;
}
public void pushSamples(short[] samples) {
try {
lock.tryLock(10, TimeUnit.MILLISECONDS);
buffer.put(samples);
count.addAndGet(samples.length);
} catch (InterruptedException e) {
System.err.println("Exception getting samples" + e);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
I'm implementing an audio track class and I'm in need of a good circular buffer implementation. I'm using shorts for my audio samples, so I would prefer to use a ShortBuffer class for the actual buffer. This track will need to be thread-safe but I can guarantee that only one thread will read and another will write on the track.
My current implementation looks like this (it doesn't handle wrapping).
public class Track {
//sample rate 44100, 2 channels with room for 4 seconds
private volatile ShortBuffer buffer = ShortBuffer.allocate((44100 * 2) * 4);
//keep count of the samples in the buffer
private AtomicInteger count = new AtomicInteger(0);
private ReentrantLock lock = new ReentrantLock(true);
private int readPosition = 0;
public int getSampleCount() {
int i = count.get();
return i > 0 ? i / 2 : 0;
}
public short[] getSamples(int sampleCount) {
short[] samples = new short[sampleCount];
try {
lock.tryLock(10, TimeUnit.MILLISECONDS);
int writePosition = buffer.position();
buffer.position(readPosition);
buffer.get(samples);
//set new read position
readPosition = buffer.position();
// set back to write position
buffer.position(writePosition);
count.addAndGet(-sampleCount);
} catch (InterruptedException e) {
System.err.println("Exception getting samples" + e);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
return samples;
}
public void pushSamples(short[] samples) {
try {
lock.tryLock(10, TimeUnit.MILLISECONDS);
buffer.put(samples);
count.addAndGet(samples.length);
} catch (InterruptedException e) {
System.err.println("Exception getting samples" + e);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是我提出的解决方案 http://pastebin.com/2St01Wzf 我认为它更容易将 head 和 tail 属性与短数组一起使用,而不仅仅是使用 ShortBuffer 读取位置。我还从 Java 集合类中汲取了一个想法来检测缓冲区何时已满。这是源代码,以防万一 Pastebin 消失:
}
Here's the solution that I have come up with http://pastebin.com/2St01Wzf I decided it was easier to use a head and tail property with a short array, instead of just the read position with a ShortBuffer. I also took an idea from the Java collections classes to detect when the buffer is full. Here is the source, just in case the pastebin disappears:
}