Browse Source

Add arbitrary waveform and offset to AudioSynthWaveform

dds
PaulStoffregen 10 years ago
parent
commit
8996df5142
5 changed files with 75 additions and 48 deletions
  1. +6
    -0
      keywords.txt
  2. +1
    -2
      synth_sine.cpp
  3. +3
    -0
      synth_sine.h
  4. +35
    -31
      synth_waveform.cpp
  5. +30
    -15
      synth_waveform.h

+ 6
- 0
keywords.txt View File

@@ -44,6 +44,7 @@ play KEYWORD2
updateCoefs KEYWORD2
frequency KEYWORD2
amplitude KEYWORD2
offset KEYWORD2
resonance KEYWORD2
octaveControl KEYWORD2
modify KEYWORD2
@@ -122,4 +123,9 @@ FILTER_PARAEQ LITERAL1
FILTER_LOSHELF LITERAL1
FILTER_HISHELF LITERAL1

WAVEFORM_SINE LITERAL1
WAVEFORM_SAWTOOTH LITERAL1
WAVEFORM_SQUARE LITERAL1
WAVEFORM_TRIANGLE LITERAL1
WAVEFORM_ARBITRARY LITERAL1


+ 1
- 2
synth_sine.cpp View File

@@ -24,8 +24,7 @@
* THE SOFTWARE.
*/

#include "Audio.h"
#include "arm_math.h"
#include "synth_sine.h"
#include "utility/dspinst.h"

// data_waveforms.c

+ 3
- 0
synth_sine.h View File

@@ -27,6 +27,9 @@
#ifndef synth_sine_h_
#define synth_sine_h_

#include "AudioStream.h"
#include "arm_math.h"

// TODO: investigate making a high resolution sine wave
// using Taylor series expansion.
// http://www.musicdsp.org/showone.php?id=13

+ 35
- 31
synth_waveform.cpp View File

@@ -36,33 +36,10 @@
// PAH 140314 - change t_hi from int to float


boolean AudioSynthWaveform::begin(float t_amp,float t_hi,short type)
{
tone_type = type;
amplitude(t_amp);
tone_freq = t_hi > 0.0;
if(t_hi <= 0.0)return false;
if(t_hi >= AUDIO_SAMPLE_RATE_EXACT/2)return false;
tone_phase = 0;
frequency(t_hi);
if(0) {
Serial.print("AudioSynthWaveform.begin(tone_amp = ");
Serial.print(t_amp);
Serial.print(", tone_hi = ");
Serial.print(t_hi);
Serial.print(", tone_incr = ");
Serial.print(tone_incr,HEX);
// Serial.print(", tone_hi = ");
// Serial.print(t_hi);
Serial.println(")");
}
return(true);
}

void AudioSynthWaveform::update(void)
{
audio_block_t *block;
short *bp;
short *bp, *end;
int32_t val1, val2, val3;
uint32_t index, scale;
@@ -70,12 +47,12 @@ void AudioSynthWaveform::update(void)
uint32_t mag;
short tmp_amp;
if(tone_freq == 0)return;
if(tone_amp == 0) return;
block = allocate();
if(block) {
if (block) {
bp = block->data;
switch(tone_type) {
case TONE_TYPE_SINE:
case WAVEFORM_SINE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
// Calculate interpolated sin
index = tone_phase >> 23;
@@ -93,8 +70,28 @@ void AudioSynthWaveform::update(void)
if(tone_phase & 0x80000000)tone_phase &= 0x7fffffff;
}
break;

case WAVEFORM_ARBITRARY:
if (!arbdata) {
release(block);
return;
}
// len = 256
for (int i = 0; i < AUDIO_BLOCK_SAMPLES;i++) {
index = tone_phase >> 23;
val1 = *(arbdata + index);
val2 = *(arbdata + ((index + 1) & 255));
scale = (tone_phase >> 7) & 0xFFFF;
val2 *= scale;
val1 *= 0xFFFF - scale;
val3 = (val1 + val2) >> 16;
*bp++ = (short)((val3 * tone_amp) >> 15);
tone_phase += tone_incr;
tone_phase &= 0x7fffffff;
}
break;
case TONE_TYPE_SQUARE:
case WAVEFORM_SQUARE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
if(tone_phase & 0x40000000)*bp++ = -tone_amp;
else *bp++ = tone_amp;
@@ -103,7 +100,7 @@ void AudioSynthWaveform::update(void)
}
break;
case TONE_TYPE_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
@@ -111,7 +108,7 @@ void AudioSynthWaveform::update(void)
}
break;

case TONE_TYPE_TRIANGLE:
case WAVEFORM_TRIANGLE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
if(tone_phase & 0x80000000) {
// negative half-cycle
@@ -132,7 +129,14 @@ void AudioSynthWaveform::update(void)
}
break;
}
// send the samples to the left channel
if (tone_offset) {
bp = block->data;
end = bp + AUDIO_BLOCK_SAMPLES;
do {
val1 = *bp;
*bp++ = signed_saturate_rshift(val1 + tone_offset, 16, 0);
} while (bp < end);
}
transmit(block,0);
release(block);
}

+ 30
- 15
synth_waveform.h View File

@@ -39,6 +39,13 @@ extern const int16_t AudioWaveformSine[257];

#define DELAY_PASSTHRU -1

#define WAVEFORM_SINE 0
#define WAVEFORM_SAWTOOTH 1
#define WAVEFORM_SQUARE 2
#define WAVEFORM_TRIANGLE 3
#define WAVEFORM_ARBITRARY 4

// todo: remove these...
#define TONE_TYPE_SINE 0
#define TONE_TYPE_SAWTOOTH 1
#define TONE_TYPE_SQUARE 2
@@ -50,24 +57,20 @@ public AudioStream
public:
AudioSynthWaveform(void) :
AudioStream(0,NULL),
tone_freq(0), tone_phase(0), tone_incr(0), tone_type(0)
tone_phase(0), tone_incr(0), tone_type(0),
tone_offset(0), arbdata(NULL)
{
}
void frequency(float t_hi)
{
if (t_hi > AUDIO_SAMPLE_RATE_EXACT / 2 || t_hi < 0.0) return;
tone_incr = ((0x80000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT) + 0.5;
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;
tone_incr = (t_freq * (0x80000000LL/AUDIO_SAMPLE_RATE_EXACT)) + 0.5;
}
void amplitude(float n) { // 0 to 1.0
if (n < 0) n = 0;
else if (n > 1.0) n = 1.0;
// Ramp code
if(tone_amp && (n == 0)) {
last_tone_amp = tone_amp;
}
else if((tone_amp == 0) && n) {
if ((tone_amp == 0) && n) {
// reset the phase when the amplitude was zero
// and has now been increased.
tone_phase = 0;
@@ -75,19 +78,31 @@ public:
// set new magnitude
tone_amp = n * 32767.0;
}
boolean begin(float t_amp,float t_hi,short t_type);
void offset(float n) {
if (n < -1.0) n = -1.0;
else if (n > 1.0) n = 1.0;
tone_offset = n * 32767.0;
}
void begin(short t_type) {
tone_phase = 0;
tone_type = t_type;
}
void begin(float t_amp, float t_freq, short t_type) {
amplitude(t_amp);
frequency(t_freq);
begin(t_type);
}
virtual void update(void);
private:
short tone_amp;
short last_tone_amp;
short tone_freq;
uint32_t tone_phase;
// volatile prevents the compiler optimizing out the frequency function
volatile uint32_t tone_incr;
short tone_type;

int16_t tone_offset;
const int16_t *arbdata;
};



Loading…
Cancel
Save