Просмотр исходного кода

Merge pull request #24 from el-supremo/master

Remove old version of AudioSynthWaveform. Fix sine wave generation to cl...
dds
Paul Stoffregen 10 лет назад
Родитель
Сommit
ab3b21ec3c
6 измененных файлов: 37 добавлений и 270 удалений
  1. +0
    -1
      examples/PlaySynthMusic/PlaySynthMusic.ino
  2. +5
    -5
      examples/ToneSweep/ToneSweep.ino
  3. +5
    -7
      synth_tonesweep.cpp
  4. +2
    -2
      synth_tonesweep.h
  5. +17
    -174
      synth_waveform.cpp
  6. +8
    -81
      synth_waveform.h

+ 0
- 1
examples/PlaySynthMusic/PlaySynthMusic.ino Просмотреть файл

@@ -8,7 +8,6 @@
//#include <WM8731.h>
#include <SD.h>
#include <SPI.h>
#include "audiotest.h"
#include "arm_math.h"

#include "PlaySynthMusic.h"

+ 5
- 5
examples/ToneSweep/ToneSweep.ino Просмотреть файл

@@ -40,7 +40,7 @@ AudioConnection c2(myEffect, 0, audioOutput, 1);
AudioControlSGTL5000 audioShield;


int t_ampx = 20000;
float t_ampx = 0.8;
int t_lox = 10;
int t_hix = 22000;
// Length of time for the sweep in seconds
@@ -63,20 +63,20 @@ void setup(void)

Serial.println("setup done");

if(!myEffect.begin(t_ampx,t_lox,t_hix,t_timex)) {
if(!myEffect.play(t_ampx,t_lox,t_hix,t_timex)) {
Serial.println("AudioSynthToneSweep - begin failed");
while(1);
}
// wait for the sweep to end
while(myEffect.busy());
while(myEffect.isPlaying());

// and now reverse the sweep
if(!myEffect.begin(t_ampx,t_hix,t_lox,t_timex)) {
if(!myEffect.play(t_ampx,t_hix,t_lox,t_timex)) {
Serial.println("AudioSynthToneSweep - begin failed");
while(1);
}
// wait for the sweep to end
while(myEffect.busy());
while(myEffect.isPlaying());
Serial.println("Done");
}


+ 5
- 7
synth_tonesweep.cpp Просмотреть файл

@@ -32,7 +32,7 @@
// Written by Pete (El Supremo) Feb 2014


boolean AudioSynthToneSweep::begin(short t_amp,int t_lo,int t_hi,float t_time)
boolean AudioSynthToneSweep::play(float t_amp,int t_lo,int t_hi,float t_time)
{
double tone_tmp;
@@ -49,6 +49,7 @@ if(0) {
}
tone_amp = 0;
if(t_amp < 0)return false;
if(t_amp > 1)return false;
if(t_lo < 1)return false;
if(t_hi < 1)return false;
if(t_hi >= 44100/2)return false;
@@ -58,11 +59,8 @@ if(0) {
tone_hi = t_hi;
tone_phase = 0;

tone_amp = t_amp;
// Limit the output amplitude to prevent aliasing
// until I can figure out why this "overtops"
// above 29000.
if(tone_amp > 29000)tone_amp = 29000;
tone_amp = t_amp * 32767.0;

tone_tmp = tone_hi - tone_lo;
tone_sign = 1;
tone_freq = tone_lo*0x100000000LL;
@@ -78,7 +76,7 @@ if(0) {



unsigned char AudioSynthToneSweep::busy(void)
unsigned char AudioSynthToneSweep::isPlaying(void)
{
return(sweep_busy);
}

+ 2
- 2
synth_tonesweep.h Просмотреть файл

@@ -35,9 +35,9 @@ public:
AudioStream(0,NULL), sweep_busy(0)
{ }

boolean begin(short t_amp,int t_lo,int t_hi,float t_time);
boolean play(float t_amp,int t_lo,int t_hi,float t_time);
virtual void update(void);
unsigned char busy(void);
unsigned char isPlaying(void);

private:
short tone_amp;

+ 17
- 174
synth_waveform.cpp Просмотреть файл

@@ -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;
@@ -126,6 +46,7 @@ void AudioSynthWaveform::set_ramp_length(uint16_t r_length)
ramp_length = r_length;
}


boolean AudioSynthWaveform::begin(float t_amp,int t_hi,short type)
{
tone_type = type;
@@ -135,7 +56,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 +72,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 +106,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 +182,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






+ 8
- 81
synth_waveform.h Просмотреть файл

@@ -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)

@@ -102,12 +50,12 @@ public:
ramp_down(0), ramp_up(0), ramp_length(0)
{
}
// Change the frequency on-the-fly to permit a phase-continuous
// change between two frequencies.
void frequency(int t_hi)
{
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
// first starts or when the amplitude is set
@@ -136,43 +84,22 @@ public:
// set new magnitude
tone_amp = n * 32767.0;
}
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;
short last_tone_amp;
short tone_freq;
uint32_t tone_phase;
uint32_t tone_incr;
// volatile prevents the compiler optimizing out the frequency function
volatile uint32_t tone_incr;
short tone_type;

uint32_t ramp_down;
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

Загрузка…
Отмена
Сохранить