Noise in background when generating sine wave in Java

后端 未结 2 595
孤城傲影
孤城傲影 2021-01-03 03:10

I\'m getting a slight distortion (sounds like buzzing) in the background when I run the following code. Because of its subtle nature it makes believe there is some sort of a

2条回答
  •  庸人自扰
    2021-01-03 03:52

    Your comments say that the code assumes big-endian.

    Technically you're actually outputting in little-endian, however it doesn't seem to matter because through a lucky quirk your most significant byte is always 0.

    EDIT: to explain that further - when your value is at its maximum value of 127, you should be writing (0x00, 0x7f), but the actual output from your code is (0x7f, 0x00) which is 32512. This happens to be near the proper 16 bit maximum value of 32767, but with the bottom 8 bits all zero. It would be better to always use 32767 as the maximum value, and then discard the bottom 8 bits if required.

    This means that even though you're outputting 16-bit data, the effective resolution is only 8 bit. This seems to account for the lack of sound quality.

    I've made a version of your code that just dumps the raw data to a file, and can't see anything otherwise wrong with the bit shifting itself. There's no unexpected changes of sign or missing bits, but there is a buzz consistent with 8 bit sample quality.

    Also, for what it's worth your math will be easier if you calculate the wave equation based on sample counts, and then worry about byte offsets separately:

    int samples = 2 << 19;
    byte audioBuffer[] = new byte[samples * channels * sampleSizeInBytes];
    
    for ( int i = 0, j = 0; i < samples; ++i )
    {
        int wave = (int)(32767.0 * Math.sin(2.0 * Math.PI * frequency * i / sampleRate));
        byte msb = (byte)(wave >>> 8);
        byte lsb = (byte) wave;
    
        for (int c = 0; c < channels; ++c) {
            audioBuffer[j++] = msb;
            if (sampleSizeInBytes > 1) {
                audioBuffer[j++] = lsb;
            }
        }
     }
    

提交回复
热议问题