正弦波在Java中交替出现失真

时间:2014-10-29 14:08:11

标签: java math signals sine

我试图生成正弦波并将其添加到字节数组中。我搜索并找到了。但是,我总是像附件一样得到扭曲的波形。

请告诉我你为什么会这样。感谢。

我的代码在这里

private byte[] getData(int freq) {   // taking pitch data
    double pha = Math.PI/2;          // defining phase
    final int LENGTH = 44100 * 10;   // defining length of sine wave, byte array
    final byte[] arr = new byte[LENGTH];
    for(int i = 0; i < arr.length; i++) {
        double angle = (2.0 * Math.PI * i*freq+pha) / (44100); 
        arr[i] = (byte) (Math.cos(angle) *127* 0.3);    // 0.3 is amplitude scale        
    }
    return arr;
}

Distort waveform example pic

enter image description here

2 个答案:

答案 0 :(得分:5)

代码看起来很好。我怀疑可视化用户将two's complement签名值解释为无符号(-1成为255-2成为254等等。< / p>

  

我写一个wav文件并用SonicVisualiser

绘制它

根据WAVE PCM soundfile format

  

8位采样存储为无符号字节,范围从0到255. 16位采样存储为2-s补码有符号整数,范围从-32768到32767。

看起来您需要将正弦波向上移动128(使其完全适合0-255范围内),或者转向使用16位样本。

答案 1 :(得分:0)

您可以使用此代码来说服自己,您生成的内容适合Java语义级别:

public static void main(String[] args) {
  for (byte b : getData(300)) System.out.println(sample(b));
}

static String sample(byte val) {
  final int len = (val-Byte.MIN_VALUE)/2;
  final StringBuilder b = new StringBuilder();
  for (int i = 0; i < len; i++) b.append(i < len-1? ' ' : '#');
  return b.toString();
}

它将打印一个漂亮的垂直正弦。通过使用此方法生成无符号字节来修复代码:

static byte[] getData(int freq) {
  double pha = Math.PI/2;
  final int LENGTH = 44100 * 10;
  final byte[] arr = new byte[LENGTH];
  for(int i = 0; i < arr.length; i++) {
    double angle = (2.0 * Math.PI * i*freq+pha) / (44100);
    int unsignedSample = (int) (Math.cos(angle)*Byte.MAX_VALUE*0.3 - Byte.MIN_VALUE);
    arr[i] = (byte) (unsignedSample & 0xFF);
  }
  return arr;
}

如果你打印这个,你会看到你在SonicVisualizer中看到的相同波形,但是在那个工具中它会看起来像你想要的那样。