裸金屬聲

使用 java 生成聲音時,你也可以使用幾乎裸機。此程式碼將原始二進位制資料寫入 OS 音訊緩衝區以生成聲音。理解產生這樣的聲音的侷限性和必要的計算是非常重要的。由於回放基本上是瞬時的,因此需要幾乎實時地進行計算。

因此,該方法不能用於更復雜的聲音取樣。出於此目的,使用專用工具是更好的方法。

以下方法在給定的持續時間內生成並直接輸出給定體積中給定頻率的矩形波。

public void rectangleWave(byte volume, int hertz, int msecs) {
    final SourceDataLine dataLine;
    // 24 kHz x 8bit, single-channel, signed little endian AudioFormat
    AudioFormat af = new AudioFormat(24_000, 8, 1, true, false);
    try {
        dataLine = AudioSystem.getSourceDataLine(af);
        dataLine.open(af, 10_000); // audio buffer size: 10k samples
    } catch (LineUnavailableException e) {
        throw new RuntimeException(e);
    }

    int waveHalf = 24_000 / hertz; // samples for half a period
    byte[] buffer = new byte[waveHalf * 20];
    int samples = msecs * (24_000 / 1000); // 24k (samples / sec) / 1000 (ms/sec) * time(ms)

    dataLine.start(); // starts playback
    int sign = 1;

    for (int i = 0; i < samples; i += buffer.length) {
        for (int j = 0; j < 20; j++) { // generate 10 waves into buffer
            sign *= -1; 
            // fill from the jth wave-half to the j+1th wave-half with volume
            Arrays.fill(buffer, waveHalf * j, waveHalf * (j+1), (byte) (volume * sign));
        }
        dataLine.write(buffer, 0, buffer.length); // 
    }
    dataLine.drain(); // forces buffer drain to hardware
    dataLine.stop();  // ends playback
}

對於產生不同聲波的更加差異化的方式,需要進行竇計算和可能更大的樣本大小。這導致明顯更復雜的程式碼,因此在此省略。