Parcourir la source

Add arbitrary waveform and offset to AudioSynthWaveform

dds
PaulStoffregen il y a 11 ans
Parent
révision
8996df5142
5 fichiers modifiés avec 75 ajouts et 48 suppressions
  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 Voir le fichier

updateCoefs KEYWORD2 updateCoefs KEYWORD2
frequency KEYWORD2 frequency KEYWORD2
amplitude KEYWORD2 amplitude KEYWORD2
offset KEYWORD2
resonance KEYWORD2 resonance KEYWORD2
octaveControl KEYWORD2 octaveControl KEYWORD2
modify KEYWORD2 modify KEYWORD2
FILTER_LOSHELF LITERAL1 FILTER_LOSHELF LITERAL1
FILTER_HISHELF LITERAL1 FILTER_HISHELF LITERAL1


WAVEFORM_SINE LITERAL1
WAVEFORM_SAWTOOTH LITERAL1
WAVEFORM_SQUARE LITERAL1
WAVEFORM_TRIANGLE LITERAL1
WAVEFORM_ARBITRARY LITERAL1



+ 1
- 2
synth_sine.cpp Voir le fichier

* THE SOFTWARE. * THE SOFTWARE.
*/ */


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


// data_waveforms.c // data_waveforms.c

+ 3
- 0
synth_sine.h Voir le fichier

#ifndef synth_sine_h_ #ifndef synth_sine_h_
#define synth_sine_h_ #define synth_sine_h_


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

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

+ 35
- 31
synth_waveform.cpp Voir le fichier

// PAH 140314 - change t_hi from int to float // 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) void AudioSynthWaveform::update(void)
{ {
audio_block_t *block; audio_block_t *block;
short *bp;
short *bp, *end;
int32_t val1, val2, val3; int32_t val1, val2, val3;
uint32_t index, scale; uint32_t index, scale;
uint32_t mag; uint32_t mag;
short tmp_amp; short tmp_amp;
if(tone_freq == 0)return;
if(tone_amp == 0) return;
block = allocate(); block = allocate();
if(block) {
if (block) {
bp = block->data; bp = block->data;
switch(tone_type) { switch(tone_type) {
case TONE_TYPE_SINE:
case WAVEFORM_SINE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) { for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
// Calculate interpolated sin // Calculate interpolated sin
index = tone_phase >> 23; index = tone_phase >> 23;
if(tone_phase & 0x80000000)tone_phase &= 0x7fffffff; if(tone_phase & 0x80000000)tone_phase &= 0x7fffffff;
} }
break; 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++) { for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
if(tone_phase & 0x40000000)*bp++ = -tone_amp; if(tone_phase & 0x40000000)*bp++ = -tone_amp;
else *bp++ = tone_amp; else *bp++ = tone_amp;
} }
break; break;
case TONE_TYPE_SAWTOOTH:
case WAVEFORM_SAWTOOTH:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) { for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
*bp++ = ((short)(tone_phase>>15)*tone_amp) >> 15; *bp++ = ((short)(tone_phase>>15)*tone_amp) >> 15;
// phase and incr are both unsigned 32-bit fractions // phase and incr are both unsigned 32-bit fractions
} }
break; break;


case TONE_TYPE_TRIANGLE:
case WAVEFORM_TRIANGLE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) { for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
if(tone_phase & 0x80000000) { if(tone_phase & 0x80000000) {
// negative half-cycle // negative half-cycle
} }
break; 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); transmit(block,0);
release(block); release(block);
} }

+ 30
- 15
synth_waveform.h Voir le fichier



#define DELAY_PASSTHRU -1 #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_SINE 0
#define TONE_TYPE_SAWTOOTH 1 #define TONE_TYPE_SAWTOOTH 1
#define TONE_TYPE_SQUARE 2 #define TONE_TYPE_SQUARE 2
public: public:
AudioSynthWaveform(void) : AudioSynthWaveform(void) :
AudioStream(0,NULL), 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 void amplitude(float n) { // 0 to 1.0
if (n < 0) n = 0; if (n < 0) n = 0;
else if (n > 1.0) n = 1.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 // reset the phase when the amplitude was zero
// and has now been increased. // and has now been increased.
tone_phase = 0; tone_phase = 0;
// set new magnitude // set new magnitude
tone_amp = n * 32767.0; 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); virtual void update(void);
private: private:
short tone_amp; short tone_amp;
short last_tone_amp;
short tone_freq; short tone_freq;
uint32_t tone_phase; uint32_t tone_phase;
// volatile prevents the compiler optimizing out the frequency function // volatile prevents the compiler optimizing out the frequency function
volatile uint32_t tone_incr; volatile uint32_t tone_incr;
short tone_type; short tone_type;

int16_t tone_offset;
const int16_t *arbdata;
}; };





Chargement…
Annuler
Enregistrer