我试图生成正弦波并将其添加到字节数组中。我搜索并找到了。但是,我总是像附件一样得到扭曲的波形。
请告诉我你为什么会这样。感谢。
我的代码在这里
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;
}
答案 0 :(得分:5)
代码看起来很好。我怀疑可视化用户将two's complement签名值解释为无符号(-1
成为255
,-2
成为254
等等。< / p>
我写一个wav文件并用SonicVisualiser
绘制它
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中看到的相同波形,但是在那个工具中它会看起来像你想要的那样。