Browse Source

Fix various issues with bandlimit pulse after testing with changing/modulating pulse width and freq, also invert phase of square and pulse to match existing tone types

dds
user 4 years ago
parent
commit
563a899378
2 changed files with 38 additions and 17 deletions
  1. +23
    -5
      synth_waveform.cpp
  2. +15
    -12
      synth_waveform.h

+ 23
- 5
synth_waveform.cpp View File



#define BASE_AMPLITUDE 0x6000 // 0x7fff won't work due to Gibb's phenomenon, so use 3/4 of full range. #define BASE_AMPLITUDE 0x6000 // 0x7fff won't work due to Gibb's phenomenon, so use 3/4 of full range.


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


#define PHASE_SCALE (0x100000000L / (2 * BASE_AMPLITUDE)) #define PHASE_SCALE (0x100000000L / (2 * BASE_AMPLITUDE))


void BandLimitedWaveform::new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i) void BandLimitedWaveform::new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i)
{ {
if (new_phase >= pulse_width && phase_word < pulse_width) // detect rising step
if (new_phase >= pulse_width && phase_word < pulse_width) // 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) * (pulse_width - phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS) if (offset == SCALE<<GUARD_BITS)
offset -- ; offset -- ;
insert_step (- offset, true, i) ;
if (pulse_state) // guard against two falling steps in a row (if pulse width changing for instance)
{
insert_step (- offset, false, i) ;
pulse_state = false ;
}
} }
if (new_phase < pulse_width && phase_word >= pulse_width) // detect wrap around, falling step
if (new_phase < pulse_width && phase_word >= pulse_width) // 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)
offset -- ; offset -- ;
insert_step (- offset, false, i) ;
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 ;
}
} }
} }


for (int i = 0 ; i < 2*SUPPORT ; i++) for (int i = 0 ; i < 2*SUPPORT ; i++)
phase_word -= freq_word ; phase_word -= freq_word ;


dc_offset = phase_word < DEG180 ? -BASE_AMPLITUDE : BASE_AMPLITUDE ;
if (phase_word < DEG90)
{
dc_offset = BASE_AMPLITUDE ;
pulse_state = true ;
}
else
{
dc_offset = -BASE_AMPLITUDE ;
pulse_state = false ;
}
for (int i = 0 ; i < 2*SUPPORT ; i++) for (int i = 0 ; i < 2*SUPPORT ; i++)
{ {

+ 15
- 12
synth_waveform.h View File

#define WAVEFORM_BANDLIMIT_SAWTOOTH 9 #define WAVEFORM_BANDLIMIT_SAWTOOTH 9
#define WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE 10 #define WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE 10
#define WAVEFORM_BANDLIMIT_SQUARE 11 #define WAVEFORM_BANDLIMIT_SQUARE 11
#define WAVEFORM_BANDLIMIT_PULSE 12
#define WAVEFORM_BANDLIMIT_PULSE 12




typedef struct step_state typedef struct step_state
int newptr ; // buffer pointers into states, AND'd with PTRMASK to keep in buffer range. int newptr ; // buffer pointers into states, AND'd with PTRMASK to keep in buffer range.
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 ;
}; };




} }
phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT); phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT);
if (phase_increment > 0x7FFE0000u) phase_increment = 0x7FFE0000; if (phase_increment > 0x7FFE0000u) phase_increment = 0x7FFE0000;
ensure_pulse_width_ok () ;
} }
void phase(float angle) { void phase(float angle) {
if (angle < 0.0) { if (angle < 0.0) {
n = 1.0; n = 1.0;
} }
pulse_width = n * 4294967296.0; pulse_width = n * 4294967296.0;
if (tone_type == WAVEFORM_BANDLIMIT_PULSE)
{
if (pulse_width < phase_increment) // ensure pulse never narrow enough to glitch out of existence.
pulse_width = phase_increment ;
else if (pulse_width > -phase_increment)
pulse_width = -phase_increment;
}
ensure_pulse_width_ok () ;
} }
void begin(short t_type) { void begin(short t_type) {
phase_offset = 0; phase_offset = 0;
band_limit_waveform.init_square (phase_increment) ; band_limit_waveform.init_square (phase_increment) ;
else if (t_type == WAVEFORM_BANDLIMIT_PULSE) else if (t_type == WAVEFORM_BANDLIMIT_PULSE)
{ {
if (pulse_width < phase_increment) // ensure pulse never narrow enough to glitch out of existence.
pulse_width = phase_increment ;
else if (pulse_width > -phase_increment)
pulse_width = -phase_increment;
ensure_pulse_width_ok () ;
band_limit_waveform.init_pulse (phase_increment, pulse_width) ; band_limit_waveform.init_pulse (phase_increment, pulse_width) ;
} }
else if (t_type == WAVEFORM_BANDLIMIT_SAWTOOTH || t_type == WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE) else if (t_type == WAVEFORM_BANDLIMIT_SAWTOOTH || t_type == WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE)
virtual void update(void); virtual void update(void);


private: private:
void ensure_pulse_width_ok()
{
if (tone_type == WAVEFORM_BANDLIMIT_PULSE)
{
if (pulse_width < phase_increment) // ensure pulse never narrow enough to glitch out of existence.
pulse_width = phase_increment ;
else if (pulse_width > -phase_increment)
pulse_width = -phase_increment;
}
}
uint32_t phase_accumulator; uint32_t phase_accumulator;
uint32_t phase_increment; uint32_t phase_increment;
uint32_t phase_offset; uint32_t phase_offset;

Loading…
Cancel
Save