7

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

一开始看起来很容易,但是当我尝试将双阵列写入扬声器时,我欣赏太多谐波。

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

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

这是代码:

/**
 * 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()
4

4 回答 4

3

将相同的值写入两个连续的位置会在波形中引入一个阶跃。任何与平滑正弦曲线的偏差都会增加谐波。如果您想要纯音,请不要这样做。如果你想这样做,不要指望纯音。

于 2014-01-25T02:54:43.217 回答
1

您需要计算 'bufferLength' 的每个值的角度和正弦值,而不是每个第二个值。您所做的基本上是通过插值进行欠采样。我没有看到任何“对称”。

于 2014-01-24T22:37:23.477 回答
0

这是最终的代码:

/**
 * 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()
于 2014-01-25T06:56:33.877 回答
0

I'm not really sure, but I think I've confused about @EJP was talking about: I needed obtain each value step by step. Symmetry it was a fast but worse method about the quality of the signal.

This is the new code:

/**
 * 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()
于 2014-01-24T23:05:33.280 回答