Quellcode durchsuchen

Fix AudioSynthWaveform (had many bugs, ugh....)

dds
PaulStoffregen vor 7 Jahren
Ursprung
Commit
e822e3fd6b
2 geänderte Dateien mit 86 neuen und 96 gelöschten Zeilen
  1. +61
    -66
      synth_waveform.cpp
  2. +25
    -30
      synth_waveform.h

+ 61
- 66
synth_waveform.cpp Datei anzeigen

void AudioSynthWaveform::update(void) void AudioSynthWaveform::update(void)
{ {
audio_block_t *block; audio_block_t *block;
short *bp, *end;
int32_t val1, val2, val3;
uint32_t index, scale;
uint32_t mag;
short tmp_amp;

if (tone_amp == 0) return;
int16_t *bp, *end;
int32_t val1, val2;
int16_t magnitude15;
uint32_t i, ph, index, index2, scale;
const uint32_t inc = phase_increment;

ph = phase_accumulator + phase_offset;
if (magnitude == 0) {
phase_accumulator += inc * AUDIO_BLOCK_SAMPLES;
return;
}
block = allocate(); block = allocate();
if (!block) { if (!block) {
phase_accumulator += inc * AUDIO_BLOCK_SAMPLES;
return; return;
} }
bp = block->data; bp = block->data;

switch(tone_type) { switch(tone_type) {
case WAVEFORM_SINE: case WAVEFORM_SINE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
// Calculate interpolated sin
index = tone_phase >> 23;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = ph >> 24;
val1 = AudioWaveformSine[index]; val1 = AudioWaveformSine[index];
val2 = AudioWaveformSine[index+1]; val2 = AudioWaveformSine[index+1];
scale = (tone_phase >> 7) & 0xFFFF;
scale = (ph >> 8) & 0xFFFF;
val2 *= scale; val2 *= scale;
val1 *= 0xFFFF - scale;
val3 = (val1 + val2) >> 16;
*bp++ = (short)((val3 * tone_amp) >> 15);

// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
// If tone_phase has overflowed, truncate the top bit
if (tone_phase & 0x80000000) tone_phase &= 0x7fffffff;
val1 *= 0x10000 - scale;
*bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
ph += inc;
} }
break; break;


case WAVEFORM_ARBITRARY: case WAVEFORM_ARBITRARY:
if (!arbdata) { if (!arbdata) {
release(block); release(block);
phase_accumulator += inc * AUDIO_BLOCK_SAMPLES;
return; return;
} }
// len = 256 // len = 256
for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = tone_phase >> 23;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = ph >> 24;
index2 = index + 1;
if (index2 >= 256) index2 = 0;
val1 = *(arbdata + index); val1 = *(arbdata + index);
val2 = *(arbdata + ((index + 1) & 255));
scale = (tone_phase >> 7) & 0xFFFF;
val2 = *(arbdata + index2);
scale = (ph >> 8) & 0xFFFF;
val2 *= scale; val2 *= scale;
val1 *= 0xFFFF - scale;
val3 = (val1 + val2) >> 16;
*bp++ = (short)((val3 * tone_amp) >> 15);
tone_phase += tone_incr;
tone_phase &= 0x7fffffff;
val1 *= 0x10000 - scale;
*bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
ph += inc;
} }
break; break;


case WAVEFORM_SQUARE: case WAVEFORM_SQUARE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (tone_phase & 0x40000000) {
*bp++ = -tone_amp;
magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (ph & 0x80000000) {
*bp++ = -magnitude15;
} else { } else {
*bp++ = tone_amp;
*bp++ = magnitude15;
} }
// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
ph += inc;
} }
break; break;


case WAVEFORM_SAWTOOTH: case WAVEFORM_SAWTOOTH:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = ((short)(tone_phase>>15) * tone_amp) >> 15;
// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = signed_multiply_32x16t(magnitude, ph);
ph += inc;
} }
break; break;


case WAVEFORM_SAWTOOTH_REVERSE: case WAVEFORM_SAWTOOTH_REVERSE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = ((short)(tone_phase>>15) * tone_amp) >> 15;
// phase and incr are both unsigned 32-bit fractions
tone_phase -= tone_incr;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = signed_multiply_32x16t(0xFFFFFFFFu - magnitude, ph);
ph += inc;
} }
break; break;


case WAVEFORM_TRIANGLE: case WAVEFORM_TRIANGLE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (tone_phase & 0x80000000) {
// negative half-cycle
tmp_amp = -tone_amp;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
uint32_t phtop = ph >> 30;
if (phtop == 1 || phtop == 2) {
*bp++ = ((0x10000 - (ph >> 15)) * magnitude) >> 16;
} else { } else {
// positive half-cycle
tmp_amp = tone_amp;
*bp++ = ((ph >> 15) * magnitude) >> 16;
} }
mag = tone_phase << 2;
// Determine which quadrant
if (tone_phase & 0x40000000) {
// negate the magnitude
mag = ~mag + 1;
}
*bp++ = ((short)(mag>>17) * tmp_amp) >> 15;
tone_phase += tone_incr * 2;
ph += inc;
} }
break; break;


case WAVEFORM_PULSE: case WAVEFORM_PULSE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (tone_phase < tone_width) {
*bp++ = -tone_amp;
magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (ph < pulse_width) {
*bp++ = magnitude15;
} else { } else {
*bp++ = tone_amp;
*bp++ = -magnitude15;
} }
tone_phase += tone_incr;
ph += inc;
} }
break; break;


case WAVEFORM_SAMPLE_HOLD: case WAVEFORM_SAMPLE_HOLD:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (tone_phase < tone_incr) {
sample = random(-tone_amp, tone_amp);
}
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = sample; *bp++ = sample;
tone_phase += tone_incr;
uint32_t newph = ph + inc;
if (newph < ph) {
sample = random(magnitude) - (magnitude >> 1);
}
ph = newph;
} }
break; break;
} }
phase_accumulator = ph - phase_offset;

if (tone_offset) { if (tone_offset) {
bp = block->data; bp = block->data;
end = bp + AUDIO_BLOCK_SAMPLES; end = bp + AUDIO_BLOCK_SAMPLES;

+ 25
- 30
synth_waveform.h Datei anzeigen

class AudioSynthWaveform : public AudioStream class AudioSynthWaveform : public AudioStream
{ {
public: public:
AudioSynthWaveform(void) : AudioStream(0,NULL), tone_amp(0), tone_freq(0),
tone_phase(0), tone_width(0.25), tone_incr(0), tone_type(0),
tone_offset(0), arbdata(NULL) {
AudioSynthWaveform(void) : AudioStream(0,NULL),
phase_accumulator(0), phase_increment(0), phase_offset(0),
magnitude(0), pulse_width(0x40000000),
arbdata(NULL), sample(0), tone_type(WAVEFORM_SINE),
tone_offset(0) {
} }


void frequency(float t_freq) {
if (t_freq < 0.0) {
t_freq = 0.0;
} else if (t_freq > AUDIO_SAMPLE_RATE_EXACT / 2) {
t_freq = AUDIO_SAMPLE_RATE_EXACT / 2;
void frequency(float freq) {
if (freq < 0.0) {
freq = 0.0;
} else if (freq > AUDIO_SAMPLE_RATE_EXACT / 2) {
freq = AUDIO_SAMPLE_RATE_EXACT / 2;
} }
tone_incr = (t_freq * (0x80000000LL/AUDIO_SAMPLE_RATE_EXACT)) + 0.5;
phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT);
//tone_incr = (t_freq * (0x80000000LL/AUDIO_SAMPLE_RATE_EXACT)) + 0.5;
} }
void phase(float angle) { void phase(float angle) {
if (angle < 0.0) { if (angle < 0.0) {
angle = angle - 360.0; angle = angle - 360.0;
if (angle >= 360.0) return; if (angle >= 360.0) return;
} }
tone_phase = angle * (2147483648.0 / 360.0);
phase_offset = angle * (4294967296.0 / 360.0);
} }
void amplitude(float n) { // 0 to 1.0 void amplitude(float n) { // 0 to 1.0
if (n < 0) { if (n < 0) {
} else if (n > 1.0) { } else if (n > 1.0) {
n = 1.0; n = 1.0;
} }
if ((tone_amp == 0) && n) {
// reset the phase when the amplitude was zero
// and has now been increased.
tone_phase = 0;
}
// set new magnitude
tone_amp = n * 32767.0;
magnitude = n * 65536.0;
} }
void offset(float n) { void offset(float n) {
if (n < -1.0) { if (n < -1.0) {
} else if (n > 1.0) { } else if (n > 1.0) {
n = 1.0; n = 1.0;
} }
tone_width = n * 0x7fffffffLL;
// pulse width is stored as the equivalent phase
pulse_width = n * 4294967296.0;
} }
void begin(short t_type) { void begin(short t_type) {
tone_phase = 0;
phase_offset = 0;
tone_type = t_type; tone_type = t_type;
} }
void begin(float t_amp, float t_freq, short t_type) { void begin(float t_amp, float t_freq, short t_type) {
amplitude(t_amp); amplitude(t_amp);
frequency(t_freq); frequency(t_freq);
begin(t_type);
phase_offset = 0;
tone_type = t_type;
} }
void arbitraryWaveform(const int16_t *data, float maxFreq) { void arbitraryWaveform(const int16_t *data, float maxFreq) {
arbdata = data; arbdata = data;
virtual void update(void); virtual void update(void);


private: private:
short tone_amp;
short tone_freq;
uint32_t tone_phase;
uint32_t tone_width;
// sample for SAMPLE_HOLD
short sample;
// volatile prevents the compiler optimizing out the frequency function
volatile uint32_t tone_incr;
uint32_t phase_accumulator;
uint32_t phase_increment;
uint32_t phase_offset;
int32_t magnitude;
uint32_t pulse_width;
const int16_t *arbdata;
int16_t sample; // for WAVEFORM_SAMPLE_HOLD
short tone_type; short tone_type;
int16_t tone_offset; int16_t tone_offset;
const int16_t *arbdata;
}; };





Laden…
Abbrechen
Speichern