我正在构建一个扩展方波发生器的脉冲波发生器。

我的问题是我希望脉冲宽度调制过渡更平滑
我试图使在波峰和波谷之间的中间样本在调制宽度时平滑地向上或向下移动。
如此一来,诸如207 Hz的C7之类的较高声音就不会发出咔嗒声,因为占空比已调制。

需要做什么?

采样率是44100
比特率是16
ampLimit是可能的最高值。
持续时间是以秒为单位的波形长度
占空比是波形的起始周期

public class PulseGenerator extends SquareGenerator {

    // constants
    public static final double DEF_MIN_DUTY_CYCLE = 0.05;
    public static final double DEF_MAX_DUTY_CYCLE = 0.95;
    public static final double DEF_CYCLE_FREQ = 2;
    public static final double DEF_HOLD_CYCLE = 0;

    // instance variables
    double minDutyCycle; // minimum value of duty cycle
    double maxDutyCycle; // maximum value of duty cycle
    double cycleFreq;
    double holdCycle; // if more than zero, the wave will hold the modulation for that period
    double dutyCycleRange;  // maxDutyCycle - minDutyCycle
    boolean setDirection;

    // constructor
    public PulseGenerator(double amplitude, double frequency, int bitRate,
            double duration, double dutyCycle, double minDutyCycle,
            double maxDutyCycle, double cycleFreq, double holdCycle) {
        super(amplitude, frequency, bitRate, duration, dutyCycle);
        // sample data
        squareSample = new int[sampleLength];
        calculateAmpLimit();
        this.dutyCycle = dutyCycle;
        waveLength = SAMPLE_RATE / this.frequency;
        this.minDutyCycle = minDutyCycle;
        this.maxDutyCycle = maxDutyCycle;
        this.cycleFreq = cycleFreq * SAMPLE_RATE;
        this.holdCycle = holdCycle * SAMPLE_RATE;
        dutyCycleRange = this.maxDutyCycle - this.minDutyCycle;
        setDirection = false;
    }

    // one arg cunstructor
    public PulseGenerator(double frequency) {
        this(AMPLITUDE, frequency, BIT_RATE, DURATION, DEF_DUTY_CYCLE,
                DEF_MIN_DUTY_CYCLE, DEF_MAX_DUTY_CYCLE, DEF_CYCLE_FREQ,
                DEF_HOLD_CYCLE);
    }

    // no args constructor
    public PulseGenerator() {
        this(AMPLITUDE, FREQUENCY, BIT_RATE, DURATION, DEF_DUTY_CYCLE,
                DEF_MIN_DUTY_CYCLE, DEF_MAX_DUTY_CYCLE, DEF_CYCLE_FREQ,
                DEF_HOLD_CYCLE);
    }

    // generate waveform method
    @Override
    public int[] generateWaveForm() {

        // define cycle point
        int cyclePoint = (int)(cycleFreq / 2 * ((dutyCycle * dutyCycleRange) + minDutyCycle));

        // generate the actual waveform
        for (int i = 0, j = 0; i < sampleLength; i++, j++) {

            double waveCycleRatio = waveLength * dutyCycle;

            // same as square generate method
            if (j - waveCycleRatio < 0.0) {
                finePoint = 1.0;
            } else if (j - waveCycleRatio >= 0.0
                    && j - waveCycleRatio < 1) {
                finePoint = 1 - (j - waveCycleRatio);
            } else if (j - waveLength < 0.0) {
                finePoint = -1.0;
            } else if (j - waveLength >= 0.0) {
                finePoint = -1 + (waveLength - j);
            }
            if (j >= waveLength) {
                j = 1;
            }
            point = (int)finePoint * ampLimit;
            squareSample[i] = point;

            if (holdCycle > 0) {
                holdCycle--;
            } else {
                dutyCycle = (cyclePoint / (cycleFreq / 2) * dutyCycleRange)
                        + minDutyCycle;
                if (cyclePoint < cycleFreq / 2 && !setDirection) {
                    cyclePoint++;
                } else if (cyclePoint >= cycleFreq / 2 && !setDirection) {
                    cyclePoint--;
                    setDirection = true;
                } else if (cyclePoint > 0 && setDirection) {
                    cyclePoint--;
                } else if (cyclePoint <= 0 && setDirection) {
                    cyclePoint++;
                    setDirection = false;
                }
            }
        }

        // return the sample data
        return squareSample;
    }

}

最佳答案

我实际上发现了什么地方出了问题,首先我将精细点乘以一个整数,然后再乘以安培极限。其次,需要重新定位细点代码并乘以2。

// generate the actual waveform
        for (int i = 0, j = 0; i < sampleLength; i++, j++) {

            double waveCycleRatio = waveLength * dutyCycle;

            // same as square
            if (j - waveCycleRatio < 0.0) {
                finePoint = 1.0;
            } else if (j - waveCycleRatio >= 0.0
                    && j - waveCycleRatio < 1) {
                finePoint = 0 - (j - waveCycleRatio - 0.5) * 2;
            } else if (j - waveLength < 0.0) {
                finePoint = -1.0;
            } else if (j - waveLength >= 0.0) {
                finePoint = (j - waveLength - 0.5) * 2;
            }
            if (j >= waveLength) {
                j = 1;
            }
            point = (int)(finePoint * ampLimit);
            squareSample[i] = point;

            if (holdCycle > 0) {
                holdCycle--;
            } else {
                dutyCycle = (cyclePoint / (cycleFreq / 2) * dutyCycleRange)
                        + minDutyCycle;
                if (cyclePoint < cycleFreq / 2 && !setDirection) {
                    cyclePoint++;
                } else if (cyclePoint >= cycleFreq / 2 && !setDirection) {
                    cyclePoint--;
                    setDirection = true;
                } else if (cyclePoint > 0 && setDirection) {
                    cyclePoint--;
                } else if (cyclePoint <= 0 && setDirection) {
                    cyclePoint++;
                    setDirection = false;
                }
            }
        }

关于java - 如何在Java中使此脉冲波在占空比采样之间具有更好的过渡,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59462648/

10-11 21:45