Parcourir la source

Remove old version of AudioSynthWaveform. Fix sine wave generation to clean up its specturm and also fix ramping.

dds
Pete (El Supremo) il y a 10 ans
Parent
révision
519822e76c
2 fichiers modifiés avec 19 ajouts et 251 suppressions
  1. +16
    -174
      synth_waveform.cpp
  2. +3
    -77
      synth_waveform.h

+ 16
- 174
synth_waveform.cpp Voir le fichier

@@ -29,90 +29,10 @@
#include "utility/dspinst.h"


#ifdef ORIGINAL_AUDIOSYNTHWAVEFORM
/******************************************************************/
// PAH - add ramp-up and ramp-down to the onset of the wave
// the length is specified in samples
void AudioSynthWaveform::set_ramp_length(uint16_t r_length)
{
if(r_length < 0) {
ramp_length = 0;
return;
}
// Don't set the ramp length longer than about 4 milliseconds
if(r_length > 44*4) {
ramp_length = 44*4;
return;
}
ramp_length = r_length;
}

void AudioSynthWaveform::update(void)
{
audio_block_t *block;
uint32_t i, ph, inc, index, scale;
int32_t val1, val2, val3;

//Serial.println("AudioSynthWaveform::update");
if (((magnitude > 0) || ramp_down) && (block = allocate()) != NULL) {
ph = phase;
inc = phase_increment;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = ph >> 24;
val1 = wavetable[index];
val2 = wavetable[index+1];
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0xFFFF - scale;
val3 = (val1 + val2) >> 16;


// The value of ramp_up is always initialized to RAMP_LENGTH and then is
// decremented each time through here until it reaches zero.
// The value of ramp_up is used to generate a Q15 fraction which varies
// from [0 - 1), and multiplies this by the current sample
if(ramp_up) {
// ramp up to the new magnitude
// ramp_mag is the Q15 representation of the fraction
// Since ramp_up can't be zero, this cannot generate +1
ramp_mag = ((ramp_length-ramp_up)<<15)/ramp_length;
ramp_up--;
block->data[i] = (val3 * ((ramp_mag * magnitude)>>15)) >> 15;

} else if(ramp_down) {
// ramp down to zero from the last magnitude
// The value of ramp_down is always initialized to RAMP_LENGTH and then is
// decremented each time through here until it reaches zero.
// The value of ramp_down is used to generate a Q15 fraction which varies
// from (1 - 0], and multiplies this by the current sample
// avoid RAMP_LENGTH/RAMP_LENGTH because Q15 format
// cannot represent +1
ramp_mag = ((ramp_down - 1)<<15)/ramp_length;
ramp_down--;
block->data[i] = (val3 * ((ramp_mag * last_magnitude)>>15)) >> 15;
} else {
block->data[i] = (val3 * magnitude) >> 15;
}

//Serial.print(block->data[i]);
//Serial.print(", ");
//if ((i % 12) == 11) Serial.println();
ph += inc;
}
//Serial.println();
phase = ph;
transmit(block);
release(block);
} else {
// is this numerical overflow ok?
phase += phase_increment * AUDIO_BLOCK_SAMPLES;
}
}
#else
/******************************************************************/
// PAH - add ramp-up and ramp-down to the onset of the wave
// the length is specified in samples
void AudioSynthWaveform::set_ramp_length(uint16_t r_length)
void AudioSynthWaveform::set_ramp_length(int16_t r_length)
{
if(r_length < 0) {
ramp_length = 0;
@@ -135,7 +55,8 @@ boolean AudioSynthWaveform::begin(float t_amp,int t_hi,short type)
if(t_hi < 1)return false;
if(t_hi >= AUDIO_SAMPLE_RATE_EXACT/2)return false;
tone_phase = 0;
tone_incr = (0x100000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT;
// tone_incr = (0x100000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT;
tone_incr = (0x80000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT;
if(0) {
Serial.print("AudioSynthWaveform.begin(tone_amp = ");
Serial.print(t_amp);
@@ -150,7 +71,9 @@ boolean AudioSynthWaveform::begin(float t_amp,int t_hi,short type)
return(true);
}


// PAH - 140313 fixed the calculation of the tone so that its spectrum
// is much improved
// PAH - 140313 fixed a problem with ramping
void AudioSynthWaveform::update(void)
{
audio_block_t *block;
@@ -182,31 +105,35 @@ void AudioSynthWaveform::update(void)
ramp_up--;
// adjust tone_phase to Q15 format and then adjust the result
// of the multiplication
*bp = (short)((arm_sin_q15(tone_phase>>17) * tone_amp) >> 15);
*bp++ = (*bp * ramp_mag)>>15;
// calculate the sample
tmp_amp = (short)((arm_sin_q15(tone_phase>>16) * tone_amp) >> 17);
*bp++ = (tmp_amp * ramp_mag)>>15;
}
else if(ramp_down) {
// ramp down to zero from the last magnitude
// The value of ramp_down is always initialized to RAMP_LENGTH and then is
// decremented each time through here until it reaches zero.
// The value of ramp_down is used to generate a Q15 fraction which varies
// from (1 - 0], and multiplies this by the current sample
// from [0 - 1), and multiplies this by the current sample
// avoid RAMP_LENGTH/RAMP_LENGTH because Q15 format
// cannot represent +1
ramp_mag = ((ramp_down - 1)<<15)/ramp_length;
ramp_down--;
// adjust tone_phase to Q15 format and then adjust the result
// of the multiplication
*bp = (short)((arm_sin_q15(tone_phase>>17) * last_tone_amp) >> 15);
*bp++ = (*bp * ramp_mag)>>15;
tmp_amp = (short)((arm_sin_q15(tone_phase>>16) * last_tone_amp) >> 17);
*bp++ = (tmp_amp * ramp_mag)>>15;
} else {
// adjust tone_phase to Q15 format and then adjust the result
// of the multiplication
*bp++ = (short)((arm_sin_q15(tone_phase>>17) * tone_amp) >> 15);
tmp_amp = (short)((arm_sin_q15(tone_phase>>16) * tone_amp) >> 17);
*bp++ = tmp_amp;
}
// 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;
}
break;
@@ -254,88 +181,3 @@ void AudioSynthWaveform::update(void)
release(block);
}
}


#endif








#if 0
void AudioSineWaveMod::frequency(float f)
{
if (f > AUDIO_SAMPLE_RATE_EXACT / 2 || f < 0.0) return;
phase_increment = (f / AUDIO_SAMPLE_RATE_EXACT) * 4294967296.0f;
}

void AudioSineWaveMod::update(void)
{
audio_block_t *block, *modinput;
uint32_t i, ph, inc, index, scale;
int32_t val1, val2;

//Serial.println("AudioSineWave::update");
modinput = receiveReadOnly();
ph = phase;
inc = phase_increment;
block = allocate();
if (!block) {
// unable to allocate memory, so we'll send nothing
if (modinput) {
// but if we got modulation data, update the phase
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
ph += inc + modinput->data[i] * modulation_factor;
}
release(modinput);
} else {
ph += phase_increment * AUDIO_BLOCK_SAMPLES;
}
phase = ph;
return;
}
if (modinput) {
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = ph >> 24;
val1 = sine_table[index];
val2 = sine_table[index+1];
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0xFFFF - scale;
block->data[i] = (val1 + val2) >> 16;
//Serial.print(block->data[i]);
//Serial.print(", ");
//if ((i % 12) == 11) Serial.println();
ph += inc + modinput->data[i] * modulation_factor;
}
release(modinput);
} else {
ph = phase;
inc = phase_increment;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = ph >> 24;
val1 = sine_table[index];
val2 = sine_table[index+1];
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0xFFFF - scale;
block->data[i] = (val1 + val2) >> 16;
//Serial.print(block->data[i]);
//Serial.print(", ");
//if ((i % 12) == 11) Serial.println();
ph += inc;
}
}
phase = ph;
transmit(block);
release(block);
}
#endif






+ 3
- 77
synth_waveform.h Voir le fichier

@@ -30,58 +30,6 @@
#include "AudioStream.h"
#include "arm_math.h"

// waveforms.c
extern "C" {
extern const int16_t AudioWaveformSine[257];
extern const int16_t AudioWaveformTriangle[257];
extern const int16_t AudioWaveformSquare[257];
extern const int16_t AudioWaveformSawtooth[257];
}

#ifdef ORIGINAL_AUDIOSYNTHWAVEFORM
class AudioSynthWaveform : public AudioStream
{
public:
AudioSynthWaveform(const int16_t *waveform)
: AudioStream(0, NULL), wavetable(waveform), magnitude(0), phase(0)
, ramp_down(0), ramp_up(0), ramp_mag(0), ramp_length(0)
{ }
void frequency(float freq) {
if (freq > AUDIO_SAMPLE_RATE_EXACT / 2 || freq < 0.0) return;
phase_increment = (freq / AUDIO_SAMPLE_RATE_EXACT) * 4294967296.0f;
}
void amplitude(float n) { // 0 to 1.0
if (n < 0) n = 0;
else if (n > 1.0) n = 1.0;
// Ramp code
if(magnitude && (n == 0)) {
ramp_down = ramp_length;
ramp_up = 0;
last_magnitude = magnitude;
}
else if((magnitude == 0) && n) {
ramp_up = ramp_length;
ramp_down = 0;
}
// set new magnitude
magnitude = n * 32767.0;
}
virtual void update(void);
void set_ramp_length(uint16_t r_length);
private:
const int16_t *wavetable;
uint16_t magnitude;
uint16_t last_magnitude;
uint32_t phase;
uint32_t phase_increment;
uint32_t ramp_down;
uint32_t ramp_up;
uint32_t ramp_mag;
uint16_t ramp_length;
};

#else

#define AUDIO_SAMPLE_RATE_ROUNDED (44118)

@@ -106,7 +54,8 @@ public:
// change between two frequencies.
void frequency(int t_hi)
{
tone_incr = (0x100000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT;
// tone_incr = (0x100000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT;
tone_incr = (0x80000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT;
}
// If ramp_length is non-zero this will set up
// either a rmap up or a ramp down when a wave
@@ -138,7 +87,7 @@ public:
}
boolean begin(float t_amp,int t_hi,short t_type);
virtual void update(void);
void set_ramp_length(uint16_t r_length);
void set_ramp_length(int16_t r_length);

private:
short tone_amp;
@@ -152,27 +101,4 @@ private:
uint32_t ramp_up;
uint16_t ramp_length;
};

#endif



#if 0
class AudioSineWaveMod : public AudioStream
{
public:
AudioSineWaveMod() : AudioStream(1, inputQueueArray) {}
void frequency(float freq);
//void amplitude(q15 n);
virtual void update(void);
private:
uint32_t phase;
uint32_t phase_increment;
uint32_t modulation_factor;
audio_block_t *inputQueueArray[1];
};
#endif



#endif

Chargement…
Annuler
Enregistrer