特定の周波数の正弦波を再生して再生する(非常に単純な)コードを一緒にスローしました-問題なく動作します:
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
が、これは、私が求めているスムーズな移行ではなく、離散周波数の「ブロック」を提供します。周りを検索しても、私がすでに試したこと以外はあまり提供されていないようです。
これはセラミンのエミュレーション用であるため、理想的には可能な限りスムーズで低遅延である必要があります。
事前に問題なく行うことができますが、ライブは難しいことがわかっています。共有できるアイデアや例はありますか?