减少谐波在Java中产生纯音的谐波



我正在尝试在Java中开发静态方法以生成纯音。

在开始时,它似乎很容易,但是当我尝试将双阵列写入扬声器时,我会欣赏太多的谐波。

i用光谱分析仪(Sonometer)对其进行了测试,然后我还绘制了图形的阵列结果。当我完成它时,我已经看到了问题:

这是关于波浪形式的,它突然发生了。我想平滑这个数组,但我不知道该怎么做。

这是代码:

/**
 * Genera un tono puro.
 * @param bufferSize Tamaño del buffer.
 * @param fs Frecuencia de muestreo.
 * @param f0 Frecuencia central. 
 * @return El tono puro.
 */
public static double[] generateTone(int bufferSize, int fs, int f0) {
    double[] tone = new double[bufferSize]; // Tono
    double angle; // Ángulo del tono
    // Sólo hace falta recorrer la mitad del array, ya que hay simetría:
    for (int i = 0; i < tone.length / 2; i++) {
        angle = 2 * Math.PI * f0 * i / fs; // Calculamos la variación del ángulo
        // Tenemos que conseguir que la señal sea menos abrupta para reducir al máximo los armónicos):
        tone[2 * i + 1] = tone[2 * i] = Math.sin(angle); // Aprovechamos la simetría
    }
    return tone;
} // getSinus()

将相同的值写入两个连续位置将相同的值引入波形。与光滑正弦曲线的任何偏差都会增加谐波。如果您想要纯正的语气,请不要那样做。如果您想这样做,不要期望纯正的音调。

您需要为'bufferLength'的每个值计算角度和正弦,而不是每个第二个值。您正在做的实质上是在插值下进行采样。我看不到任何"对称性"。

我不太确定,但是我认为我对@EJP所说的困惑:我需要逐步获得每个值。对称性是关于信号质量的快速但更糟糕的方法。

这是新代码:

/**
 * Genera un tono puro.
 * @param bufferSize Tamaño del buffer.
 * @param fs Frecuencia de muestreo.
 * @param f0 Frecuencia central. 
 * @return El tono puro.
 */
public static double[] generateTone(int bufferSize, int fs, int f0) {
    double[] tone = new double[bufferSize]; // Tono
    double angle; // Ángulo del tono
    for (int i = 0; i < tone.length; i++) {
        angle = 2 * Math.PI * f0 * i / fs; // Calculamos la variación del ángulo
        tone[i] = Math.sin(angle); // Cada muestra se obtiene a partir del seno del ángulo
    }
    return tone;
} // generateTone()

这是确定的代码:

/**
 * Genera un tono puro.
 * @param bufferSize Tamaño del buffer.
 * @param fs Frecuencia de muestreo.
 * @param f0 Frecuencia central. 
 * @return El tono puro.
 */
public static double[] generateTone(int bufferSize, int fs, double f0) {
    double[] tone = new double[bufferSize]; // Tono
    double angle; // Ángulo del tono
    for (int i = 0; i < tone.length; i++) {
        angle = 2 * Math.PI * f0 * i / fs; // Calculamos la variación del ángulo
        tone[i] = Math.sin(angle); // Cada muestra se obtiene a partir del seno del ángulo
    }
    return tone;
} // generateTone()

测试它的main():

public static void main(String[] args) {
    double[] x; // Señal de entrada (en nuestro caso es un tono puro a 250 Hz)
    int bufferSize = 1024;
    int fs = 44100;
    double f0 = ((float) fs / (float) bufferSize);
    System.out.println("f0 =  " + f0);
    x = GSignals.generateTone(bufferSize, fs, f0); // Generamos la señal de entrada
} // main()

相关内容

  • 没有找到相关文章

最新更新