// I want output on the line out too | // I want output on the line out too | ||||
codec.unmuteLineout(); | codec.unmuteLineout(); | ||||
// Comment out this code to hear what it sounds like | |||||
// when the tones aren't ramped. (or change 88 to 0) | |||||
// Set the ramp time for each wave | |||||
for(int i = 0; i < 8;i++) { | |||||
waves[i]->set_ramp_length(88); | |||||
} | |||||
delay(200); | delay(200); | ||||
Serial.println("Begin PlayMidiTones"); | Serial.println("Begin PlayMidiTones"); | ||||
delay(50); | delay(50); | ||||
Serial.println("setup done"); | Serial.println("setup done"); | ||||
AudioProcessorUsageMaxReset(); | |||||
AudioMemoryUsageMaxReset(); | |||||
AudioProcessorUsageMaxReset(); | |||||
AudioMemoryUsageMaxReset(); | |||||
} | } | ||||
unsigned long last_time = millis(); | unsigned long last_time = millis(); |
// Comment this if you don't it | // Comment this if you don't it | ||||
codec.unmuteLineout(); | codec.unmuteLineout(); | ||||
// Set the ramp time for each wave object | |||||
for(int i = 0; i < 8;i++) { | |||||
waves[i]->set_ramp_length(88); | |||||
} | |||||
Serial.println("setup done"); | Serial.println("setup done"); | ||||
// Initialize processor and memory measurements | // Initialize processor and memory measurements |
// faster than arm's sin function | // faster than arm's sin function | ||||
// PAH 140316 - fix calculation of sample (amplitude error) | // PAH 140316 - fix calculation of sample (amplitude error) | ||||
// PAH 140314 - change t_hi from int to float | // PAH 140314 - change t_hi from int to float | ||||
// PAH - add ramp-up and ramp-down to the onset of the wave | |||||
// the length is specified in samples | |||||
void AudioSynthWaveform::set_ramp_length(int16_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; | |||||
} | |||||
boolean AudioSynthWaveform::begin(float t_amp,float t_hi,short type) | boolean AudioSynthWaveform::begin(float t_amp,float t_hi,short type) | ||||
return(true); | return(true); | ||||
} | } | ||||
// PAH - 140313 fixed a problem with ramping | |||||
void AudioSynthWaveform::update(void) | void AudioSynthWaveform::update(void) | ||||
{ | { | ||||
audio_block_t *block; | audio_block_t *block; | ||||
short *bp; | short *bp; | ||||
// temporary for ramp in sine | |||||
uint32_t ramp_mag; | |||||
int32_t val1, val2, val3; | int32_t val1, val2, val3; | ||||
uint32_t index, scale; | uint32_t index, scale; | ||||
short tmp_amp; | short tmp_amp; | ||||
if(tone_freq == 0)return; | if(tone_freq == 0)return; | ||||
// L E F T C H A N N E L O N L Y | |||||
block = allocate(); | block = allocate(); | ||||
if(block) { | if(block) { | ||||
bp = block->data; | bp = block->data; | ||||
val2 *= scale; | val2 *= scale; | ||||
val1 *= 0xFFFF - scale; | val1 *= 0xFFFF - scale; | ||||
val3 = (val1 + val2) >> 16; | 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--; | |||||
// adjust tone_phase to Q15 format and then adjust the result | |||||
// of the multiplication | |||||
// calculate the sample | |||||
tmp_amp = (short)((val3 * tone_amp) >> 15); | |||||
*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 [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--; | |||||
tmp_amp = (short)((val3 * last_tone_amp) >> 15); | |||||
*bp++ = (tmp_amp * ramp_mag)>>15; | |||||
} else { | |||||
*bp++ = (short)((val3 * tone_amp) >> 15); | |||||
} | |||||
*bp++ = (short)((val3 * tone_amp) >> 15); | |||||
// phase and incr are both unsigned 32-bit fractions | // phase and incr are both unsigned 32-bit fractions | ||||
tone_phase += tone_incr; | tone_phase += tone_incr; |
public: | public: | ||||
AudioSynthWaveform(void) : | AudioSynthWaveform(void) : | ||||
AudioStream(0,NULL), | AudioStream(0,NULL), | ||||
tone_freq(0), tone_phase(0), tone_incr(0), tone_type(0), | |||||
ramp_down(0), ramp_up(0), ramp_length(0) | |||||
tone_freq(0), tone_phase(0), tone_incr(0), tone_type(0) | |||||
{ | { | ||||
} | } | ||||
tone_incr = ((0x80000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT) + 0.5; | tone_incr = ((0x80000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT) + 0.5; | ||||
} | } | ||||
// 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 | |||||
// back to zero. | |||||
// Note that if the ramp_length is N, the generated | |||||
// wave will be N samples longer than when it is not | |||||
// ramp | |||||
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 | // Ramp code | ||||
if(tone_amp && (n == 0)) { | if(tone_amp && (n == 0)) { | ||||
ramp_down = ramp_length; | |||||
ramp_up = 0; | |||||
last_tone_amp = tone_amp; | last_tone_amp = tone_amp; | ||||
} | } | ||||
else if((tone_amp == 0) && n) { | else if((tone_amp == 0) && n) { | ||||
ramp_up = ramp_length; | |||||
ramp_down = 0; | |||||
// reset the phase when the amplitude was zero | // reset the phase when the amplitude was zero | ||||
// and has now been increased. Note that this | |||||
// happens even if the wave is not ramped | |||||
// so that the signal starts at zero | |||||
// and has now been increased. | |||||
tone_phase = 0; | tone_phase = 0; | ||||
} | } | ||||
// set new magnitude | // set new magnitude | ||||
boolean begin(float t_amp,float t_hi,short t_type); | boolean begin(float t_amp,float t_hi,short t_type); | ||||
virtual void update(void); | virtual void update(void); | ||||
void set_ramp_length(int16_t r_length); | |||||
private: | private: | ||||
short tone_amp; | short tone_amp; | ||||
volatile uint32_t tone_incr; | volatile uint32_t tone_incr; | ||||
short tone_type; | short tone_type; | ||||
uint32_t ramp_down; | |||||
uint32_t ramp_up; | |||||
uint16_t ramp_length; | |||||
}; | }; | ||||