Я пытаюсь создать формулу для вывода треугольной волны, используя logi c вместо аддитивного синтеза, поскольку использование аддитивного синтеза более интенсивно использует процессор.
Более подробную информацию можно найти здесь, ' Проблемы с формулой для вывода формы треугольника в Java '
С тех пор я немного отредактировал код. Моя проблема в том, что формула генерации линейной треугольной волны не является точной. Он искажен и слишком резок для высоких нот.
Метод, с которым у меня возникли проблемы: 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);
}
}