Java中正弦波交替畸变

3

我正在尝试生成正弦波并将其添加到字节数组中。我搜索并找到了相关资料,但是我总是得到像附件上这样的畸变波形。

请告诉我为什么会出现这种情况。谢谢。

我的代码在这里

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;
}

波形扭曲示例图片

输入图像描述


我认为是这样,但我无法处理它。 - Bilge Mirac Atici
@AkiSuihkonen,这是Java。这里没有无符号类型。 - John Bollinger
2个回答

5
代码看起来没问题。我怀疑是可视化器将二进制补码表示的带符号值解释为无符号值(-1变成了255-2变成了254等)。根据WAVE PCM音频文件格式:8位采样作为无符号字节存储,范围从0到255。16位采样以二进制补码形式存储,范围从-32768到32767。看起来你需要将正弦波上移128个单位(这样它就完全适合0-255的范围内)或转向使用16位采样。

我将数据写入wav文件并使用SonicVisualiser进行绘图。 - Bilge Mirac Atici
Java中的byte是有符号的。在Sonic Visualizer中它是无符号的吗? - user3458

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中相同的波形,但在那个工具中它会呈现你期望的样子。


它对我也有效,但我无法缩放振幅。我应该在哪里添加*0.3? - Bilge Mirac Atici
它已经在代码中了,在声明unsignedSample的那一行。 - Marko Topolnik
定义“不起作用”的含义。我可以成功地将那个0.3替换为任何其他振幅,并获得预期的结果。 - Marko Topolnik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接