improved PWM code
This commit is contained in:
parent
b8265f6938
commit
18dd0947d4
@ -25,11 +25,11 @@ Synth ic29;
|
||||
Synth::Synth() {
|
||||
d_debug("initialising synth\n");
|
||||
envAtk = 0x00;
|
||||
envDcy = 0x50;
|
||||
envStn = 0x7f;
|
||||
envRls = 0x3f;
|
||||
envDcy = 0x1f;
|
||||
envStn = 0x00;
|
||||
envRls = 0x1f;
|
||||
portaCoeff = 0x0;
|
||||
lfo.speed = 0x1f;
|
||||
lfo.speed = 0x06;
|
||||
}
|
||||
|
||||
void Synth::buildTables(double sampleRate) {
|
||||
@ -49,6 +49,17 @@ void Synth::run() {
|
||||
|
||||
masterPitch = 0x1818;
|
||||
|
||||
// need to calculate VCF "base" setting
|
||||
// need to calculate PWM
|
||||
// various on/off switches
|
||||
|
||||
// PWM is bit 0 sw2, 0 = fixed 1 = lfo
|
||||
// 0 sets EA to 0x3fff, 1 adds
|
||||
uint16_t pwmVal = 0x2000 - ic29.lfo.lfoOut;
|
||||
if (0) pwmVal = 0x3fff;
|
||||
|
||||
ic29.pwm = pwmVal / 40960.0f * (1); // 0.5 is knob val
|
||||
|
||||
for (uint8_t i = 0; i < NUM_VOICES; i++) {
|
||||
ic29.voices[i].update();
|
||||
}
|
||||
@ -91,7 +102,7 @@ void LFO::run() {
|
||||
phase = 1;
|
||||
}
|
||||
|
||||
//printf("lfoOut=%04x\n", lfoOut);
|
||||
// printf("lfoOut=%04x\n", lfoOut);
|
||||
}
|
||||
|
||||
Envelope::Envelope() {
|
||||
@ -126,7 +137,7 @@ void Envelope::run() {
|
||||
}
|
||||
|
||||
Voice::Voice() {
|
||||
subosc = .11;
|
||||
subosc = .1;
|
||||
}
|
||||
|
||||
void Voice::calcPitch() {
|
||||
@ -173,6 +184,7 @@ void Voice::update() {
|
||||
// calculate the once-per-block values
|
||||
env.run();
|
||||
calcPitch();
|
||||
pw = 0.5 - ic29.pwm;
|
||||
// do filter values
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ class Voice {
|
||||
uint16_t pitch = 0x1818; // calculated pitch value with porta and master pitch etc
|
||||
float delay; // delay slot for polyblep
|
||||
bool pulseStage;
|
||||
float lastpw;
|
||||
float pw, lastpw, pwrc;
|
||||
float subosc = -1;
|
||||
float phase = 0, omega = 0;
|
||||
enum { V_DONE,
|
||||
@ -119,6 +119,8 @@ class Synth {
|
||||
Voice voices[NUM_VOICES];
|
||||
LFO lfo;
|
||||
|
||||
float pwm;
|
||||
|
||||
};
|
||||
|
||||
// global
|
||||
|
@ -30,24 +30,25 @@ static inline float poly3blep1(float t) {
|
||||
void Voice::run(float *buffer, uint32_t samples) {
|
||||
// generate a full block of samples for the oscillator
|
||||
|
||||
float y, out, pw = .50, t;
|
||||
|
||||
float y, out, t;
|
||||
float saw = 0;
|
||||
pw = 0.5-(ic29.lfo.lfoOut + 0x2000) / 61600.0f;
|
||||
|
||||
float gain = env.level / 16384.0;
|
||||
|
||||
|
||||
|
||||
// this uses an adaptation of Mystran's Polyblep oscillator
|
||||
for (uint32_t i = 0; i < samples; i++) {
|
||||
y = delay;
|
||||
delay = 0;
|
||||
phase += omega;
|
||||
|
||||
pwrc = ((pw - pwrc) *.01 ) + pwrc;
|
||||
|
||||
// this is the clever bit
|
||||
while (true) {
|
||||
if (!pulseStage) {
|
||||
if (phase < pw) break; // it's not time for the PWM output to step
|
||||
t = (phase - pw) / (lastpw - pw + omega); // calculate fractional sample allowing for PW amount
|
||||
if (phase < pwrc) break; // it's not time for the PWM output to step
|
||||
t = (phase - pwrc) / (lastpw - pwrc + omega); // calculate fractional sample allowing for PW amount
|
||||
y -= 0.63 * poly3blep0(t); // magic numbers observed on oscilloscope from real synth
|
||||
delay -= 0.63 * poly3blep1(t);
|
||||
pulseStage = true;
|
||||
@ -70,7 +71,8 @@ void Voice::run(float *buffer, uint32_t samples) {
|
||||
delay += subosc;
|
||||
|
||||
out = y * 0.15;
|
||||
lastpw = pw;
|
||||
lastpw = pwrc;
|
||||
buffer[i] += out * gain;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user