print "};\n"; | print "};\n"; | ||||
#endif | #endif | ||||
const int16_t AudioWaveformTriangle[257] = { | |||||
0, 512, 1024, 1536, 2048, 2560, 3072, 3584, 4096, 4608, | |||||
5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, | |||||
10240, 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336, 14848, | |||||
15360, 15872, 16384, 16895, 17407, 17919, 18431, 18943, 19455, 19967, | |||||
20479, 20991, 21503, 22015, 22527, 23039, 23551, 24063, 24575, 25087, | |||||
25599, 26111, 26623, 27135, 27647, 28159, 28671, 29183, 29695, 30207, | |||||
30719, 31231, 31743, 32255, 32767, 32255, 31743, 31231, 30719, 30207, | |||||
29695, 29183, 28671, 28159, 27647, 27135, 26623, 26111, 25599, 25087, | |||||
24575, 24063, 23551, 23039, 22527, 22015, 21503, 20991, 20479, 19967, | |||||
19455, 18943, 18431, 17919, 17407, 16895, 16384, 15872, 15360, 14848, | |||||
14336, 13824, 13312, 12800, 12288, 11776, 11264, 10752, 10240, 9728, | |||||
9216, 8704, 8192, 7680, 7168, 6656, 6144, 5632, 5120, 4608, | |||||
4096, 3584, 3072, 2560, 2048, 1536, 1024, 512, 0, -512, | |||||
-1024, -1536, -2048, -2560, -3072, -3584, -4096, -4608, -5120, -5632, | |||||
-6144, -6656, -7168, -7680, -8192, -8704, -9216, -9728,-10240,-10752, | |||||
-11264,-11776,-12288,-12800,-13312,-13824,-14336,-14848,-15360,-15872, | |||||
-16384,-16895,-17407,-17919,-18431,-18943,-19455,-19967,-20479,-20991, | |||||
-21503,-22015,-22527,-23039,-23551,-24063,-24575,-25087,-25599,-26111, | |||||
-26623,-27135,-27647,-28159,-28671,-29183,-29695,-30207,-30719,-31231, | |||||
-31743,-32255,-32767,-32255,-31743,-31231,-30719,-30207,-29695,-29183, | |||||
-28671,-28159,-27647,-27135,-26623,-26111,-25599,-25087,-24575,-24063, | |||||
-23551,-23039,-22527,-22015,-21503,-20991,-20479,-19967,-19455,-18943, | |||||
-18431,-17919,-17407,-16895,-16384,-15872,-15360,-14848,-14336,-13824, | |||||
-13312,-12800,-12288,-11776,-11264,-10752,-10240, -9728, -9216, -8704, | |||||
-8192, -7680, -7168, -6656, -6144, -5632, -5120, -4608, -4096, -3584, | |||||
-3072, -2560, -2048, -1536, -1024, -512, 0 | |||||
}; | |||||
#if 0 | |||||
#! /usr/bin/perl | |||||
$len = 256; | |||||
print "const int16_t AudioWaveformTriangle[257] = {\n"; | |||||
for ($i=0; $i <= $len; $i++) { | |||||
$f = 0; | |||||
if ($i < $len / 4) { | |||||
$f = $i / ($len / 4); | |||||
} elsif ($i < $len * 3 / 4) { | |||||
$f = 2 - $i / ($len / 4); | |||||
} else { | |||||
$f = $i / ($len / 4) - 4; | |||||
#print "$i $f\n"; | |||||
} | |||||
$d = sprintf "%.0f", $f * 32767.0; | |||||
printf "%6d", $d + 0; | |||||
print "," if ($i < $len); | |||||
print "\n" if ($i % 10) == 9; | |||||
} | |||||
print "\n" unless ($len % 10) == 9; | |||||
print "};\n"; | |||||
#endif | |||||
const int16_t AudioWaveformSquare[257] = { | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, | |||||
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, | |||||
-32767,-32767,-32767,-32767,-32767,-32767, 32767 | |||||
}; | |||||
#if 0 | |||||
#! /usr/bin/perl | |||||
$len = 256; | |||||
print "const int16_t AudioWaveformSquare[257] = {\n"; | |||||
for ($i=0; $i <= $len; $i++) { | |||||
$f = 1.0; | |||||
if ($i < $len / 2) { | |||||
$f = 1.0; | |||||
} elsif ($i < $len) { | |||||
$f = -1.0; | |||||
} | |||||
$d = sprintf "%.0f", $f * 32767.0; | |||||
printf "%6d", $d + 0; | |||||
print "," if ($i < $len); | |||||
print "\n" if ($i % 10) == 9; | |||||
} | |||||
print "\n" unless ($len % 10) == 9; | |||||
print "};\n"; | |||||
#endif | |||||
const int16_t AudioWaveformSawtooth[257] = { | |||||
0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, | |||||
2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 4864, | |||||
5120, 5376, 5632, 5888, 6144, 6400, 6656, 6912, 7168, 7424, | |||||
7680, 7936, 8192, 8448, 8704, 8960, 9216, 9472, 9728, 9984, | |||||
10240, 10496, 10752, 11008, 11264, 11520, 11776, 12032, 12288, 12544, | |||||
12800, 13056, 13312, 13568, 13824, 14080, 14336, 14592, 14848, 15104, | |||||
15360, 15616, 15872, 16128, 16384, 16639, 16895, 17151, 17407, 17663, | |||||
17919, 18175, 18431, 18687, 18943, 19199, 19455, 19711, 19967, 20223, | |||||
20479, 20735, 20991, 21247, 21503, 21759, 22015, 22271, 22527, 22783, | |||||
23039, 23295, 23551, 23807, 24063, 24319, 24575, 24831, 25087, 25343, | |||||
25599, 25855, 26111, 26367, 26623, 26879, 27135, 27391, 27647, 27903, | |||||
28159, 28415, 28671, 28927, 29183, 29439, 29695, 29951, 30207, 30463, | |||||
30719, 30975, 31231, 31487, 31743, 31999, 32255, 32511,-32767,-32511, | |||||
-32255,-31999,-31743,-31487,-31231,-30975,-30719,-30463,-30207,-29951, | |||||
-29695,-29439,-29183,-28927,-28671,-28415,-28159,-27903,-27647,-27391, | |||||
-27135,-26879,-26623,-26367,-26111,-25855,-25599,-25343,-25087,-24831, | |||||
-24575,-24319,-24063,-23807,-23551,-23295,-23039,-22783,-22527,-22271, | |||||
-22015,-21759,-21503,-21247,-20991,-20735,-20479,-20223,-19967,-19711, | |||||
-19455,-19199,-18943,-18687,-18431,-18175,-17919,-17663,-17407,-17151, | |||||
-16895,-16639,-16384,-16128,-15872,-15616,-15360,-15104,-14848,-14592, | |||||
-14336,-14080,-13824,-13568,-13312,-13056,-12800,-12544,-12288,-12032, | |||||
-11776,-11520,-11264,-11008,-10752,-10496,-10240, -9984, -9728, -9472, | |||||
-9216, -8960, -8704, -8448, -8192, -7936, -7680, -7424, -7168, -6912, | |||||
-6656, -6400, -6144, -5888, -5632, -5376, -5120, -4864, -4608, -4352, | |||||
-4096, -3840, -3584, -3328, -3072, -2816, -2560, -2304, -2048, -1792, | |||||
-1536, -1280, -1024, -768, -512, -256, 0 | |||||
}; | |||||
#if 0 | |||||
#! /usr/bin/perl | |||||
$len = 256; | |||||
print "const int16_t AudioWaveformSawtooth[257] = {\n"; | |||||
for ($i=0; $i <= $len; $i++) { | |||||
$f = 0; | |||||
if ($i < $len / 2) { | |||||
$f = $i / $len * 2; | |||||
} else { | |||||
$f = -2 + $i / $len * 2; | |||||
#print "$i $f\n"; | |||||
} | |||||
$d = sprintf "%.0f", $f * 32767.0; | |||||
printf "%6d", $d + 0; | |||||
print "," if ($i < $len); | |||||
print "\n" if ($i % 10) == 9; | |||||
} | |||||
print "\n" unless ($len % 10) == 9; | |||||
print "};\n"; | |||||
#endif | |||||
const int16_t fader_table[257] = { | const int16_t fader_table[257] = { | ||||
0, 1, 4, 11, 19, 30, 44, 60, 78, 99, | 0, 1, 4, 11, 19, 30, 44, 60, 78, 99, |
AudioWindowHamming256 LITERAL1 | AudioWindowHamming256 LITERAL1 | ||||
AudioWindowCosine256 LITERAL1 | AudioWindowCosine256 LITERAL1 | ||||
AudioWindowTukey256 LITERAL1 | AudioWindowTukey256 LITERAL1 | ||||
AudioWaveformSine LITERAL1 | |||||
AudioWaveformTriangle LITERAL1 | |||||
AudioWaveformSquare LITERAL1 | |||||
AudioWaveformSawtooth LITERAL1 | |||||
FILTER_LOPASS LITERAL1 | FILTER_LOPASS LITERAL1 | ||||
FILTER_HIPASS LITERAL1 | FILTER_HIPASS LITERAL1 |
#include "utility/dspinst.h" | #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 140415 - change sin to use Paul's interpolation which is much | // PAH 140415 - change sin to use Paul's interpolation which is much | ||||
// faster than arm's sin function | // faster than arm's sin function | ||||
} | } | ||||
#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 | |||||
#include "AudioStream.h" | #include "AudioStream.h" | ||||
#include "arm_math.h" | #include "arm_math.h" | ||||
//#define ORIGINAL_AUDIOSYNTHWAVEFORM | |||||
#ifdef ORIGINAL_AUDIOSYNTHWAVEFORM | |||||
// 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]; | |||||
} | |||||
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 | |||||
// waveforms.c | // waveforms.c | ||||
extern "C" { | extern "C" { | ||||
extern const int16_t AudioWaveformSine[257]; | extern const int16_t AudioWaveformSine[257]; | ||||
uint16_t ramp_length; | 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 | #endif |