我有一段(非常简单的)我已经拼凑在一起的代码,它播放特定频率的正弦波并播放它 - 它没有问题:
public class Sine {
private static final int SAMPLE_RATE = 16 * 1024;
private static final int FREQ = 500;
public static void main(String[] args) throws LineUnavailableException {
final AudioFormat af = new AudioFormat(SAMPLE_RATE, 8, 1, true, true);
try(SourceDataLine line = AudioSystem.getSourceDataLine(af)) {
line.open(af, SAMPLE_RATE);
line.start();
play(line);
line.drain();
}
}
private static void play(SourceDataLine line) {
byte[] arr = getData();
line.write(arr, 0, arr.length);
}
private static byte[] getData() {
final int LENGTH = SAMPLE_RATE * 100;
final byte[] arr = new byte[LENGTH];
for(int i = 0; i < arr.length; i++) {
double angle = (2.0 * Math.PI * i) / (SAMPLE_RATE/FREQ);
arr[i] = (byte) (Math.sin(angle) * 127);
}
return arr;
}
}
我还可以修改该getData()
方法以返回一个字节数组,该数组在播放时会产生逐渐变化的音高,没有问题。
但是,我正在努力寻找一种连续播放正弦波的方法,我可以平滑地更新“实时”的频率和幅度——即FREQ
在上面的示例中,由另一个线程更改并实时更新声音。我已经尝试创建字节数组,然后根据所需值在单独的线程中填充它,但似乎没有得到任何东西或失真。我也尝试过写入SourceDataLine
in 块,但这提供了离散频率的“块”,而不是我所追求的平滑过渡。除了我已经尝试过的以外,搜索似乎并没有提供太多帮助。
它用于模拟 theramin,因此理想情况下需要尽可能平滑低延迟。
我可以提前做没有问题 - 但事实证明现场很棘手。有没有人可以分享任何想法或例子?