我正在嘗試制作一段可以連續播放正弦波的代碼。我希望能夠播放 MIDI 音符的頻率。Java 中的 MIDI 庫感覺有點草率(當我告訴它播放時,按鍵和音符播放之間有一個小延遲)。我見過這樣的例子,你生成一個確定長度的正弦波,然后你通過給一個SourceDataLine字節數組來播放它。這行得通,但字節數組只能這么長,最終會停止播放。我的下一個想法是不斷地向該行寫入一個字節,計算下一行并繼續。這是我的代碼:int i = 0;int sampleRate = 8000;int freq = 440;while (true) { double samplingInterval = (double) (sampleRate / freq); double angle = (2.0 * Math.PI * i) / samplingInterval; byte toPlay = (byte) (Math.sin(angle) * 127); line.write(new byte[] {toPlay}, 0, 1); i++;}我希望這會給我一個頻率為 440hz 的恒定輸出,但它給了我這個錯誤:java.lang.IllegalArgumentException: illegal request to write non-integral number of frames (1 bytes, frameSize = 2 bytes)如果沒有,有沒有辦法在 Java 中加速 MIDI 庫,或者我只是犯了一個愚蠢的錯誤?提前致謝。
2 回答

嚕嚕噠
TA貢獻1784條經驗 獲得超7個贊
一幀音頻是一個或多個同時定時的音頻樣本。在您的情況下,立體聲 ( frames ==2
)。在流中,它們通常是交錯的(例如 L、R、L、R....)。
您可以通過將每個示例編寫兩次來解決此問題。
雖然 Java(或任何其他具有停止世界垃圾收集功能的 JITd 語言運行時)從來都不是低延遲音頻軟件的實現選擇,但我懷疑您檢測到的“草率”實際上是一個較長的音頻緩沖期:默認設置緩沖期可能只有幾分之一秒。

Cats萌萌
TA貢獻1805條經驗 獲得超9個贊
對于這個特定的想法,您可以使用
while (true) {
double samplingInterval = (double) (sampleRate / freq);
double angle = (2.0 * Math.PI * i) / samplingInterval;
byte toPlay = (byte) (Math.sin(angle) * 127);
byte[] data=new byte[1024];
for(int j=0; j<data.length; j++) data[j]=toPlay;
line.write(data, 0, data.length);
i++;
}
或者長度為 4 就足夠了。
添加回答
舉報
0/150
提交
取消