的正弦波我有一個(很簡單)的代碼,我放在一起時播放特定頻率的正弦波併發揮它 - 它的工作原理沒有問題:播放不同的音調
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
,但這提供了離散頻率的「塊」,而不是我之後的平滑過渡。搜索周圍似乎沒有提供比我已經嘗試過的更多。
這是模擬一個theramin,所以理想情況下需要儘可能平滑低延遲。
我可以提前做到沒有問題 - 但生活是棘手的。有沒有人可以分享他們的想法或實例?
使用[javax.sound.midi](http://docs.oracle.com/javase/7/docs/api/javax/sound/midi/package-summary.html)可能會帶來更好的運氣。 MIDI規格。 Channel Pressure&Pitch Bend似乎適合用例。 –
@AndrewThompson我的確想到了這一點,但是我認爲我只能彎曲我目前正在演奏的音符的任何一邊的音調,所以需要找到一些「默默」的機制(因爲想要一個更好的詞)在音調變化時我正在演奏的音符之間切換,然後使用彎音來管理轉場。 – berry120