Bläddra i källkod

Merge pull request #360 from MarkTillotson/band_limited_waveforms

Band limited waveforms
dds
Paul Stoffregen 3 år sedan
förälder
incheckning
272233e399
Inget konto är kopplat till bidragsgivarens mejladress
4 ändrade filer med 529 tillägg och 2 borttagningar
  1. +101
    -0
      data_bandlimit_step.c
  2. +4
    -0
      keywords.txt
  3. +361
    -0
      synth_waveform.cpp
  4. +63
    -2
      synth_waveform.h

+ 101
- 0
data_bandlimit_step.c Visa fil

@@ -0,0 +1,101 @@
#include <stdint.h>

// band limited step function, 17kHz limit for 44.1kSPS.
// step goes from -BASE_AMPLITUDE to +BASE_AMPLITUDE nominally
// [ only store the first half of the table due to its odd symmetry ]
// the extra first entry allows for the interpolation code not to overrun on reflected table,
// the last extra entry allows for interpolation not to overrun when non-reflected

const int16_t step_table [258] = // size is N/2+2 where N = SUPPORT * SCALE * 2
{
-24576,
-24551, -24550, -24549, -24548, -24546, -24544, -24542, -24540, -24538, -24537, -24537, -24537, -24539, -24543, -24547, -24553,
-24560, -24569, -24579, -24590, -24602, -24614, -24627, -24639, -24651, -24663, -24673, -24682, -24689, -24693, -24695, -24694,
-24691, -24684, -24674, -24661, -24646, -24627, -24607, -24585, -24561, -24536, -24511, -24486, -24463, -24441, -24421, -24403,
-24390, -24380, -24374, -24373, -24377, -24386, -24400, -24418, -24441, -24469, -24499, -24533, -24569, -24607, -24645, -24683,
-24720, -24755, -24786, -24814, -24836, -24854, -24865, -24870, -24867, -24858, -24842, -24819, -24789, -24753, -24712, -24666,
-24617, -24566, -24513, -24460, -24408, -24359, -24314, -24274, -24239, -24212, -24193, -24182, -24181, -24189, -24206, -24233,
-24268, -24312, -24364, -24422, -24485, -24552, -24621, -24691, -24760, -24826, -24889, -24945, -24994, -25034, -25064, -25084,
-25091, -25087, -25070, -25041, -25000, -24948, -24886, -24815, -24736, -24652, -24564, -24473, -24383, -24296, -24213, -24136,
-24068, -24011, -23965, -23934, -23916, -23914, -23928, -23958, -24003, -24064, -24137, -24224, -24320, -24426, -24537, -24653,
-24769, -24884, -24994, -25097, -25190, -25271, -25337, -25387, -25418, -25430, -25422, -25394, -25345, -25276, -25188, -25084,
-24964, -24832, -24691, -24542, -24391, -24240, -24092, -23953, -23824, -23710, -23613, -23537, -23484, -23456, -23454, -23478,
-23531, -23610, -23714, -23843, -23993, -24162, -24347, -24542, -24745, -24950, -25153, -25348, -25531, -25697, -25841, -25960,
-26048, -26104, -26125, -26108, -26054, -25961, -25831, -25665, -25466, -25238, -24984, -24710, -24422, -24125, -23828, -23535,
-23256, -22998, -22766, -22570, -22414, -22304, -22246, -22244, -22300, -22417, -22594, -22831, -23126, -23475, -23872, -24311,
-24785, -25283, -25795, -26311, -26816, -27300, -27747, -28143, -28476, -28731, -28894, -28953, -28896, -28711, -28390, -27923,
-27305, -26530, -25596, -24501, -23246, -21836, -20274, -18569, -16729, -14766, -12691, -10521, -8269, -5953, -3591, -1200,
1200
};

/* // this version is for SCALE = 64, but with interpolation isn't really needed
int16_t edge_table [1026] = // size is N/2+2 where N = SUPPORT * SCALE * 2
{
-24576,
-24551, -24551, -24551, -24551, -24551, -24550, -24550, -24550, -24550, -24549, -24549, -24549, -24548, -24548, -24547, -24547,
-24547, -24546, -24546, -24545, -24544, -24544, -24543, -24543, -24542, -24542, -24541, -24541, -24540, -24540, -24539, -24539,
-24539, -24538, -24538, -24538, -24537, -24537, -24537, -24537, -24537, -24537, -24537, -24537, -24537, -24537, -24538, -24538,
-24539, -24539, -24540, -24540, -24541, -24542, -24543, -24544, -24545, -24546, -24548, -24549, -24551, -24552, -24554, -24556,
-24557, -24559, -24561, -24563, -24566, -24568, -24570, -24573, -24575, -24578, -24580, -24583, -24586, -24588, -24591, -24594,
-24597, -24600, -24603, -24606, -24609, -24612, -24616, -24619, -24622, -24625, -24628, -24631, -24635, -24638, -24641, -24644,
-24647, -24650, -24653, -24656, -24659, -24661, -24664, -24667, -24669, -24672, -24674, -24677, -24679, -24681, -24683, -24685,
-24686, -24688, -24689, -24690, -24692, -24693, -24693, -24694, -24695, -24695, -24695, -24695, -24695, -24694, -24694, -24693,
-24692, -24691, -24690, -24688, -24687, -24685, -24683, -24680, -24678, -24675, -24672, -24669, -24666, -24663, -24659, -24656,
-24652, -24648, -24643, -24639, -24634, -24630, -24625, -24620, -24615, -24609, -24604, -24599, -24593, -24587, -24582, -24576,
-24570, -24564, -24558, -24552, -24545, -24539, -24533, -24527, -24520, -24514, -24508, -24502, -24496, -24489, -24483, -24477,
-24471, -24466, -24460, -24454, -24449, -24443, -24438, -24433, -24428, -24423, -24418, -24414, -24410, -24406, -24402, -24398,
-24395, -24391, -24388, -24386, -24383, -24381, -24379, -24377, -24376, -24375, -24374, -24374, -24373, -24373, -24374, -24374,
-24375, -24377, -24378, -24380, -24382, -24385, -24388, -24391, -24394, -24398, -24402, -24406, -24411, -24416, -24421, -24427,
-24432, -24438, -24445, -24451, -24458, -24465, -24472, -24480, -24488, -24496, -24504, -24512, -24520, -24529, -24538, -24547,
-24556, -24565, -24574, -24583, -24593, -24602, -24612, -24621, -24631, -24641, -24650, -24660, -24669, -24679, -24688, -24697,
-24706, -24715, -24724, -24733, -24742, -24750, -24759, -24767, -24775, -24782, -24790, -24797, -24804, -24810, -24817, -24823,
-24828, -24834, -24839, -24843, -24848, -24852, -24855, -24858, -24861, -24864, -24866, -24867, -24868, -24869, -24869, -24869,
-24869, -24868, -24866, -24864, -24862, -24859, -24856, -24852, -24848, -24844, -24839, -24834, -24828, -24822, -24815, -24808,
-24800, -24793, -24784, -24776, -24767, -24758, -24748, -24738, -24728, -24717, -24706, -24695, -24684, -24672, -24660, -24648,
-24636, -24623, -24611, -24598, -24585, -24572, -24559, -24546, -24533, -24520, -24506, -24493, -24480, -24467, -24454, -24441,
-24428, -24415, -24402, -24390, -24377, -24365, -24354, -24342, -24331, -24320, -24309, -24298, -24288, -24279, -24269, -24260,
-24252, -24243, -24236, -24228, -24222, -24215, -24210, -24204, -24199, -24195, -24191, -24188, -24186, -24183, -24182, -24181,
-24181, -24181, -24182, -24183, -24185, -24188, -24191, -24194, -24199, -24204, -24209, -24215, -24222, -24229, -24237, -24245,
-24254, -24264, -24274, -24284, -24295, -24307, -24319, -24331, -24344, -24357, -24371, -24385, -24399, -24414, -24429, -24445,
-24461, -24477, -24493, -24510, -24526, -24543, -24560, -24577, -24595, -24612, -24630, -24647, -24665, -24682, -24700, -24717,
-24734, -24751, -24768, -24785, -24802, -24818, -24834, -24850, -24866, -24881, -24896, -24910, -24924, -24938, -24951, -24964,
-24976, -24988, -24999, -25010, -25020, -25029, -25038, -25046, -25054, -25061, -25067, -25072, -25077, -25081, -25085, -25087,
-25089, -25091, -25091, -25091, -25090, -25088, -25085, -25082, -25077, -25073, -25067, -25060, -25053, -25045, -25036, -25027,
-25017, -25006, -24994, -24982, -24969, -24955, -24941, -24926, -24910, -24894, -24878, -24860, -24842, -24824, -24805, -24786,
-24766, -24746, -24726, -24705, -24684, -24663, -24641, -24619, -24597, -24575, -24552, -24530, -24507, -24485, -24462, -24440,
-24417, -24395, -24372, -24350, -24328, -24307, -24285, -24264, -24243, -24223, -24203, -24183, -24164, -24145, -24127, -24110,
-24093, -24076, -24061, -24046, -24031, -24018, -24005, -23993, -23981, -23971, -23961, -23952, -23944, -23937, -23931, -23926,
-23922, -23918, -23916, -23914, -23914, -23914, -23916, -23918, -23922, -23926, -23932, -23938, -23946, -23954, -23964, -23974,
-23985, -23997, -24011, -24025, -24040, -24056, -24073, -24090, -24109, -24128, -24148, -24169, -24190, -24213, -24236, -24259,
-24283, -24308, -24334, -24359, -24386, -24413, -24440, -24467, -24495, -24523, -24552, -24581, -24609, -24638, -24667, -24697,
-24726, -24755, -24784, -24813, -24841, -24870, -24898, -24926, -24953, -24980, -25007, -25034, -25059, -25084, -25109, -25133,
-25156, -25179, -25201, -25222, -25242, -25261, -25280, -25297, -25314, -25329, -25344, -25357, -25370, -25381, -25391, -25400,
-25408, -25415, -25420, -25425, -25428, -25429, -25430, -25429, -25427, -25424, -25419, -25413, -25406, -25398, -25388, -25377,
-25365, -25351, -25336, -25320, -25303, -25285, -25265, -25244, -25223, -25200, -25176, -25150, -25124, -25097, -25069, -25040,
-25010, -24980, -24948, -24916, -24883, -24849, -24815, -24780, -24745, -24709, -24672, -24635, -24598, -24561, -24523, -24486,
-24448, -24410, -24372, -24334, -24296, -24258, -24221, -24184, -24147, -24111, -24075, -24039, -24004, -23970, -23936, -23903,
-23871, -23840, -23809, -23780, -23751, -23724, -23697, -23672, -23648, -23625, -23603, -23583, -23564, -23546, -23530, -23515,
-23502, -23490, -23480, -23471, -23464, -23459, -23455, -23453, -23452, -23453, -23456, -23461, -23467, -23475, -23485, -23496,
-23509, -23524, -23540, -23558, -23578, -23599, -23622, -23647, -23673, -23701, -23730, -23761, -23793, -23826, -23861, -23898,
-23935, -23974, -24014, -24055, -24098, -24141, -24185, -24230, -24277, -24323, -24371, -24419, -24468, -24518, -24568, -24618,
-24669, -24720, -24771, -24822, -24873, -24925, -24976, -25027, -25077, -25128, -25178, -25227, -25276, -25324, -25371, -25418,
-25464, -25509, -25552, -25595, -25636, -25677, -25715, -25753, -25789, -25824, -25856, -25888, -25917, -25945, -25971, -25995,
-26017, -26038, -26056, -26072, -26086, -26098, -26107, -26115, -26120, -26123, -26123, -26121, -26117, -26111, -26102, -26091,
-26077, -26061, -26043, -26022, -25999, -25973, -25945, -25915, -25883, -25848, -25811, -25772, -25730, -25687, -25641, -25593,
-25543, -25492, -25438, -25383, -25326, -25267, -25207, -25145, -25081, -25016, -24950, -24883, -24815, -24745, -24675, -24603,
-24531, -24458, -24385, -24311, -24237, -24163, -24088, -24014, -23939, -23865, -23791, -23717, -23644, -23572, -23500, -23429,
-23360, -23291, -23224, -23157, -23093, -23030, -22968, -22908, -22851, -22795, -22741, -22690, -22640, -22594, -22549, -22508,
-22469, -22432, -22399, -22369, -22341, -22317, -22296, -22278, -22264, -22253, -22245, -22241, -22240, -22243, -22250, -22261,
-22275, -22292, -22314, -22339, -22368, -22401, -22438, -22479, -22523, -22571, -22623, -22678, -22738, -22801, -22867, -22938,
-23011, -23088, -23169, -23253, -23340, -23430, -23524, -23620, -23719, -23822, -23926, -24034, -24144, -24256, -24370, -24487,
-24605, -24725, -24847, -24970, -25094, -25220, -25347, -25474, -25602, -25731, -25860, -25989, -26118, -26246, -26374, -26502,
-26628, -26753, -26877, -27000, -27121, -27240, -27356, -27471, -27582, -27691, -27797, -27900, -27999, -28095, -28186, -28274,
-28357, -28436, -28509, -28578, -28642, -28700, -28753, -28800, -28841, -28875, -28903, -28925, -28940, -28947, -28948, -28941,
-28927, -28905, -28875, -28837, -28791, -28737, -28674, -28602, -28522, -28432, -28334, -28227, -28110, -27984, -27849, -27704,
-27549, -27385, -27211, -27027, -26833, -26629, -26416, -26192, -25959, -25715, -25461, -25198, -24924, -24640, -24346, -24043,
-23729, -23406, -23073, -22730, -22377, -22015, -21643, -21262, -20872, -20472, -20063, -19646, -19220, -18785, -18341, -17889,
-17429, -16961, -16486, -16002, -15511, -15013, -14508, -13996, -13477, -12953, -12421, -11884, -11342, -10794, -10240, -9682,
-9119, -8552, -7980, -7405, -6826, -6243, -5658, -5070, -4479, -3887, -3292, -2696, -2098, -1499, -900, -300,
300
} ;
*/

+ 4
- 0
keywords.txt Visa fil

@@ -252,6 +252,10 @@ WAVEFORM_PULSE LITERAL1
WAVEFORM_SAWTOOTH_REVERSE LITERAL1
WAVEFORM_SAMPLE_HOLD LITERAL1
WAVEFORM_TRIANGLE_VARIABLE LITERAL1
WAVEFORM_BANDLIMIT_SAWTOOTH LITERAL1
WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE LITERAL1
WAVEFORM_BANDLIMIT_SQUARE LITERAL1
WAVEFORM_BANDLIMIT_PULSE LITERAL1

AUDIO_MEMORY_23LC1024 LITERAL1
AUDIO_MEMORY_MEMORYBOARD LITERAL1

+ 361
- 0
synth_waveform.cpp Visa fil

@@ -32,6 +32,8 @@

// uncomment for more accurate but more computationally expensive frequency modulation
//#define IMPROVE_EXPONENTIAL_ACCURACY
#define BASE_AMPLITUDE 0x6000 // 0x7fff won't work due to Gibb's phenomenon, so use 3/4 of full range.



void AudioSynthWaveform::update(void)
@@ -102,6 +104,16 @@ void AudioSynthWaveform::update(void)
}
break;

case WAVEFORM_BANDLIMIT_SQUARE:
for (int i = 0 ; i < AUDIO_BLOCK_SAMPLES ; i++)
{
uint32_t new_ph = ph + inc ;
int16_t val = band_limit_waveform.generate_square (new_ph, i) ;
*bp++ = (val * magnitude) >> 16 ;
ph = new_ph ;
}
break;

case WAVEFORM_SAWTOOTH:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = signed_multiply_32x16t(magnitude, ph);
@@ -116,6 +128,20 @@ void AudioSynthWaveform::update(void)
}
break;

case WAVEFORM_BANDLIMIT_SAWTOOTH:
case WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE:
for (i = 0 ; i < AUDIO_BLOCK_SAMPLES; i++)
{
uint32_t new_ph = ph + inc ;
int16_t val = band_limit_waveform.generate_sawtooth (new_ph, i) ;
if (tone_type == WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE)
*bp++ = (val * -magnitude) >> 16 ;
else
*bp++ = (val * magnitude) >> 16 ;
ph = new_ph ;
}
break;

case WAVEFORM_TRIANGLE:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
uint32_t phtop = ph >> 30;
@@ -160,6 +186,16 @@ void AudioSynthWaveform::update(void)
}
break;

case WAVEFORM_BANDLIMIT_PULSE:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++)
{
int32_t new_ph = ph + inc ;
int32_t val = band_limit_waveform.generate_pulse (new_ph, pulse_width, i) ;
*bp++ = (int16_t) ((val * magnitude) >> 16) ;
ph = new_ph ;
}
break;

case WAVEFORM_SAMPLE_HOLD:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = sample;
@@ -223,6 +259,7 @@ void AudioSynthWaveformModulated::update(void)
// exp2 algorithm by Laurent de Soras
// https://www.musicdsp.org/en/latest/Other/106-fast-exp2-approximation.html
n = (n + 134217728) << 3;

n = multiply_32x32_rshift32_rounded(n, n);
n = multiply_32x32_rshift32_rounded(n, 715827883) << 3;
n = n + 715827882;
@@ -330,6 +367,26 @@ void AudioSynthWaveformModulated::update(void)
}
break;

case WAVEFORM_BANDLIMIT_PULSE:
if (shapedata)
{
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++)
{
uint32_t width = ((shapedata->data[i] + 0x8000) & 0xFFFF) << 16;
int32_t val = band_limit_waveform.generate_pulse (phasedata[i], width, i) ;
*bp++ = (int16_t) ((val * magnitude) >> 16) ;
}
break;
} // else fall through to orginary square without shape modulation

case WAVEFORM_BANDLIMIT_SQUARE:
for (i = 0 ; i < AUDIO_BLOCK_SAMPLES ; i++)
{
int32_t val = band_limit_waveform.generate_square (phasedata[i], i) ;
*bp++ = (int16_t) ((val * magnitude) >> 16) ;
}
break;

case WAVEFORM_SAWTOOTH:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = signed_multiply_32x16t(magnitude, phasedata[i]);
@@ -342,6 +399,16 @@ void AudioSynthWaveformModulated::update(void)
}
break;

case WAVEFORM_BANDLIMIT_SAWTOOTH:
case WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE:
for (i = 0 ; i < AUDIO_BLOCK_SAMPLES ; i++)
{
int16_t val = band_limit_waveform.generate_sawtooth (phasedata[i], i) ;
val = (int16_t) ((val * magnitude) >> 16) ;
*bp++ = tone_type == WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE ? (int16_t) -val : (int16_t) +val ;
}
break;

case WAVEFORM_TRIANGLE_VARIABLE:
if (shapedata) {
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
@@ -403,3 +470,297 @@ void AudioSynthWaveformModulated::update(void)
}


// BandLimitedWaveform


#define SUPPORT_SHIFT 4
#define SUPPORT (1 << SUPPORT_SHIFT)
#define PTRMASK ((2 << SUPPORT_SHIFT) - 1)

#define SCALE 16
#define SCALE_MASK (SCALE-1)
#define N (SCALE * SUPPORT * 2)

#define GUARD_BITS 8
#define GUARD (1 << GUARD_BITS)
#define HALF_GUARD (1 << (GUARD_BITS-1))


#define DEG180 0x80000000u

#define PHASE_SCALE (0x100000000L / (2 * BASE_AMPLITUDE))


extern "C"
{
extern const int16_t step_table [258] ;
}

int32_t BandLimitedWaveform::lookup (int offset)
{
int off = offset >> GUARD_BITS ;
int frac = offset & (GUARD-1) ;

int32_t a, b ;
if (off < N/2) // handle odd symmetry by reflecting table
{
a = step_table [off+1] ;
b = step_table [off+2] ;
}
else
{
a = - step_table [N-off] ;
b = - step_table [N-off-1] ;
}
return BASE_AMPLITUDE + ((frac * b + (GUARD - frac) * a + HALF_GUARD) >> GUARD_BITS) ; // interpolated
}

// create a new step, apply its past waveform into the cyclic sample buffer
// and add a step_state object into active list so it can be added for the future samples
void BandLimitedWaveform::insert_step (int offset, bool rising, int i)
{
while (offset <= (N/2-SCALE)<<GUARD_BITS)
{
if (offset >= 0)
cyclic [i & 15] += rising ? lookup (offset) : -lookup (offset) ;
offset += SCALE<<GUARD_BITS ;
i ++ ;
}

states[newptr].offset = offset ;
states[newptr].positive = rising ;
newptr = (newptr+1) & PTRMASK ;
}

// generate value for current sample from one active step, checking for the
// dc_offset adjustment at the end of the table.
int32_t BandLimitedWaveform::process_step (int i)
{
int off = states[i].offset ;
bool positive = states[i].positive ;

int32_t entry = lookup (off) ;
off += SCALE<<GUARD_BITS ;
states[i].offset = off ; // update offset in table for next sample
if (off >= N<<GUARD_BITS) // at end of step table we alter dc_offset to extend the step into future
dc_offset += positive ? 2*BASE_AMPLITUDE : -2*BASE_AMPLITUDE ;

return positive ? entry : -entry ;
}

// process all active steps for current sample, basically generating the waveform portion
// due only to steps
// square waves use this directly.
int32_t BandLimitedWaveform::process_active_steps (uint32_t new_phase)
{
int32_t sample = dc_offset ;
int step_count = (newptr - delptr) & PTRMASK ;
if (step_count > 0) // for any steps in-flight we sum in table entry and update its state
{
int i = newptr ;
do
{
i = (i-1) & PTRMASK ;
sample += process_step (i) ;
} while (i != delptr) ;
if (states[delptr].offset >= N<<GUARD_BITS) // remove any finished entries from the buffer.
{
delptr = (delptr+1) & PTRMASK ;
// can be upto two steps per sample now for pulses
if (newptr != delptr && states[delptr].offset >= N<<GUARD_BITS)
delptr = (delptr+1) & PTRMASK ;
}
}
return sample ;
}

// for sawtooth need to add in the slope and compensate for all the steps being one way
int32_t BandLimitedWaveform::process_active_steps_saw (uint32_t new_phase)
{
int32_t sample = process_active_steps (new_phase) ;

sample += (int16_t) ((((uint64_t)phase_word * (2*BASE_AMPLITUDE)) >> 32) - BASE_AMPLITUDE) ; // generate the sloped part of the wave

if (new_phase < DEG180 && phase_word >= DEG180) // detect wrap around, correct dc offset
dc_offset += 2*BASE_AMPLITUDE ;

return sample ;
}

// for pulse need to adjust the baseline according to the pulse width to cancel the DC component.
int32_t BandLimitedWaveform::process_active_steps_pulse (uint32_t new_phase, uint32_t pulse_width)
{
int32_t sample = process_active_steps (new_phase) ;

return sample + BASE_AMPLITUDE/2 - pulse_width / (0x80000000u / BASE_AMPLITUDE) ; // correct DC offset for duty cycle
}

// Check for new steps using the phase update for the current sample for a square wave
void BandLimitedWaveform::new_step_check_square (uint32_t new_phase, int i)
{
if (new_phase >= DEG180 && phase_word < DEG180) // detect falling step
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (sampled_width - phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
if (pulse_state) // guard against two falling steps in a row (if pulse width changing for instance)
{
insert_step (- offset, false, i) ;
pulse_state = false ;
}
}
else if (new_phase < DEG180 && phase_word >= DEG180) // detect wrap around, rising step
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (- phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
if (!pulse_state) // guard against two rising steps in a row (if pulse width changing for instance)
{
insert_step (- offset, true, i) ;
pulse_state = true ;
}
}
}

// Checking for new steps for pulse waveform has to deal with changing frequency and pulse width and
// not letting a pulse glitch out of existence as these change across a single period of the waveform
// now we detect the rising edge just like for a square wave and use that to sample the pulse width
// parameter, which then has to be checked against the instantaneous frequency every sample.
void BandLimitedWaveform::new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i)
{
if (pulse_state && phase_word < sampled_width && (new_phase >= sampled_width || new_phase < phase_word)) // falling edge
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (sampled_width - phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
insert_step (- offset, false, i) ;
pulse_state = false ;
}
if ((!pulse_state) && phase_word >= DEG180 && new_phase < DEG180) // detect wrap around, rising step
{
// sample the pulse width value so its not changing under our feet later in cycle due to modulation
sampled_width = pulse_width ;

int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (- phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
insert_step (- offset, true, i) ;
pulse_state = true ;
if (pulse_state && new_phase >= sampled_width) // detect falling step directly after a rising edge
//if (new_phase - sampled_width < DEG180) // detect falling step directly after a rising edge
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (sampled_width - phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
insert_step (- offset, false, i) ;
pulse_state = false ;
}
}
}

// new steps for sawtooth are at 180 degree point, always falling.
void BandLimitedWaveform::new_step_check_saw (uint32_t new_phase, int i)
{
if (new_phase >= DEG180 && phase_word < DEG180) // detect falling step
{
int32_t offset = (int32_t) ((uint64_t) (SCALE<<GUARD_BITS) * (DEG180 - phase_word) / (new_phase - phase_word)) ;
if (offset == SCALE<<GUARD_BITS)
offset -- ;
insert_step (- offset, false, i) ;
}
}
// the generation function pushd new sample into cyclic buffer, having taken out the oldest entry
// to return. The output is thus 16 samples behind, which allows the non-casual step function to
// work in real time.
int16_t BandLimitedWaveform::generate_sawtooth (uint32_t new_phase, int i)
{
new_step_check_saw (new_phase, i) ;
int32_t val = process_active_steps_saw (new_phase) ;
int16_t sample = (int16_t) cyclic [i&15] ;
cyclic [i&15] = val ;
phase_word = new_phase ;
return sample ;
}

int16_t BandLimitedWaveform::generate_square (uint32_t new_phase, int i)
{
new_step_check_square (new_phase, i) ;
int32_t val = process_active_steps (new_phase) ;
int16_t sample = (int16_t) cyclic [i&15] ;
cyclic [i&15] = val ;
phase_word = new_phase ;
return sample ;
}

int16_t BandLimitedWaveform::generate_pulse (uint32_t new_phase, uint32_t pulse_width, int i)
{
new_step_check_pulse (new_phase, pulse_width, i) ;
int32_t val = process_active_steps_pulse (new_phase, pulse_width) ;
int32_t sample = cyclic [i&15] ;
cyclic [i&15] = val ;
phase_word = new_phase ;
return (int16_t) ((sample >> 1) - (sample >> 5)) ; // scale down to avoid overflow on narrow pulses, where the DC shift is big
}

void BandLimitedWaveform::init_sawtooth (uint32_t freq_word)
{
phase_word = 0 ;
newptr = 0 ;
delptr = 0 ;
for (int i = 0 ; i < 2*SUPPORT ; i++)
phase_word -= freq_word ;
dc_offset = phase_word < DEG180 ? BASE_AMPLITUDE : -BASE_AMPLITUDE ;
for (int i = 0 ; i < 2*SUPPORT ; i++)
{
uint32_t new_phase = phase_word + freq_word ;
new_step_check_saw (new_phase, i) ;
cyclic [i & 15] = (int16_t) process_active_steps_saw (new_phase) ;
phase_word = new_phase ;
}
}


void BandLimitedWaveform::init_square (uint32_t freq_word)
{
init_pulse (freq_word, DEG180) ;
}

void BandLimitedWaveform::init_pulse (uint32_t freq_word, uint32_t pulse_width)
{
phase_word = 0 ;
sampled_width = pulse_width ;
newptr = 0 ;
delptr = 0 ;
for (int i = 0 ; i < 2*SUPPORT ; i++)
phase_word -= freq_word ;

if (phase_word < pulse_width)
{
dc_offset = BASE_AMPLITUDE ;
pulse_state = true ;
}
else
{
dc_offset = -BASE_AMPLITUDE ;
pulse_state = false ;
}
for (int i = 0 ; i < 2*SUPPORT ; i++)
{
uint32_t new_phase = phase_word + freq_word ;
new_step_check_pulse (new_phase, pulse_width, i) ;
cyclic [i & 15] = (int16_t) process_active_steps_pulse (new_phase, pulse_width) ;
phase_word = new_phase ;
}
}

BandLimitedWaveform::BandLimitedWaveform()
{
newptr = 0 ;
delptr = 0 ;
dc_offset = BASE_AMPLITUDE ;
phase_word = 0 ;
}

+ 63
- 2
synth_waveform.h Visa fil

@@ -46,6 +46,53 @@ extern const int16_t AudioWaveformSine[257];
#define WAVEFORM_SAWTOOTH_REVERSE 6
#define WAVEFORM_SAMPLE_HOLD 7
#define WAVEFORM_TRIANGLE_VARIABLE 8
#define WAVEFORM_BANDLIMIT_SAWTOOTH 9
#define WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE 10
#define WAVEFORM_BANDLIMIT_SQUARE 11
#define WAVEFORM_BANDLIMIT_PULSE 12


typedef struct step_state
{
int offset ;
bool positive ;
} step_state ;


class BandLimitedWaveform
{
public:
BandLimitedWaveform (void) ;
int16_t generate_sawtooth (uint32_t new_phase, int i) ;
int16_t generate_square (uint32_t new_phase, int i) ;
int16_t generate_pulse (uint32_t new_phase, uint32_t pulse_width, int i) ;
void init_sawtooth (uint32_t freq_word) ;
void init_square (uint32_t freq_word) ;
void init_pulse (uint32_t freq_word, uint32_t pulse_width) ;

private:
int32_t lookup (int offset) ;
void insert_step (int offset, bool rising, int i) ;
int32_t process_step (int i) ;
int32_t process_active_steps (uint32_t new_phase) ;
int32_t process_active_steps_saw (uint32_t new_phase) ;
int32_t process_active_steps_pulse (uint32_t new_phase, uint32_t pulse_width) ;
void new_step_check_square (uint32_t new_phase, int i) ;
void new_step_check_pulse (uint32_t new_phase, uint32_t pulse_width, int i) ;
void new_step_check_saw (uint32_t new_phase, int i) ;

uint32_t phase_word ;
int32_t dc_offset ;
step_state states [32] ; // circular buffer of active steps
int newptr ; // buffer pointers into states, AND'd with PTRMASK to keep in buffer range.
int delptr ;
int32_t cyclic[16] ; // circular buffer of output samples
bool pulse_state ;
uint32_t sampled_width ; // pulse width is sampled once per waveform
};


class AudioSynthWaveform : public AudioStream
{
@@ -102,12 +149,18 @@ public:
void begin(short t_type) {
phase_offset = 0;
tone_type = t_type;
if (t_type == WAVEFORM_BANDLIMIT_SQUARE)
band_limit_waveform.init_square (phase_increment) ;
else if (t_type == WAVEFORM_BANDLIMIT_PULSE)
band_limit_waveform.init_pulse (phase_increment, pulse_width) ;
else if (t_type == WAVEFORM_BANDLIMIT_SAWTOOTH || t_type == WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE)
band_limit_waveform.init_sawtooth (phase_increment) ;
}
void begin(float t_amp, float t_freq, short t_type) {
amplitude(t_amp);
frequency(t_freq);
phase_offset = 0;
tone_type = t_type;
begin (t_type);
}
void arbitraryWaveform(const int16_t *data, float maxFreq) {
arbdata = data;
@@ -124,6 +177,7 @@ private:
int16_t sample; // for WAVEFORM_SAMPLE_HOLD
short tone_type;
int16_t tone_offset;
BandLimitedWaveform band_limit_waveform ;
};


@@ -163,11 +217,17 @@ public:
}
void begin(short t_type) {
tone_type = t_type;
if (t_type == WAVEFORM_BANDLIMIT_SQUARE)
band_limit_waveform.init_square (phase_increment) ;
else if (t_type == WAVEFORM_BANDLIMIT_PULSE)
band_limit_waveform.init_pulse (phase_increment, 0x80000000u) ;
else if (t_type == WAVEFORM_BANDLIMIT_SAWTOOTH || t_type == WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE)
band_limit_waveform.init_sawtooth (phase_increment) ;
}
void begin(float t_amp, float t_freq, short t_type) {
amplitude(t_amp);
frequency(t_freq);
tone_type = t_type;
begin (t_type) ;
}
void arbitraryWaveform(const int16_t *data, float maxFreq) {
arbdata = data;
@@ -204,6 +264,7 @@ private:
int16_t tone_offset;
uint8_t tone_type;
uint8_t modulation_type;
BandLimitedWaveform band_limit_waveform ;
};



Laddar…
Avbryt
Spara