Browse Source

Add pulse-width sampling to the pulse generator - at rising edge sample the pulse width for the cycle so that modulation doesn't break the step-detection logic

dds
user 4 years ago
parent
commit
0d938fe01a
2 changed files with 46 additions and 7 deletions
  1. +44
    -7
      synth_waveform.cpp
  2. +2
    -0
      synth_waveform.h

+ 44
- 7
synth_waveform.cpp View File

#define HALF_GUARD (1 << (GUARD_BITS-1)) #define HALF_GUARD (1 << (GUARD_BITS-1))




#define DEG90 0x40000000u
#define DEG180 0x80000000u #define DEG180 0x80000000u


#define PHASE_SCALE (0x100000000L / (2 * BASE_AMPLITUDE)) #define PHASE_SCALE (0x100000000L / (2 * BASE_AMPLITUDE))
return sample ; return sample ;
} }


void BandLimitedWaveform::new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i)
void BandLimitedWaveform::new_step_check_square (uint32_t new_phase, int i)
{ {
if (new_phase >= pulse_width && phase_word < pulse_width) // detect falling step
if (new_phase >= DEG180 && phase_word < DEG180) // detect falling step
{ {
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (pulse_width - phase_word) / (new_phase - phase_word)) ;
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (sampled_width - phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS) if (offset == SCALE<<GUARD_BITS)
offset -- ; offset -- ;
if (pulse_state) // guard against two falling steps in a row (if pulse width changing for instance) if (pulse_state) // guard against two falling steps in a row (if pulse width changing for instance)
pulse_state = false ; pulse_state = false ;
} }
} }
if (new_phase < pulse_width && phase_word >= pulse_width) // detect wrap around, rising step
else if (new_phase < DEG180 && phase_word >= DEG180) // detect wrap around, rising step
{ {
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (- phase_word) / (new_phase - phase_word)) ; int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (- phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS) if (offset == SCALE<<GUARD_BITS)
} }
} }


// Checking for new steps for pulse waveform has to deal with changing frequency and pulse width and
// not letting a pulse glitch out of existence as these change across a single period of the waveform
// now we detect the rising edge just like for a square wave and use that to sample the pulse width
// parameter, which then has to be checked against the instantaneous frequency every sample.
void BandLimitedWaveform::new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i)
{
uint32_t phase_advance = new_phase - phase_word ;
// prevent pulses glitching away by enforcing 1 sample minimum pulse width.
if (sampled_width < phase_advance)
sampled_width = phase_advance ;
else if (sampled_width > -phase_advance)
sampled_width = -phase_advance ;
if (new_phase < DEG180 && phase_word >= DEG180) // detect wrap around, rising step
{
// sample the pulse width value so its not changing under our feet later in cycle due to modulation
sampled_width = pulse_width ;

int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (- phase_word) / phase_advance) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
if (!pulse_state) // guard against two rising steps in a row (if pulse width changing for instance)
{
insert_step (- offset, true, i) ;
pulse_state = true ;
}
}
else if (pulse_state && phase_word < sampled_width && new_phase >= sampled_width) // detect falling step
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (sampled_width - phase_word) / phase_advance) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
insert_step (- offset, false, i) ;
pulse_state = false ;
}
}

void BandLimitedWaveform::new_step_check_saw (uint32_t new_phase, int i) void BandLimitedWaveform::new_step_check_saw (uint32_t new_phase, int i)
{ {


int16_t BandLimitedWaveform::generate_square (uint32_t new_phase, int i) int16_t BandLimitedWaveform::generate_square (uint32_t new_phase, int i)
{ {
new_step_check_pulse (new_phase, DEG180, i) ;
new_step_check_square (new_phase, i) ;
int32_t val = process_active_steps (new_phase) ; int32_t val = process_active_steps (new_phase) ;
int16_t sample = (int16_t) cyclic [i&15] ; int16_t sample = (int16_t) cyclic [i&15] ;
cyclic [i&15] = val ; cyclic [i&15] = val ;
void BandLimitedWaveform::init_pulse (uint32_t freq_word, uint32_t pulse_width) void BandLimitedWaveform::init_pulse (uint32_t freq_word, uint32_t pulse_width)
{ {
phase_word = 0 ; phase_word = 0 ;
sampled_width = pulse_width ;
newptr = 0 ; newptr = 0 ;
delptr = 0 ; delptr = 0 ;
for (int i = 0 ; i < 2*SUPPORT ; i++) for (int i = 0 ; i < 2*SUPPORT ; i++)
phase_word -= freq_word ; phase_word -= freq_word ;


if (phase_word < DEG90)
if (phase_word < pulse_width)
{ {
dc_offset = BASE_AMPLITUDE ; dc_offset = BASE_AMPLITUDE ;
pulse_state = true ; pulse_state = true ;

+ 2
- 0
synth_waveform.h View File

int32_t process_step (int i) ; int32_t process_step (int i) ;
int32_t process_active_steps (uint32_t new_phase) ; int32_t process_active_steps (uint32_t new_phase) ;
int32_t process_active_steps_saw (uint32_t new_phase) ; int32_t process_active_steps_saw (uint32_t new_phase) ;
void new_step_check_square (uint32_t new_phase, int i) ;
void new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i) ; void new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i) ;
void new_step_check_saw (uint32_t new_phase, int i) ; void new_step_check_saw (uint32_t new_phase, int i) ;


int delptr ; int delptr ;
int32_t cyclic[16] ; // circular buffer of output samples int32_t cyclic[16] ; // circular buffer of output samples
bool pulse_state ; bool pulse_state ;
uint32_t sampled_width ;
}; };





Loading…
Cancel
Save