Problems with formula to output a triangle waveform in Java

人盡茶涼 提交于 2020-06-14 07:59:52

问题


I got my wave file creator working and I split it into three classes, I also made a sinewave generator that inherits from an abstract class called waveform and I can export 8 and 16 bit mono or sterio sine waves. I am trying to make a class called TriangleWave Generator to output a triangle wave tone, but I can't get the algebra from https://en.wikipedia.org/wiki/Triangle_wave#, the first formula, to work. It will only export the highest harmonic stated and not blend them together with the fundamental

Sample length: length in seconds point: individual sample amp limit: the highest position possible harmonics: the number of harmonics to use to make the waveform 1 = fundamental, 2 = 1st overtone, 3 = 2nd overtone....... frequency: fundamental frequency (Middle C = 261.63) sample rate = 44100; (CD quality) triangle Samples array: sample data

This is my code

public class TriangleGenerator extends Waveform {

    // constants
    public static final int HARMONIC_COUNT = 16;

    // instance variabls
    int harmonics;
    int[] triangleSample;
    int addCount;

    // constructor
    public TriangleGenerator(double amplitude, double frequency, int bitRate, double duration, int harmonics) {
        super(amplitude, frequency, bitRate, duration);
        // sample data
        triangleSample = new int[sampleLength];
        calculateAmpLimit();
        this.harmonics = harmonics;
    }

    // one arg cunstructor
    public TriangleGenerator(double frequency) {
        this(AMPLITUDE, frequency, BIT_RATE, DURATION, HARMONIC_COUNT);
    }

    // no args constructor
    public TriangleGenerator() {
        this(AMPLITUDE, FREQUENCY, BIT_RATE, DURATION, HARMONIC_COUNT);
    }

    @Override
    public int[] generateWaveForm() {

        // generate the actual waveform
        for (int i = 0; i < sampleLength; i++) {
            point = (int)(ampLimit * ((8 / Math.pow(Math.PI, 2)) * sumnate(harmonics - 1, Math.pow(-1, addCount))
                    * Math.pow(harmonics, -2) * Math.sin(2 * Math.PI * frequency * harmonics * i / SAMPLE_RATE)));
            triangleSample[i] = point;
        }

        // return the sample data
        return triangleSample;
    }

    public double sumnate(int n, double adder) {
        double sum = 0;

        for (addCount = 0; addCount <= n; addCount++) {
            sum += adder;
        }

        return sum;
    }
}

回答1:


In the formula for the triangle wave:

the mode number n is dependent on the harmonic label i:

This means that it must also be summed over the components

which doesn't happen in the current implementation. One possible implementation is:

public int[] generateWaveForm() {
    for (int t = 0; t < sampleLength; t++) {
        triangleSample[t] = (int)(ampLimit * 8.0 / Math.pow(Math.PI, 2.0) * getDataPoint(t, N));
    }
    return triangleSample;
}

private double getDataPoint(int t, int N) {
    double sum = 0;
    for (int i = 0; i <= N - 1; i++) {
        sum += getHarmonicShare(t, i);
    }
    return sum;
}

private double getHarmonicShare(int t, int i) {
double n = 2.0 * i + 1.0;
    return Math.pow(-1.0, i) * Math.pow(n, -2.0) * Math.sin(2.0 * Math.PI * frequency * (t / SAMPLE_RATE) * n);
}

Here t, i, n and N correspond to the values from the formula. frequency denotes the frequency. The remaining values correspond to the parameters of the posted code.

The curve reaches up to the value sampleLength / SAMPLE_RATE. The period is 1 / frequency and there are (sampleLength / SAMPLE_RATE) * frequency periods in the displayed frame.

Example:

sampleLength:   500
ampLimit:       100.00
SAMPLE_RATE:  44100.00
frequency:      261.63

sampleLength / SAMPLE_RATE:               0.0113378685
1 / frequency:                            0.0038221916
(sampleLength / SAMPLE_RATE) * frequency: 2.9663265306

In the following the corresponding curve is shown for different N using JFreeChart:



来源:https://stackoverflow.com/questions/59433916/problems-with-formula-to-output-a-triangle-waveform-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!