Browse Source

Add AudioSynthWaveformSineHires - High Precision Sine Wave

dds
PaulStoffregen 8 years ago
parent
commit
c626b4443b
3 changed files with 101 additions and 0 deletions
  1. +1
    -0
      keywords.txt
  2. +69
    -0
      synth_sine.cpp
  3. +31
    -0
      synth_sine.h

+ 1
- 0
keywords.txt View File

@@ -40,6 +40,7 @@ AudioRecordQueue KEYWORD2
AudioSynthToneSweep KEYWORD2
AudioSynthWaveform KEYWORD2
AudioSynthWaveformSine KEYWORD2
AudioSynthWaveformSineHires KEYWORD2
AudioSynthWaveformSineModulated KEYWORD2
AudioSynthWaveformDc KEYWORD2
AudioSynthNoiseWhite KEYWORD2

+ 69
- 0
synth_sine.cpp View File

@@ -68,6 +68,75 @@ void AudioSynthWaveformSine::update(void)
}





#if defined(KINETISK)
// High accuracy 11th order Taylor Series Approximation
// input is 0 to 0xFFFFFFFF, representing 0 to 360 degree phase
// output is 32 bit signed integer, top 25 bits should be very good
static int32_t taylor(uint32_t ph)
{
int32_t angle, sum, p1, p2, p3, p5, p7, p9, p11;

if (ph >= 0xC0000000 || ph < 0x40000000) {
angle = (int32_t)ph; // valid from -90 to +90 degrees
} else {
angle = (int32_t)(0x80000000u - ph);
}
p1 = multiply_32x32_rshift32_rounded(angle << 1, 1686629713);
p2 = multiply_32x32_rshift32_rounded(p1, p1) << 3;
p3 = multiply_32x32_rshift32_rounded(p2, p1) << 3;
sum = multiply_subtract_32x32_rshift32_rounded(p1 << 1, p3, 1431655765);
p5 = multiply_32x32_rshift32_rounded(p3, p2) << 1;
sum = multiply_accumulate_32x32_rshift32_rounded(sum, p5, 286331153);
p7 = multiply_32x32_rshift32_rounded(p5, p2);
sum = multiply_subtract_32x32_rshift32_rounded(sum, p7, 54539267);
p9 = multiply_32x32_rshift32_rounded(p7, p2);
sum = multiply_accumulate_32x32_rshift32_rounded(sum, p9, 6059919);
p11 = multiply_32x32_rshift32_rounded(p9, p2);
sum = multiply_subtract_32x32_rshift32_rounded(sum, p11, 440721);
return sum <<= 1;
}
#endif


void AudioSynthWaveformSineHires::update(void)
{
#if defined(KINETISK)
audio_block_t *msw, *lsw;
uint32_t i, ph, inc;
int32_t val;

if (magnitude) {
msw = allocate();
lsw = allocate();
if (msw && lsw) {
ph = phase_accumulator;
inc = phase_increment;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
val = taylor(ph);
msw->data[i] = val >> 16;
lsw->data[i] = val & 0xFFFF;
ph += inc;
}
phase_accumulator = ph;
transmit(msw);
release(msw);
transmit(lsw);
release(lsw);
return;
} else {
if (msw) release(msw);
if (lsw) release(lsw);
}
}
phase_accumulator += phase_increment * AUDIO_BLOCK_SAMPLES;
#endif
}



#if defined(KINETISK)

void AudioSynthWaveformSineModulated::update(void)

+ 31
- 0
synth_sine.h View File

@@ -63,6 +63,37 @@ private:
int32_t magnitude;
};


class AudioSynthWaveformSineHires : public AudioStream
{
public:
AudioSynthWaveformSineHires() : AudioStream(0, NULL), magnitude(16384) {}
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;
phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT);
}
void phase(float angle) {
if (angle < 0.0) angle = 0.0;
else if (angle > 360.0) {
angle = angle - 360.0;
if (angle >= 360.0) return;
}
phase_accumulator = angle * (4294967296.0 / 360.0);
}
void amplitude(float n) {
if (n < 0) n = 0;
else if (n > 1.0) n = 1.0;
magnitude = n * 65536.0;
}
virtual void update(void);
private:
uint32_t phase_accumulator;
uint32_t phase_increment;
int32_t magnitude;
};


class AudioSynthWaveformSineModulated : public AudioStream
{
public:

Loading…
Cancel
Save