|
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace Fem {
|
|
|
|
|
|
|
|
class Oscillator {
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const uint32_t NOTELUT[128] = {
|
|
|
|
|
|
|
|
0x000b29a6, 0x000bd392, 0x000c879a, 0x000d4656, 0x000e1069, 0x000ee680, 0x000fc953, 0x0010b9a2,
|
|
|
|
|
|
|
|
0x0011b83c, 0x0012c5f9, 0x0013e3c0, 0x00151285, 0x0016534c, 0x0017a725, 0x00190f34, 0x001a8cac,
|
|
|
|
|
|
|
|
0x001c20d2, 0x001dcd01, 0x001f92a6, 0x00217345, 0x00237078, 0x00258bf2, 0x0027c780, 0x002a250b,
|
|
|
|
|
|
|
|
0x002ca698, 0x002f4e4b, 0x00321e68, 0x00351958, 0x003841a5, 0x003b9a03, 0x003f254d, 0x0042e68a,
|
|
|
|
|
|
|
|
0x0046e0f0, 0x004b17e4, 0x004f8f01, 0x00544a17, 0x00594d30, 0x005e9c96, 0x00643cd1, 0x006a32b0,
|
|
|
|
|
|
|
|
0x0070834b, 0x00773407, 0x007e4a9b, 0x0085cd15, 0x008dc1e0, 0x00962fc9, 0x009f1e02, 0x00a8942e,
|
|
|
|
|
|
|
|
0x00b29a61, 0x00bd392c, 0x00c879a3, 0x00d46561, 0x00e10697, 0x00ee680e, 0x00fc9536, 0x010b9a2a,
|
|
|
|
|
|
|
|
0x011b83c1, 0x012c5f92, 0x013e3c05, 0x0151285c, 0x016534c3, 0x017a7259, 0x0190f346, 0x01a8cac3,
|
|
|
|
|
|
|
|
0x01c20d2e, 0x01dcd01d, 0x01f92a6c, 0x02173455, 0x02370783, 0x0258bf25, 0x027c780b, 0x02a250b9,
|
|
|
|
|
|
|
|
0x02ca6986, 0x02f4e4b3, 0x0321e68d, 0x03519586, 0x03841a5d, 0x03b9a03a, 0x03f254d9, 0x042e68ab,
|
|
|
|
|
|
|
|
0x046e0f06, 0x04b17e4b, 0x04f8f016, 0x0544a173, 0x0594d30d, 0x05e9c967, 0x0643cd1a, 0x06a32b0c,
|
|
|
|
|
|
|
|
0x070834ba, 0x07734074, 0x07e4a9b2, 0x085cd157, 0x08dc1e0d, 0x0962fc96, 0x09f1e02d, 0x0a8942e6,
|
|
|
|
|
|
|
|
0x0b29a61a, 0x0bd392cf, 0x0c879a35, 0x0d465619, 0x0e106974, 0x0ee680e9, 0x0fc95364, 0x10b9a2ae,
|
|
|
|
|
|
|
|
0x11b83c1a, 0x12c5f92c, 0x13e3c05a, 0x151285cd, 0x16534c34, 0x17a7259f, 0x190f346a, 0x1a8cac33,
|
|
|
|
|
|
|
|
0x1c20d2e8, 0x1dcd01d2, 0x1f92a6c8, 0x2173455d, 0x23707834, 0x258bf258, 0x27c780b4, 0x2a250b9b,
|
|
|
|
|
|
|
|
0x2ca69869, 0x2f4e4b3f, 0x321e68d4, 0x35195867, 0x3841a5d0, 0x3b9a03a5, 0x3f254d90, 0x42e68abb
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// lanczos2 kernel LUT
|
|
|
|
|
|
|
|
const int16_t LANCZOS2[512] = {
|
|
|
|
|
|
|
|
0x0, 0x0, -0x1, -0x2, -0x3, -0x4, -0x6, -0x8, -0xa, -0xc, -0xf, -0x12, -0x16, -0x19, -0x1d, -0x21,
|
|
|
|
|
|
|
|
-0x26, -0x2b, -0x30, -0x35, -0x3b, -0x41, -0x47, -0x4d, -0x54, -0x5b, -0x63, -0x6a, -0x73, -0x7b, -0x84, -0x8d,
|
|
|
|
|
|
|
|
-0x96, -0x9f, -0xa9, -0xb3, -0xbe, -0xc9, -0xd4, -0xdf, -0xeb, -0xf7, -0x103, -0x110, -0x11d, -0x12a, -0x138, -0x145,
|
|
|
|
|
|
|
|
-0x154, -0x162, -0x171, -0x180, -0x18f, -0x19f, -0x1af, -0x1bf, -0x1cf, -0x1e0, -0x1f1, -0x202, -0x214, -0x226, -0x238, -0x24a,
|
|
|
|
|
|
|
|
-0x25d, -0x270, -0x283, -0x296, -0x2aa, -0x2be, -0x2d2, -0x2e6, -0x2fb, -0x310, -0x325, -0x33a, -0x350, -0x365, -0x37b, -0x391,
|
|
|
|
|
|
|
|
-0x3a8, -0x3be, -0x3d5, -0x3ec, -0x403, -0x41a, -0x431, -0x449, -0x461, -0x478, -0x490, -0x4a9, -0x4c1, -0x4d9, -0x4f2, -0x50a,
|
|
|
|
|
|
|
|
-0x523, -0x53c, -0x554, -0x56d, -0x586, -0x59f, -0x5b9, -0x5d2, -0x5eb, -0x604, -0x61d, -0x637, -0x650, -0x669, -0x682, -0x69c,
|
|
|
|
|
|
|
|
-0x6b5, -0x6ce, -0x6e7, -0x700, -0x719, -0x732, -0x74b, -0x764, -0x77d, -0x795, -0x7ae, -0x7c6, -0x7de, -0x7f7, -0x80e, -0x826,
|
|
|
|
|
|
|
|
-0x83e, -0x855, -0x86c, -0x883, -0x89a, -0x8b1, -0x8c7, -0x8dd, -0x8f3, -0x909, -0x91e, -0x933, -0x948, -0x95c, -0x970, -0x984,
|
|
|
|
|
|
|
|
-0x997, -0x9aa, -0x9bd, -0x9cf, -0x9e1, -0x9f3, -0xa04, -0xa14, -0xa25, -0xa34, -0xa44, -0xa53, -0xa61, -0xa6f, -0xa7c, -0xa89,
|
|
|
|
|
|
|
|
-0xa96, -0xaa2, -0xaad, -0xab8, -0xac2, -0xacc, -0xad5, -0xadd, -0xae5, -0xaec, -0xaf3, -0xaf9, -0xafe, -0xb03, -0xb07, -0xb0a,
|
|
|
|
|
|
|
|
-0xb0d, -0xb0e, -0xb10, -0xb10, -0xb10, -0xb0e, -0xb0d, -0xb0a, -0xb07, -0xb02, -0xafd, -0xaf7, -0xaf1, -0xae9, -0xae1, -0xad8,
|
|
|
|
|
|
|
|
-0xace, -0xac3, -0xab7, -0xaaa, -0xa9c, -0xa8e, -0xa7e, -0xa6e, -0xa5c, -0xa4a, -0xa36, -0xa22, -0xa0d, -0x9f7, -0x9df, -0x9c7,
|
|
|
|
|
|
|
|
-0x9ae, -0x993, -0x978, -0x95b, -0x93e, -0x91f, -0x8ff, -0x8df, -0x8bd, -0x89a, -0x876, -0x851, -0x82a, -0x803, -0x7da, -0x7b1,
|
|
|
|
|
|
|
|
-0x786, -0x75a, -0x72d, -0x6fe, -0x6cf, -0x69e, -0x66c, -0x639, -0x605, -0x5d0, -0x599, -0x561, -0x528, -0x4ee, -0x4b2, -0x475,
|
|
|
|
|
|
|
|
-0x437, -0x3f8, -0x3b8, -0x376, -0x333, -0x2ef, -0x2a9, -0x263, -0x21b, -0x1d2, -0x187, -0x13b, -0xee, -0xa0, -0x50, 0x0,
|
|
|
|
|
|
|
|
0x52, 0xa5, 0xfa, 0x150, 0x1a7, 0x1ff, 0x259, 0x2b4, 0x310, 0x36e, 0x3cd, 0x42d, 0x48e, 0x4f1, 0x555, 0x5ba,
|
|
|
|
|
|
|
|
0x621, 0x688, 0x6f1, 0x75c, 0x7c7, 0x834, 0x8a2, 0x911, 0x981, 0x9f3, 0xa66, 0xada, 0xb4f, 0xbc6, 0xc3e, 0xcb7,
|
|
|
|
|
|
|
|
0xd31, 0xdac, 0xe29, 0xea6, 0xf25, 0xfa5, 0x1026, 0x10a8, 0x112c, 0x11b0, 0x1236, 0x12bd, 0x1345, 0x13ce, 0x1458, 0x14e3,
|
|
|
|
|
|
|
|
0x156f, 0x15fc, 0x168b, 0x171a, 0x17aa, 0x183c, 0x18ce, 0x1962, 0x19f6, 0x1a8b, 0x1b22, 0x1bb9, 0x1c51, 0x1cea, 0x1d84, 0x1e1f,
|
|
|
|
|
|
|
|
0x1ebb, 0x1f58, 0x1ff5, 0x2094, 0x2133, 0x21d3, 0x2274, 0x2315, 0x23b8, 0x245b, 0x24ff, 0x25a3, 0x2649, 0x26ef, 0x2796, 0x283d,
|
|
|
|
|
|
|
|
0x28e5, 0x298e, 0x2a37, 0x2ae1, 0x2b8c, 0x2c37, 0x2ce2, 0x2d8e, 0x2e3b, 0x2ee8, 0x2f96, 0x3044, 0x30f3, 0x31a2, 0x3251, 0x3301,
|
|
|
|
|
|
|
|
0x33b2, 0x3462, 0x3513, 0x35c4, 0x3676, 0x3728, 0x37da, 0x388c, 0x393f, 0x39f2, 0x3aa5, 0x3b58, 0x3c0b, 0x3cbf, 0x3d72, 0x3e26,
|
|
|
|
|
|
|
|
0x3eda, 0x3f8d, 0x4041, 0x40f5, 0x41a9, 0x425d, 0x4310, 0x43c4, 0x4478, 0x452b, 0x45de, 0x4692, 0x4745, 0x47f7, 0x48aa, 0x495c,
|
|
|
|
|
|
|
|
0x4a0e, 0x4ac0, 0x4b72, 0x4c23, 0x4cd4, 0x4d84, 0x4e34, 0x4ee4, 0x4f93, 0x5042, 0x50f0, 0x519e, 0x524b, 0x52f8, 0x53a4, 0x5450,
|
|
|
|
|
|
|
|
0x54fb, 0x55a6, 0x564f, 0x56f9, 0x57a1, 0x5849, 0x58f0, 0x5996, 0x5a3c, 0x5ae0, 0x5b84, 0x5c28, 0x5cca, 0x5d6b, 0x5e0c, 0x5eab,
|
|
|
|
|
|
|
|
0x5f4a, 0x5fe8, 0x6085, 0x6120, 0x61bb, 0x6255, 0x62ee, 0x6385, 0x641c, 0x64b1, 0x6546, 0x65d9, 0x666b, 0x66fc, 0x678b, 0x681a,
|
|
|
|
|
|
|
|
0x68a7, 0x6933, 0x69bd, 0x6a47, 0x6acf, 0x6b56, 0x6bdb, 0x6c5f, 0x6ce1, 0x6d63, 0x6de3, 0x6e61, 0x6ede, 0x6f59, 0x6fd3, 0x704c,
|
|
|
|
|
|
|
|
0x70c3, 0x7138, 0x71ac, 0x721e, 0x728f, 0x72fe, 0x736c, 0x73d8, 0x7442, 0x74ab, 0x7512, 0x7577, 0x75db, 0x763d, 0x769d, 0x76fb,
|
|
|
|
|
|
|
|
0x7758, 0x77b3, 0x780c, 0x7864, 0x78b9, 0x790d, 0x795f, 0x79af, 0x79fe, 0x7a4a, 0x7a95, 0x7ade, 0x7b25, 0x7b6a, 0x7bad, 0x7bee,
|
|
|
|
|
|
|
|
0x7c2d, 0x7c6b, 0x7ca6, 0x7ce0, 0x7d17, 0x7d4d, 0x7d81, 0x7db2, 0x7de2, 0x7e10, 0x7e3b, 0x7e65, 0x7e8d, 0x7eb3, 0x7ed6, 0x7ef8,
|
|
|
|
|
|
|
|
0x7f18, 0x7f35, 0x7f51, 0x7f6b, 0x7f82, 0x7f98, 0x7fab, 0x7fbd, 0x7fcc, 0x7fda, 0x7fe5, 0x7fee, 0x7ff5, 0x7ffa, 0x7ffd, 0x7fff
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 4-point lanczos2 resampling filter
|
|
|
|
|
|
|
|
int16_t lanczos(uint32_t pitchAcc, int16_t* waveSample) {
|
|
|
|
|
|
|
|
uint32_t sampleIndex = pitchAcc >> 21;
|
|
|
|
|
|
|
|
uint32_t sampleError = (pitchAcc >> 13) & 0x000000ff;
|
|
|
|
|
|
|
|
int32_t filteredSample = waveSample[sampleIndex] * LANCZOS2[255 - sampleError];
|
|
|
|
|
|
|
|
filteredSample += (waveSample[(sampleIndex + 1) & 0x000007ff] * LANCZOS2[511 - sampleError]);
|
|
|
|
|
|
|
|
filteredSample += (waveSample[(sampleIndex + 2) & 0x000007ff] * LANCZOS2[256 + sampleError]);
|
|
|
|
|
|
|
|
filteredSample += (waveSample[(sampleIndex + 3) & 0x000007ff] * LANCZOS2[sampleError]);
|
|
|
|
|
|
|
|
filteredSample /= 32768; // should actually be /= 32767 but who's counting
|
|
|
|
|
|
|
|
return (int16_t)filteredSample;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// linear interpolation of two samples
|
|
|
|
|
|
|
|
int16_t lerp(int16_t a, int16_t b, uint16_t t) {
|
|
|
|
|
|
|
|
int32_t lerpSum = (int32_t)(0x2000 - t) * (int32_t)a;
|
|
|
|
|
|
|
|
lerpSum += (int32_t)t * (int32_t)b;
|
|
|
|
|
|
|
|
return (int16_t)(lerpSum / 0x2000);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Oscillator() {
|
|
|
|
|
|
|
|
this->pitchAcc = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t pitchAcc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void reset() {
|
|
|
|
|
|
|
|
pitchAcc = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int16_t gen(uint8_t note, uint16_t wavePos, int16_t** waveTable) {
|
|
|
|
|
|
|
|
// pitchAcc += noteFrequency(note);
|
|
|
|
|
|
|
|
pitchAcc += NOTELUT[note];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// interpolate between two waves in the wavetable
|
|
|
|
|
|
|
|
uint8_t waveIndex = wavePos >> 13;
|
|
|
|
|
|
|
|
int16_t* waveA = waveTable[waveIndex];
|
|
|
|
|
|
|
|
int16_t* waveB = waveTable[(waveIndex + 1) & 0x07];
|
|
|
|
|
|
|
|
int16_t sampleA = lanczos(pitchAcc, waveA);
|
|
|
|
|
|
|
|
int16_t sampleB = lanczos(pitchAcc, waveB);
|
|
|
|
|
|
|
|
return lerp (sampleA, sampleB, wavePos & 0x1fff);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|