如何让这个脉冲波在 Java 中的占空比样本之间有更好的转换
How to get this pulse wave to to have a finer transtion between duty cycle samples in Java
我正在构建一个扩展方波发生器的脉冲波发生器。
我的问题是我希望脉宽调制过渡更平滑
我试图使波峰和波谷之间的中间样本在调制宽度时平滑地上下移动。
这是如此高的声音,例如 2093 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;
}
}
我实际上发现了问题所在,首先我将精细点转换为整数,然后再将其乘以安培限制。其次,精细点的代码需要重新定位并乘以二。
// 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;
}
}
}
我正在构建一个扩展方波发生器的脉冲波发生器。
我的问题是我希望脉宽调制过渡更平滑 我试图使波峰和波谷之间的中间样本在调制宽度时平滑地上下移动。 这是如此高的声音,例如 2093 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;
}
}
我实际上发现了问题所在,首先我将精细点转换为整数,然后再将其乘以安培限制。其次,精细点的代码需要重新定位并乘以二。
// 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;
}
}
}