Problem with formula to output a triangle waveform using linear aliasing

会有一股神秘感。 提交于 2021-01-29 16:20:50

问题


I am trying to make a formula to output a triangle wave using logic instead of additive Synthesis since using additive Synthesis is more CPU intense.

More info can be found here, 'Problems with formula to output a triangle waveform in Java'

I have edited the code a bit since then. My problem is that the linear triangle wave generation formula is not precise. It has distortion and is too sharp for higher notes.

The method I am having trouble with is liniarTriangle()

public class TriangleGenerator extends AdditiveWaveform {

    // constants
    public static final int HARMONIC_COUNT = 16;

    // instance variables
    int[] triangleSample;

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

    // one arg constructor
    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() {
        if (harmonics == 0) {
            liniarTriangle();
        } else {
            additiveTriangle();
        }
        return triangleSample;
    }

    public void liniarTriangle() {

        // method variables
        double halfWaveLength = (double)SAMPLE_RATE / 
                frequency / (double)2;
        double ratio = 2 / halfWaveLength;
        double finePoint = 0;
        boolean risingEdge = true;

        // set first sample
        point = 0;
        triangleSample[0] = point;

        // loop
        for (exportIndex = 1; exportIndex < sampleLength; exportIndex++) {
            if (risingEdge) {
                if (finePoint + ratio < 1)
                    finePoint += ratio;
                else if (finePoint + ratio > 1) {
                    finePoint = finePoint - (ratio - (finePoint + ratio - 1));
                    risingEdge = false;
                } else if (finePoint + ratio == 1) {
                    finePoint = 1;
                    risingEdge = false;
                }
            } else {
                if (finePoint - ratio > -1)
                    finePoint -= ratio;
                else if (finePoint - ratio < -1) {
                    finePoint =
                        finePoint + (ratio - (Math.abs(finePoint) + ratio - 1));
                    risingEdge = true;
                } else if (finePoint - ratio == -1) {
                    finePoint = -1;
                    risingEdge = true;
                }
            }
            point = (int)(finePoint * ampLimit);
            triangleSample[exportIndex] = point;
        }
    }

    public void additiveTriangle() {
        for (exportIndex = 0; exportIndex < sampleLength; exportIndex++) {
            point = (int) (ampLimit * (8.0 / Math.pow(Math.PI, 2.0) 
                    * getDataPoint(exportIndex, harmonics)));
            triangleSample[exportIndex] = point;
        }
    }

    private double getDataPoint(int t, int N) {
        double sum = 0;
        for (int i = 0; i <= N; 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 / sampleRate * n);
    }
}

来源:https://stackoverflow.com/questions/61009312/problem-with-formula-to-output-a-triangle-waveform-using-linear-aliasing

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