class BandLimitedWaveform
{
public:
BandLimitedWaveform (void) ;
int16_t generate_sawtooth (uint32_t new_phase, int i) ;
int16_t generate_square (uint32_t new_phase, int i) ;
int16_t generate_pulse (uint32_t new_phase, uint32_t pulse_width, int i) ;
void init_sawtooth (uint32_t freq_word) ;
void init_square (uint32_t freq_word) ;
void init_pulse (uint32_t freq_word, uint32_t pulse_width) ;
private:
int32_t lookup (int offset) ;
void insert_step (int offset, bool rising, int i) ;
int32_t process_step (int i) ;
int32_t process_active_steps (uint32_t new_phase) ;
int32_t process_active_steps_saw (uint32_t new_phase) ;
int32_t process_active_steps_pulse (uint32_t new_phase, uint32_t pulse_width) ;
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_saw (uint32_t new_phase, int i) ;
uint32_t phase_word ;
int32_t dc_offset ;
step_state states [32] ;
int newptr ;
int delptr ;
int32_t cyclic[16] ;
bool pulse_state ;
uint32_t sampled_width ;
};
#define SUPPORT_SHIFT 4
#define SUPPORT (1 << SUPPORT_SHIFT)
#define PTRMASK ((2 << SUPPORT_SHIFT) - 1)
#define SCALE 16
#define SCALE_MASK (SCALE-1)
#define N (SCALE * SUPPORT * 2)
#define GUARD_BITS 8
#define GUARD (1 << GUARD_BITS)
#define HALF_GUARD (1 << (GUARD_BITS-1))
#define DEG180 0x80000000u
#define PHASE_SCALE (0x100000000L / (2 * BASE_AMPLITUDE))
extern "C"
{
extern const int16_t step_table [258] ;
}
int32_t BandLimitedWaveform::lookup (int offset)
{
int off = offset >> GUARD_BITS ;
int frac = offset & (GUARD-1) ;
int32_t a, b ;
if (off < N/2)
{
a = step_table [off+1] ;
b = step_table [off+2] ;
}
else
{
a = - step_table [N-off] ;
b = - step_table [N-off-1] ;
}
return BASE_AMPLITUDE + ((frac * b + (GUARD - frac) * a + HALF_GUARD) >> GUARD_BITS) ;
}
void BandLimitedWaveform::insert_step (int offset, bool rising, int i)
{
while (offset <= (N/2-SCALE)<<GUARD_BITS)
{
if (offset >= 0)
cyclic [i & 15] += rising ? lookup (offset) : -lookup (offset) ;
offset += SCALE<<GUARD_BITS ;
i ++ ;
}
states[newptr].offset = offset ;
states[newptr].positive = rising ;
newptr = (newptr+1) & PTRMASK ;
}
int32_t BandLimitedWaveform::process_step (int i)
{
int off = states[i].offset ;
bool positive = states[i].positive ;
int32_t entry = lookup (off) ;
off += SCALE<<GUARD_BITS ;
states[i].offset = off ;
if (off >= N<<GUARD_BITS)
dc_offset += positive ? 2*BASE_AMPLITUDE : -2*BASE_AMPLITUDE ;
return positive ? entry : -entry ;
}
int32_t BandLimitedWaveform::process_active_steps (uint32_t new_phase)
{
int32_t sample = dc_offset ;
int step_count = (newptr - delptr) & PTRMASK ;
if (step_count > 0)
{
int i = newptr ;
do
{
i = (i-1) & PTRMASK ;
sample += process_step (i) ;
} while (i != delptr) ;
if (states[delptr].offset >= N<<GUARD_BITS)
{
delptr = (delptr+1) & PTRMASK ;
if (newptr != delptr && states[delptr].offset >= N<<GUARD_BITS)
delptr = (delptr+1) & PTRMASK ;
}
}
return sample ;
}
int32_t BandLimitedWaveform::process_active_steps_saw (uint32_t new_phase)
{
int32_t sample = process_active_steps (new_phase) ;
sample += (int16_t) ((((uint64_t)phase_word * (2*BASE_AMPLITUDE)) >> 32) - BASE_AMPLITUDE) ;
if (new_phase < DEG180 && phase_word >= DEG180)
dc_offset += 2*BASE_AMPLITUDE ;
return sample ;
}
int32_t BandLimitedWaveform::process_active_steps_pulse (uint32_t new_phase, uint32_t pulse_width)
{
int32_t sample = process_active_steps (new_phase) ;
return sample + BASE_AMPLITUDE/2 - pulse_width / (0x80000000u / BASE_AMPLITUDE) ;
}
void BandLimitedWaveform::new_step_check_square (uint32_t new_phase, int i)
{
if (new_phase >= DEG180 && phase_word < DEG180)
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (sampled_width - phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
if (pulse_state)
{
insert_step (- offset, false, i) ;
pulse_state = false ;
}
}
else if (new_phase < DEG180 && phase_word >= DEG180)
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (- phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
if (!pulse_state)
{
insert_step (- offset, true, i) ;
pulse_state = true ;
}
}
}
void BandLimitedWaveform::new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i)
{
if (pulse_state && phase_word < sampled_width && (new_phase >= sampled_width || 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)
offset -- ;
insert_step (- offset, false, i) ;
pulse_state = false ;
}
if ((!pulse_state) && phase_word >= DEG180 && new_phase < DEG180)
{
sampled_width = pulse_width ;
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (- phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
insert_step (- offset, true, i) ;
pulse_state = true ;
if (pulse_state && new_phase >= sampled_width)
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (sampled_width - phase_word) / (new_phase - phase_word)) ;
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)
{
if (new_phase >= DEG180 && phase_word < DEG180)
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (DEG180 - phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
insert_step (- offset, false, i) ;
}
}
int16_t BandLimitedWaveform::generate_sawtooth (uint32_t new_phase, int i)
{
new_step_check_saw (new_phase, i) ;
int32_t val = process_active_steps_saw (new_phase) ;
int16_t sample = (int16_t) cyclic [i&15] ;
cyclic [i&15] = val ;
phase_word = new_phase ;
return sample ;
}
int16_t BandLimitedWaveform::generate_square (uint32_t new_phase, int i)
{
new_step_check_square (new_phase, i) ;
int32_t val = process_active_steps (new_phase) ;
int16_t sample = (int16_t) cyclic [i&15] ;
cyclic [i&15] = val ;
phase_word = new_phase ;
return sample ;
}
int16_t BandLimitedWaveform::generate_pulse (uint32_t new_phase, uint32_t pulse_width, int i)
{
new_step_check_pulse (new_phase, pulse_width, i) ;
int32_t val = process_active_steps_pulse (new_phase, pulse_width) ;
int32_t sample = cyclic [i&15] ;
cyclic [i&15] = val ;
phase_word = new_phase ;
return (int16_t) ((sample >> 1) - (sample >> 5)) ;
}
void BandLimitedWaveform::init_sawtooth (uint32_t freq_word)
{
phase_word = 0 ;
newptr = 0 ;
delptr = 0 ;
for (int i = 0 ; i < 2*SUPPORT ; i++)
phase_word -= freq_word ;
dc_offset = phase_word < DEG180 ? BASE_AMPLITUDE : -BASE_AMPLITUDE ;
for (int i = 0 ; i < 2*SUPPORT ; i++)
{
uint32_t new_phase = phase_word + freq_word ;
new_step_check_saw (new_phase, i) ;
cyclic [i & 15] = (int16_t) process_active_steps_saw (new_phase) ;
phase_word = new_phase ;
}
}
void BandLimitedWaveform::init_square (uint32_t freq_word)
{
init_pulse (freq_word, DEG180) ;
}
void BandLimitedWaveform::init_pulse (uint32_t freq_word, uint32_t pulse_width)
{
phase_word = 0 ;
sampled_width = pulse_width ;
newptr = 0 ;
delptr = 0 ;
for (int i = 0 ; i < 2*SUPPORT ; i++)
phase_word -= freq_word ;
if (phase_word < pulse_width)
{
dc_offset = BASE_AMPLITUDE ;
pulse_state = true ;
}
else
{
dc_offset = -BASE_AMPLITUDE ;
pulse_state = false ;
}
for (int i = 0 ; i < 2*SUPPORT ; i++)
{
uint32_t new_phase = phase_word + freq_word ;
new_step_check_pulse (new_phase, pulse_width, i) ;
cyclic [i & 15] = (int16_t) process_active_steps_pulse (new_phase, pulse_width) ;
phase_word = new_phase ;
}
}
BandLimitedWaveform::BandLimitedWaveform()
{
newptr = 0 ;
delptr = 0 ;
dc_offset = BASE_AMPLITUDE ;
phase_word = 0 ;
}