javasound-synthesissine-wave

Why does this code produce a very noisy sine wave?


I'm trying to write a very simple sound synth in Java. I'm using the javax.sound.sampled package. The code below works, but the sine wave is very noisy and sounds like there's some kind of quiet warm noise played alongside the wave.

try {
    double sampleRate = 44100;
    //8 bits per sample, so a byte.
    AudioFormat audioFormat = new AudioFormat((float) sampleRate, 8, 1, true, false);
    SourceDataLine line = AudioSystem.getSourceDataLine(audioFormat);

    line.open(audioFormat);
    line.start();

    //A4
    double freq = 440.0;

    byte[] buf = new byte[1];

    //the formula for a sample is amplitude * sin(2.0 * PI * freq * time)
    for (int i = 0; i < sampleRate; i++) {
        double t = (i / (sampleRate - 1));
        double sample = 0.1 * Math.sin(2.0 * Math.PI * freq * t);

        //scaling the sound from -1, 1 to -127, 127
        buf[0] = (byte) (sample * (double) Byte.MAX_VALUE);

        line.write(buf, 0, 1);
    }

    line.drain();
    line.stop();
    line.close();
} catch (Exception e) {
    throw new RuntimeException(e);
}

I put the generated sound into an EQ, to verify that the sound was actually noisy, and sure enough:

this is what I got

The dominant frequency is 440 hz, but there are some other frequencies which shouldn't be present. Why is this happening? How do I fix it?


Solution

  • Here's your sine wave:

    Jagged sine wave

    It's very jagged because you're using a low bit depth combined with a low amplitude. You only have 25 different sample values to choose from.

    Here's instead your sine wave if you set your amplitude to 1.0, using the full range of your 8bit sample:

    Smooth sine wave

    And here's keeping the amplitude at 0.1, but using 16bit samples instead:

    Equally smooth sine wave

    Both of these options will clearly be less noisy.