mirror of
https://github.com/opentx/opentx.git
synced 2025-07-24 16:55:20 +03:00
Merge pull request #738 from opentx/bsongis/vario_improvements
Bsongis/vario improvements
This commit is contained in:
commit
32bcb8b5d6
14 changed files with 582 additions and 364 deletions
|
@ -462,6 +462,9 @@ class GeneralSettings {
|
|||
int beepVolume;
|
||||
int wavVolume;
|
||||
int varioVolume;
|
||||
int varioPitch;
|
||||
int varioRange;
|
||||
int varioRepeat;
|
||||
int backgroundVolume;
|
||||
unsigned int mavbaud;
|
||||
unsigned int switchUnlockStates;
|
||||
|
|
|
@ -2379,6 +2379,11 @@ Open9xGeneralDataNew::Open9xGeneralDataNew(GeneralSettings & generalData, BoardE
|
|||
internalField.Append(new SignedField<8>(generalData.beepVolume));
|
||||
internalField.Append(new SignedField<8>(generalData.wavVolume));
|
||||
internalField.Append(new SignedField<8>(generalData.varioVolume));
|
||||
if (version >= 216) {
|
||||
internalField.Append(new SignedField<8>(generalData.varioPitch));
|
||||
internalField.Append(new SignedField<8>(generalData.varioRange));
|
||||
internalField.Append(new SignedField<8>(generalData.varioRepeat));
|
||||
}
|
||||
internalField.Append(new SignedField<8>(generalData.backgroundVolume));
|
||||
}
|
||||
if (IS_TARANIS(board) && version >= 216) {
|
||||
|
|
|
@ -41,24 +41,111 @@ extern OS_MutexID audioMutex;
|
|||
|
||||
const int16_t sineValues[] =
|
||||
{
|
||||
0, 64, 128, 191, 254, 316, 376, 435, 493, 548,
|
||||
601, 652, 700, 746, 789, 828, 864, 897, 926, 952,
|
||||
973, 991, 1005, 1015, 1021, 1024, 1021, 1015, 1005, 991,
|
||||
973, 952, 926, 897, 864, 828, 789, 746, 700, 652,
|
||||
601, 548, 493, 435, 376, 316, 254, 191, 128, 64,
|
||||
0, -64, -128, -191, -254, -316, -376, -435, -493, -548,
|
||||
-601, -652, -700, -746, -789, -828, -864, -897, -926, -952,
|
||||
-973, -991, -1005, -1015, -1021, -1024, -1021, -1015, -1005, -991,
|
||||
-973, -952, -926, -897, -864, -828, -789, -746, -700, -652,
|
||||
-601, -548, -493, -435, -376, -316, -254, -191, -128, -64,
|
||||
0, 196, 392, 588, 784, 980, 1175, 1370, 1564, 1758,
|
||||
1951, 2143, 2335, 2525, 2715, 2904, 3091, 3278, 3463, 3647,
|
||||
3829, 4011, 4190, 4369, 4545, 4720, 4894, 5065, 5235, 5403,
|
||||
5569, 5733, 5895, 6055, 6213, 6369, 6522, 6673, 6822, 6969,
|
||||
7113, 7255, 7395, 7532, 7667, 7799, 7929, 8056, 8180, 8302,
|
||||
8422, 8539, 8653, 8765, 8874, 8980, 9084, 9185, 9283, 9379,
|
||||
9472, 9562, 9650, 9735, 9818, 9898, 9975, 10050, 10123, 10192,
|
||||
10260, 10324, 10387, 10447, 10504, 10559, 10612, 10663, 10711, 10757,
|
||||
10801, 10843, 10882, 10920, 10955, 10989, 11020, 11050, 11078, 11104,
|
||||
11128, 11151, 11172, 11191, 11209, 11225, 11240, 11254, 11266, 11277,
|
||||
11287, 11296, 11303, 11310, 11316, 11320, 11324, 11327, 11330, 11331,
|
||||
11332, 11333, 11333, 11333, 11332, 11331, 11329, 11328, 11326, 11324,
|
||||
11323, 11321, 11319, 11318, 11316, 11315, 11314, 11313, 11313, 11313,
|
||||
11314, 11315, 11317, 11319, 11323, 11326, 11331, 11336, 11342, 11349,
|
||||
11356, 11365, 11375, 11385, 11397, 11409, 11423, 11437, 11453, 11470,
|
||||
11488, 11507, 11527, 11548, 11571, 11595, 11620, 11646, 11673, 11702,
|
||||
11732, 11763, 11795, 11828, 11863, 11899, 11936, 11974, 12013, 12054,
|
||||
12095, 12138, 12182, 12227, 12273, 12320, 12368, 12417, 12467, 12518,
|
||||
12570, 12623, 12676, 12731, 12786, 12842, 12898, 12956, 13014, 13072,
|
||||
13131, 13191, 13251, 13311, 13372, 13433, 13495, 13556, 13618, 13680,
|
||||
13743, 13805, 13867, 13929, 13991, 14053, 14115, 14177, 14238, 14299,
|
||||
14359, 14419, 14479, 14538, 14597, 14655, 14712, 14768, 14824, 14879,
|
||||
14933, 14986, 15039, 15090, 15140, 15189, 15237, 15284, 15330, 15375,
|
||||
15418, 15460, 15500, 15539, 15577, 15614, 15648, 15682, 15714, 15744,
|
||||
15772, 15799, 15825, 15849, 15871, 15891, 15910, 15927, 15942, 15955,
|
||||
15967, 15977, 15985, 15991, 15996, 15999, 16000, 15999, 15996, 15991,
|
||||
15985, 15977, 15967, 15955, 15942, 15927, 15910, 15891, 15871, 15849,
|
||||
15825, 15799, 15772, 15744, 15714, 15682, 15648, 15614, 15577, 15539,
|
||||
15500, 15460, 15418, 15375, 15330, 15284, 15237, 15189, 15140, 15090,
|
||||
15039, 14986, 14933, 14879, 14824, 14768, 14712, 14655, 14597, 14538,
|
||||
14479, 14419, 14359, 14299, 14238, 14177, 14115, 14053, 13991, 13929,
|
||||
13867, 13805, 13743, 13680, 13618, 13556, 13495, 13433, 13372, 13311,
|
||||
13251, 13191, 13131, 13072, 13014, 12956, 12898, 12842, 12786, 12731,
|
||||
12676, 12623, 12570, 12518, 12467, 12417, 12368, 12320, 12273, 12227,
|
||||
12182, 12138, 12095, 12054, 12013, 11974, 11936, 11899, 11863, 11828,
|
||||
11795, 11763, 11732, 11702, 11673, 11646, 11620, 11595, 11571, 11548,
|
||||
11527, 11507, 11488, 11470, 11453, 11437, 11423, 11409, 11397, 11385,
|
||||
11375, 11365, 11356, 11349, 11342, 11336, 11331, 11326, 11323, 11319,
|
||||
11317, 11315, 11314, 11313, 11313, 11313, 11314, 11315, 11316, 11318,
|
||||
11319, 11321, 11323, 11324, 11326, 11328, 11329, 11331, 11332, 11333,
|
||||
11333, 11333, 11332, 11331, 11330, 11327, 11324, 11320, 11316, 11310,
|
||||
11303, 11296, 11287, 11277, 11266, 11254, 11240, 11225, 11209, 11191,
|
||||
11172, 11151, 11128, 11104, 11078, 11050, 11020, 10989, 10955, 10920,
|
||||
10882, 10843, 10801, 10757, 10711, 10663, 10612, 10559, 10504, 10447,
|
||||
10387, 10324, 10260, 10192, 10123, 10050, 9975, 9898, 9818, 9735,
|
||||
9650, 9562, 9472, 9379, 9283, 9185, 9084, 8980, 8874, 8765,
|
||||
8653, 8539, 8422, 8302, 8180, 8056, 7929, 7799, 7667, 7532,
|
||||
7395, 7255, 7113, 6969, 6822, 6673, 6522, 6369, 6213, 6055,
|
||||
5895, 5733, 5569, 5403, 5235, 5065, 4894, 4720, 4545, 4369,
|
||||
4190, 4011, 3829, 3647, 3463, 3278, 3091, 2904, 2715, 2525,
|
||||
2335, 2143, 1951, 1758, 1564, 1370, 1175, 980, 784, 588,
|
||||
392, 196, 0, -196, -392, -588, -784, -980, -1175, -1370,
|
||||
-1564, -1758, -1951, -2143, -2335, -2525, -2715, -2904, -3091, -3278,
|
||||
-3463, -3647, -3829, -4011, -4190, -4369, -4545, -4720, -4894, -5065,
|
||||
-5235, -5403, -5569, -5733, -5895, -6055, -6213, -6369, -6522, -6673,
|
||||
-6822, -6969, -7113, -7255, -7395, -7532, -7667, -7799, -7929, -8056,
|
||||
-8180, -8302, -8422, -8539, -8653, -8765, -8874, -8980, -9084, -9185,
|
||||
-9283, -9379, -9472, -9562, -9650, -9735, -9818, -9898, -9975, -10050,
|
||||
-10123, -10192, -10260, -10324, -10387, -10447, -10504, -10559, -10612, -10663,
|
||||
-10711, -10757, -10801, -10843, -10882, -10920, -10955, -10989, -11020, -11050,
|
||||
-11078, -11104, -11128, -11151, -11172, -11191, -11209, -11225, -11240, -11254,
|
||||
-11266, -11277, -11287, -11296, -11303, -11310, -11316, -11320, -11324, -11327,
|
||||
-11330, -11331, -11332, -11333, -11333, -11333, -11332, -11331, -11329, -11328,
|
||||
-11326, -11324, -11323, -11321, -11319, -11318, -11316, -11315, -11314, -11313,
|
||||
-11313, -11313, -11314, -11315, -11317, -11319, -11323, -11326, -11331, -11336,
|
||||
-11342, -11349, -11356, -11365, -11375, -11385, -11397, -11409, -11423, -11437,
|
||||
-11453, -11470, -11488, -11507, -11527, -11548, -11571, -11595, -11620, -11646,
|
||||
-11673, -11702, -11732, -11763, -11795, -11828, -11863, -11899, -11936, -11974,
|
||||
-12013, -12054, -12095, -12138, -12182, -12227, -12273, -12320, -12368, -12417,
|
||||
-12467, -12518, -12570, -12623, -12676, -12731, -12786, -12842, -12898, -12956,
|
||||
-13014, -13072, -13131, -13191, -13251, -13311, -13372, -13433, -13495, -13556,
|
||||
-13618, -13680, -13743, -13805, -13867, -13929, -13991, -14053, -14115, -14177,
|
||||
-14238, -14299, -14359, -14419, -14479, -14538, -14597, -14655, -14712, -14768,
|
||||
-14824, -14879, -14933, -14986, -15039, -15090, -15140, -15189, -15237, -15284,
|
||||
-15330, -15375, -15418, -15460, -15500, -15539, -15577, -15614, -15648, -15682,
|
||||
-15714, -15744, -15772, -15799, -15825, -15849, -15871, -15891, -15910, -15927,
|
||||
-15942, -15955, -15967, -15977, -15985, -15991, -15996, -15999, -16000, -15999,
|
||||
-15996, -15991, -15985, -15977, -15967, -15955, -15942, -15927, -15910, -15891,
|
||||
-15871, -15849, -15825, -15799, -15772, -15744, -15714, -15682, -15648, -15614,
|
||||
-15577, -15539, -15500, -15460, -15418, -15375, -15330, -15284, -15237, -15189,
|
||||
-15140, -15090, -15039, -14986, -14933, -14879, -14824, -14768, -14712, -14655,
|
||||
-14597, -14538, -14479, -14419, -14359, -14299, -14238, -14177, -14115, -14053,
|
||||
-13991, -13929, -13867, -13805, -13743, -13680, -13618, -13556, -13495, -13433,
|
||||
-13372, -13311, -13251, -13191, -13131, -13072, -13014, -12956, -12898, -12842,
|
||||
-12786, -12731, -12676, -12623, -12570, -12518, -12467, -12417, -12368, -12320,
|
||||
-12273, -12227, -12182, -12138, -12095, -12054, -12013, -11974, -11936, -11899,
|
||||
-11863, -11828, -11795, -11763, -11732, -11702, -11673, -11646, -11620, -11595,
|
||||
-11571, -11548, -11527, -11507, -11488, -11470, -11453, -11437, -11423, -11409,
|
||||
-11397, -11385, -11375, -11365, -11356, -11349, -11342, -11336, -11331, -11326,
|
||||
-11323, -11319, -11317, -11315, -11314, -11313, -11313, -11313, -11314, -11315,
|
||||
-11316, -11318, -11319, -11321, -11323, -11324, -11326, -11328, -11329, -11331,
|
||||
-11332, -11333, -11333, -11333, -11332, -11331, -11330, -11327, -11324, -11320,
|
||||
-11316, -11310, -11303, -11296, -11287, -11277, -11266, -11254, -11240, -11225,
|
||||
-11209, -11191, -11172, -11151, -11128, -11104, -11078, -11050, -11020, -10989,
|
||||
-10955, -10920, -10882, -10843, -10801, -10757, -10711, -10663, -10612, -10559,
|
||||
-10504, -10447, -10387, -10324, -10260, -10192, -10123, -10050, -9975, -9898,
|
||||
-9818, -9735, -9650, -9562, -9472, -9379, -9283, -9185, -9084, -8980,
|
||||
-8874, -8765, -8653, -8539, -8422, -8302, -8180, -8056, -7929, -7799,
|
||||
-7667, -7532, -7395, -7255, -7113, -6969, -6822, -6673, -6522, -6369,
|
||||
-6213, -6055, -5895, -5733, -5569, -5403, -5235, -5065, -4894, -4720,
|
||||
-4545, -4369, -4190, -4011, -3829, -3647, -3463, -3278, -3091, -2904,
|
||||
-2715, -2525, -2335, -2143, -1951, -1758, -1564, -1370, -1175, -980,
|
||||
-784, -588, -392, -196,
|
||||
};
|
||||
|
||||
#if 1
|
||||
const unsigned int toneVolumes[] = { 2, 4, 8, 12, 16 };
|
||||
#else
|
||||
const unsigned int toneVolumes[] = { 4000, 8000, 16000, 24000, 32000 };
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD)
|
||||
const char * audioFilenames[] = {
|
||||
"tada",
|
||||
|
@ -190,7 +277,7 @@ void referenceSystemAudioFiles()
|
|||
if (!strcmp(filename, fn)) {
|
||||
availableAudioFiles |= MASK_SYSTEM_AUDIO_FILE(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +303,7 @@ void getPhaseAudioFile(char * filename, int index, unsigned int event)
|
|||
char * tmp = strcat_phasename(str, index);
|
||||
strcpy(tmp, suffixes[event]);
|
||||
strcat(tmp, SOUNDS_EXT);
|
||||
}
|
||||
}
|
||||
|
||||
void getSwitchAudioFile(char * filename, int index)
|
||||
{
|
||||
|
@ -227,7 +314,7 @@ void getSwitchAudioFile(char * filename, int index)
|
|||
if (*str == '\300') {
|
||||
strcpy(str, "-up");
|
||||
str += 3;
|
||||
}
|
||||
}
|
||||
else if (*str == '-') {
|
||||
strcpy(str, "-mid");
|
||||
str += 4;
|
||||
|
@ -265,7 +352,7 @@ void referenceModelAudioFiles()
|
|||
sdAvailablePhaseAudioFiles = 0;
|
||||
sdAvailableSwitchAudioFiles = 0;
|
||||
sdAvailableLogicalSwitchAudioFiles = 0;
|
||||
|
||||
|
||||
char * filename = getModelPath(path);
|
||||
*(filename-1) = '\0';
|
||||
|
||||
|
@ -289,7 +376,7 @@ void referenceModelAudioFiles()
|
|||
sdAvailablePhaseAudioFiles |= MASK_PHASE_AUDIO_FILE(i, event);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,8 +386,8 @@ void referenceModelAudioFiles()
|
|||
if (!strcmp(filename, fn)) {
|
||||
sdAvailableSwitchAudioFiles |= MASK_SWITCH_AUDIO_FILE(i);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Logical Switches Audio Files <switchname>-[on|off].wav
|
||||
for (int i=0; i<NUM_CSW && !found; i++) {
|
||||
|
@ -336,21 +423,21 @@ bool isAudioFileReferenced(uint32_t i, char * filename)
|
|||
else if (category == PHASE_AUDIO_CATEGORY) {
|
||||
if (sdAvailablePhaseAudioFiles & MASK_PHASE_AUDIO_FILE(index, event)) {
|
||||
getPhaseAudioFile(filename, index, event);
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (category == SWITCH_AUDIO_CATEGORY) {
|
||||
if (sdAvailableSwitchAudioFiles & MASK_SWITCH_AUDIO_FILE(index)) {
|
||||
getSwitchAudioFile(filename, index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (category == LOGICAL_SWITCH_AUDIO_CATEGORY) {
|
||||
if (sdAvailableLogicalSwitchAudioFiles & MASK_LOGICAL_SWITCH_AUDIO_FILE(index, event)) {
|
||||
getLogicalSwitchAudioFile(filename, index, event);
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -370,55 +457,8 @@ void playModelEvent(uint8_t category, uint8_t index, uint8_t event)
|
|||
|
||||
#endif
|
||||
|
||||
// TODO should be generated and in flash rather than in ram
|
||||
int16_t alawTable[256];
|
||||
int16_t ulawTable[256];
|
||||
|
||||
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
|
||||
#define QUANT_MASK (0xf) /* Quantization field mask. */
|
||||
#define SEG_SHIFT (4) /* Left shift for segment number. */
|
||||
#define SEG_MASK (0x70) /* Segment field mask. */
|
||||
#define BIAS (0x84) /* Bias for linear code. */
|
||||
|
||||
static short alaw2linear(unsigned char a_val)
|
||||
{
|
||||
int t;
|
||||
int seg;
|
||||
|
||||
a_val ^= 0x55;
|
||||
|
||||
t = a_val & QUANT_MASK;
|
||||
seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
|
||||
if(seg) t= (t + t + 1 + 32) << (seg + 2);
|
||||
else t= (t + t + 1 ) << 3;
|
||||
|
||||
return (a_val & SIGN_BIT) ? t : -t;
|
||||
}
|
||||
|
||||
static short ulaw2linear(unsigned char u_val)
|
||||
{
|
||||
int t;
|
||||
|
||||
/* Complement to obtain normal u-law value. */
|
||||
u_val = ~u_val;
|
||||
|
||||
/*
|
||||
* Extract and bias the quantization bits. Then
|
||||
* shift up by the segment number and subtract out the bias.
|
||||
*/
|
||||
t = ((u_val & QUANT_MASK) << 3) + BIAS;
|
||||
t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
|
||||
|
||||
return (u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS);
|
||||
}
|
||||
|
||||
void codecsInit()
|
||||
{
|
||||
for (uint32_t i=0; i<256; i++) {
|
||||
alawTable[i] = alaw2linear(i);
|
||||
ulawTable[i] = ulaw2linear(i);
|
||||
}
|
||||
}
|
||||
const int16_t alawTable[256] = { -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, -344, -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848 };
|
||||
const int16_t ulawTable[256] = { -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876, -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, -396, -372, -356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, -132, -120, -112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 876, 844, 812, 780, 748, 716, 684, 652, 620, 588, 556, 524, 492, 460, 428, 396, 372, 356, 340, 324, 308, 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0 };
|
||||
|
||||
AudioQueue audioQueue;
|
||||
|
||||
|
@ -448,7 +488,6 @@ void audioTask(void* pdata)
|
|||
|
||||
#if defined(SDCARD)
|
||||
if (!unexpectedShutdown) {
|
||||
codecsInit();
|
||||
sdInit();
|
||||
AUDIO_TADA();
|
||||
}
|
||||
|
@ -476,7 +515,7 @@ void AudioQueue::pushBuffer(AudioBuffer *buffer)
|
|||
__enable_irq();
|
||||
}
|
||||
|
||||
void mix(uint16_t * result, int sample, unsigned int fade)
|
||||
void mixSample(uint16_t * result, int sample, unsigned int fade)
|
||||
{
|
||||
*result = limit(0, *result + ((sample >> fade) >> 4), 4095);
|
||||
}
|
||||
|
@ -486,42 +525,41 @@ void mix(uint16_t * result, int sample, unsigned int fade)
|
|||
#define RIFF_CHUNK_SIZE 12
|
||||
uint8_t wavBuffer[AUDIO_BUFFER_SIZE*2];
|
||||
|
||||
int AudioQueue::mixWav(AudioContext &context, AudioBuffer *buffer, int volume, unsigned int fade)
|
||||
int WavContext::mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade)
|
||||
{
|
||||
FRESULT result = FR_OK;
|
||||
UINT read = 0;
|
||||
AudioFragment & fragment = context.fragment;
|
||||
|
||||
if (fragment.file[1]) {
|
||||
result = f_open(&context.state.wav.file, fragment.file, FA_OPEN_EXISTING | FA_READ);
|
||||
result = f_open(&state.file, fragment.file, FA_OPEN_EXISTING | FA_READ);
|
||||
fragment.file[1] = 0;
|
||||
if (result == FR_OK) {
|
||||
result = f_read(&context.state.wav.file, wavBuffer, RIFF_CHUNK_SIZE+8, &read);
|
||||
result = f_read(&state.file, wavBuffer, RIFF_CHUNK_SIZE+8, &read);
|
||||
if (result == FR_OK && read == RIFF_CHUNK_SIZE+8 && !memcmp(wavBuffer, "RIFF", 4) && !memcmp(wavBuffer+8, "WAVEfmt ", 8)) {
|
||||
uint32_t size = *((uint32_t *)(wavBuffer+16));
|
||||
result = (size < 256 ? f_read(&context.state.wav.file, wavBuffer, size+8, &read) : FR_DENIED);
|
||||
result = (size < 256 ? f_read(&state.file, wavBuffer, size+8, &read) : FR_DENIED);
|
||||
if (result == FR_OK && read == size+8) {
|
||||
context.state.wav.codec = ((uint16_t *)wavBuffer)[0];
|
||||
context.state.wav.freq = ((uint16_t *)wavBuffer)[2];
|
||||
state.codec = ((uint16_t *)wavBuffer)[0];
|
||||
state.freq = ((uint16_t *)wavBuffer)[2];
|
||||
uint32_t *wavSamplesPtr = (uint32_t *)(wavBuffer + size);
|
||||
uint32_t size = wavSamplesPtr[1];
|
||||
if (context.state.wav.freq != 0 && context.state.wav.freq * (AUDIO_SAMPLE_RATE / context.state.wav.freq) == AUDIO_SAMPLE_RATE) {
|
||||
context.state.wav.resampleRatio = (AUDIO_SAMPLE_RATE / context.state.wav.freq);
|
||||
context.state.wav.readSize = (context.state.wav.codec == CODEC_ID_PCM_S16LE ? 2*AUDIO_BUFFER_SIZE : AUDIO_BUFFER_SIZE) / context.state.wav.resampleRatio;
|
||||
if (state.freq != 0 && state.freq * (AUDIO_SAMPLE_RATE / state.freq) == AUDIO_SAMPLE_RATE) {
|
||||
state.resampleRatio = (AUDIO_SAMPLE_RATE / state.freq);
|
||||
state.readSize = (state.codec == CODEC_ID_PCM_S16LE ? 2*AUDIO_BUFFER_SIZE : AUDIO_BUFFER_SIZE) / state.resampleRatio;
|
||||
}
|
||||
else {
|
||||
result = FR_DENIED;
|
||||
}
|
||||
while (result == FR_OK && memcmp(wavSamplesPtr, "data", 4) != 0) {
|
||||
result = f_lseek(&context.state.wav.file, f_tell(&context.state.wav.file)+size);
|
||||
result = f_lseek(&state.file, f_tell(&state.file)+size);
|
||||
if (result == FR_OK) {
|
||||
result = f_read(&context.state.wav.file, wavBuffer, 8, &read);
|
||||
result = f_read(&state.file, wavBuffer, 8, &read);
|
||||
if (read != 8) result = FR_DENIED;
|
||||
wavSamplesPtr = (uint32_t *)wavBuffer;
|
||||
size = wavSamplesPtr[1];
|
||||
}
|
||||
}
|
||||
context.state.wav.size = size;
|
||||
state.size = size;
|
||||
}
|
||||
else {
|
||||
result = FR_DENIED;
|
||||
|
@ -535,128 +573,128 @@ int AudioQueue::mixWav(AudioContext &context, AudioBuffer *buffer, int volume, u
|
|||
|
||||
read = 0;
|
||||
if (result == FR_OK) {
|
||||
result = f_read(&context.state.wav.file, wavBuffer, context.state.wav.readSize, &read);
|
||||
result = f_read(&state.file, wavBuffer, state.readSize, &read);
|
||||
if (result == FR_OK) {
|
||||
if (read > context.state.wav.size) {
|
||||
read = context.state.wav.size;
|
||||
if (read > state.size) {
|
||||
read = state.size;
|
||||
}
|
||||
context.state.wav.size -= read;
|
||||
state.size -= read;
|
||||
|
||||
if (read != context.state.wav.readSize) {
|
||||
f_close(&context.state.wav.file);
|
||||
if (read != state.readSize) {
|
||||
f_close(&state.file);
|
||||
fragment.clear();
|
||||
}
|
||||
|
||||
uint16_t * samples = buffer->data;
|
||||
if (context.state.wav.codec == CODEC_ID_PCM_S16LE) {
|
||||
if (state.codec == CODEC_ID_PCM_S16LE) {
|
||||
read /= 2;
|
||||
for (uint32_t i=0; i<read; i++) {
|
||||
for (uint8_t j=0; j<context.state.wav.resampleRatio; j++)
|
||||
mix(samples++, ((int16_t *)wavBuffer)[i], fade+2-volume);
|
||||
for (uint8_t j=0; j<state.resampleRatio; j++)
|
||||
mixSample(samples++, ((int16_t *)wavBuffer)[i], fade+2-volume);
|
||||
}
|
||||
}
|
||||
else if (context.state.wav.codec == CODEC_ID_PCM_ALAW) {
|
||||
else if (state.codec == CODEC_ID_PCM_ALAW) {
|
||||
for (uint32_t i=0; i<read; i++)
|
||||
for (uint8_t j=0; j<context.state.wav.resampleRatio; j++)
|
||||
mix(samples++, alawTable[wavBuffer[i]], fade+2-volume);
|
||||
for (uint8_t j=0; j<state.resampleRatio; j++)
|
||||
mixSample(samples++, alawTable[wavBuffer[i]], fade+2-volume);
|
||||
}
|
||||
else if (context.state.wav.codec == CODEC_ID_PCM_MULAW) {
|
||||
else if (state.codec == CODEC_ID_PCM_MULAW) {
|
||||
for (uint32_t i=0; i<read; i++)
|
||||
for (uint8_t j=0; j<context.state.wav.resampleRatio; j++)
|
||||
mix(samples++, ulawTable[wavBuffer[i]], fade+2-volume);
|
||||
for (uint8_t j=0; j<state.resampleRatio; j++)
|
||||
mixSample(samples++, ulawTable[wavBuffer[i]], fade+2-volume);
|
||||
}
|
||||
|
||||
return samples - buffer->data;
|
||||
}
|
||||
}
|
||||
|
||||
fragment.clear();
|
||||
clear();
|
||||
return -result;
|
||||
}
|
||||
#else
|
||||
int AudioQueue::mixWav(AudioContext &context, AudioBuffer *buffer, int volume, unsigned int fade)
|
||||
int WavContext::mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int AudioQueue::mixBeep(AudioContext &context, AudioBuffer *buffer, int volume, unsigned int fade)
|
||||
const unsigned int toneVolumes[] = { 10, 8, 6, 4, 2 };
|
||||
inline float evalVolumeRatio(int freq, int volume)
|
||||
{
|
||||
AudioFragment & fragment = context.fragment;
|
||||
int duration = 0;
|
||||
int result = 0;
|
||||
|
||||
if (fragment.tone.duration > 0) {
|
||||
result = AUDIO_BUFFER_SIZE;
|
||||
if (fragment.tone.freq && context.state.tone.freq!=fragment.tone.freq && (!fragment.tone.freqIncr || abs(context.state.tone.freq-fragment.tone.freq) > 100)) {
|
||||
int periods = BEEP_POINTS_COUNT / ((AUDIO_SAMPLE_RATE / fragment.tone.freq) + 1);
|
||||
context.state.tone.count = (periods * AUDIO_SAMPLE_RATE) / fragment.tone.freq;
|
||||
if (context.state.tone.idx >= context.state.tone.count) context.state.tone.idx = 0;
|
||||
#if 1
|
||||
for (unsigned int i=0; i<context.state.tone.count; i++)
|
||||
context.state.tone.points[i] = sineValues[((DIM(sineValues)*periods*i)/context.state.tone.count) % DIM(sineValues)] * (toneVolumes[2+volume]);
|
||||
#else
|
||||
double t = (M_PI * 2 * periods) / context.state.tone.count;
|
||||
for (unsigned int i=0; i<context.state.tone.count; i++)
|
||||
context.state.tone.points[i] = sin(t*i) * (toneVolumes[2+volume]);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fragment.tone.freqIncr)
|
||||
fragment.tone.freq += AUDIO_BUFFER_DURATION * fragment.tone.freqIncr;
|
||||
else
|
||||
fragment.tone.freq = 0;
|
||||
|
||||
duration = AUDIO_BUFFER_DURATION;
|
||||
int points = AUDIO_BUFFER_SIZE;
|
||||
bool end = false;
|
||||
|
||||
if (fragment.tone.duration <= AUDIO_BUFFER_DURATION) {
|
||||
duration = fragment.tone.duration;
|
||||
points = duration*(AUDIO_BUFFER_SIZE/AUDIO_BUFFER_DURATION);
|
||||
end = true;
|
||||
}
|
||||
|
||||
for (int i=0; i<points; i++) {
|
||||
mix(&buffer->data[i], context.state.tone.points[context.state.tone.idx], fade);
|
||||
context.state.tone.idx = context.state.tone.idx + 1;
|
||||
if (context.state.tone.idx >= context.state.tone.count) {
|
||||
context.state.tone.idx = 0;
|
||||
if (end && i+BEEP_POINTS_COUNT>points) break;
|
||||
}
|
||||
}
|
||||
|
||||
fragment.tone.duration -= duration;
|
||||
if (fragment.tone.duration > 0)
|
||||
return AUDIO_BUFFER_SIZE;
|
||||
float result = toneVolumes[2+volume];
|
||||
if (freq < 330) {
|
||||
result = (result * freq * freq) / (330 * 330);
|
||||
}
|
||||
|
||||
if (fragment.tone.pause > 0) {
|
||||
result = AUDIO_BUFFER_SIZE;
|
||||
fragment.tone.pause -= min<unsigned int>(AUDIO_BUFFER_DURATION-duration, fragment.tone.pause);
|
||||
if (fragment.tone.pause > 0)
|
||||
return AUDIO_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
fragment.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
int AudioQueue::mixAudioContext(AudioContext &context, AudioBuffer *buffer, int beepVolume, int wavVolume, unsigned int fade)
|
||||
int ToneContext::mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade)
|
||||
{
|
||||
int result;
|
||||
AudioFragment & fragment = context.fragment;
|
||||
int duration = 0;
|
||||
int result = 0;
|
||||
|
||||
if (fragment.type == FRAGMENT_TONE) {
|
||||
result = mixBeep(context, buffer, beepVolume, fade);
|
||||
}
|
||||
else if (fragment.type == FRAGMENT_FILE) {
|
||||
result = mixWav(context, buffer, wavVolume, fade);
|
||||
}
|
||||
else {
|
||||
result = 0;
|
||||
int remainingDuration = fragment.tone.duration - state.duration;
|
||||
if (remainingDuration > 0) {
|
||||
int points;
|
||||
double toneIdx = state.idx;
|
||||
|
||||
if (fragment.tone.reset) {
|
||||
state.duration = 0;
|
||||
state.pause = 0;
|
||||
}
|
||||
|
||||
if (fragment.tone.freq != state.freq) {
|
||||
state.freq = fragment.tone.freq;
|
||||
state.step = double(DIM(sineValues)*fragment.tone.freq) / AUDIO_SAMPLE_RATE;
|
||||
state.volume = evalVolumeRatio(fragment.tone.freq, volume);
|
||||
}
|
||||
|
||||
if (fragment.tone.freqIncr) {
|
||||
fragment.tone.freq += AUDIO_BUFFER_DURATION * fragment.tone.freqIncr;
|
||||
}
|
||||
|
||||
if (remainingDuration > AUDIO_BUFFER_DURATION) {
|
||||
duration = AUDIO_BUFFER_DURATION;
|
||||
points = AUDIO_BUFFER_SIZE;
|
||||
}
|
||||
else {
|
||||
duration = remainingDuration;
|
||||
points = (duration * AUDIO_BUFFER_SIZE) / AUDIO_BUFFER_DURATION;
|
||||
unsigned int end = toneIdx + (state.step * points);
|
||||
if (end > DIM(sineValues))
|
||||
end -= (end % DIM(sineValues));
|
||||
else
|
||||
end = DIM(sineValues);
|
||||
points = (double(end) - toneIdx) / state.step;
|
||||
}
|
||||
|
||||
for (int i=0; i<points; i++) {
|
||||
int16_t sample = sineValues[int(toneIdx)] / state.volume;
|
||||
mixSample(&buffer->data[i], sample, fade);
|
||||
toneIdx += state.step;
|
||||
if ((unsigned int)toneIdx >= DIM(sineValues))
|
||||
toneIdx -= DIM(sineValues);
|
||||
}
|
||||
|
||||
if (remainingDuration > AUDIO_BUFFER_DURATION) {
|
||||
state.duration += AUDIO_BUFFER_DURATION;
|
||||
state.idx = toneIdx;
|
||||
return AUDIO_BUFFER_SIZE;
|
||||
}
|
||||
else {
|
||||
state.duration = 32000; // once the tone is finished, it's not possible to update its frequency and duration
|
||||
}
|
||||
}
|
||||
|
||||
remainingDuration = fragment.tone.pause - state.pause;
|
||||
if (remainingDuration > 0) {
|
||||
result = AUDIO_BUFFER_SIZE;
|
||||
state.pause += min<unsigned int>(AUDIO_BUFFER_DURATION-duration, fragment.tone.pause);
|
||||
if (fragment.tone.pause > state.pause)
|
||||
return result;
|
||||
}
|
||||
|
||||
clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -673,15 +711,20 @@ void AudioQueue::wakeup()
|
|||
buffer->data[i] = 0x8000 >> 4; /* silence */
|
||||
}
|
||||
|
||||
// mix the foreground context
|
||||
result = mixAudioContext(foregroundContext, buffer, g_eeGeneral.beepVolume, g_eeGeneral.wavVolume, fade);
|
||||
// mix the priority context (only tones)
|
||||
result = priorityContext.mixBuffer(buffer, g_eeGeneral.beepVolume, fade);
|
||||
if (result > 0) {
|
||||
size = max(size, result);
|
||||
size = result;
|
||||
fade += 1;
|
||||
}
|
||||
|
||||
// mix the normal context
|
||||
result = mixAudioContext(currentContext, buffer, g_eeGeneral.beepVolume, g_eeGeneral.wavVolume, fade);
|
||||
// mix the normal context (tones and wavs)
|
||||
if (normalContext.fragment.type == FRAGMENT_TONE)
|
||||
result = normalContext.tone.mixBuffer(buffer, g_eeGeneral.beepVolume, fade);
|
||||
else if (normalContext.fragment.type == FRAGMENT_FILE)
|
||||
result = normalContext.wav.mixBuffer(buffer, g_eeGeneral.wavVolume, fade);
|
||||
else
|
||||
result = 0;
|
||||
if (result > 0) {
|
||||
size = max(size, result);
|
||||
fade += 1;
|
||||
|
@ -689,8 +732,7 @@ void AudioQueue::wakeup()
|
|||
else {
|
||||
CoEnterMutexSection(audioMutex);
|
||||
if (ridx != widx) {
|
||||
currentContext.clear();
|
||||
currentContext.fragment = fragments[ridx];
|
||||
normalContext.fragment = fragments[ridx];
|
||||
if (!fragments[ridx].repeat--) {
|
||||
ridx = (ridx + 1) % AUDIO_QUEUE_LENGTH;
|
||||
}
|
||||
|
@ -698,9 +740,16 @@ void AudioQueue::wakeup()
|
|||
CoLeaveMutexSection(audioMutex);
|
||||
}
|
||||
|
||||
// mix the vario context
|
||||
result = varioContext.mixBuffer(buffer, g_eeGeneral.varioVolume, fade);
|
||||
if (result > 0) {
|
||||
size = max(size, result);
|
||||
fade += 1;
|
||||
}
|
||||
|
||||
// mix the background context
|
||||
if (!isFunctionActive(FUNCTION_BACKGND_MUSIC_PAUSE)) {
|
||||
result = mixAudioContext(backgroundContext, buffer, g_eeGeneral.varioVolume, g_eeGeneral.backgroundVolume, fade);
|
||||
if (isFunctionActive(FUNCTION_BACKGND_MUSIC) && !isFunctionActive(FUNCTION_BACKGND_MUSIC_PAUSE)) {
|
||||
result = backgroundContext.mixBuffer(buffer, g_eeGeneral.backgroundVolume, fade);
|
||||
if (result > 0) {
|
||||
size = max(size, result);
|
||||
}
|
||||
|
@ -728,12 +777,12 @@ inline unsigned int getToneLength(uint16_t len)
|
|||
|
||||
void AudioQueue::pause(uint16_t len)
|
||||
{
|
||||
play(0, 0, len);
|
||||
playTone(0, 0, len);
|
||||
}
|
||||
|
||||
bool AudioQueue::isPlaying(uint8_t id)
|
||||
{
|
||||
if (currentContext.fragment.id == id || backgroundContext.fragment.id == id)
|
||||
if (normalContext.fragment.id == id || backgroundContext.fragment.id == id)
|
||||
return true;
|
||||
|
||||
uint8_t i = ridx;
|
||||
|
@ -746,7 +795,7 @@ bool AudioQueue::isPlaying(uint8_t id)
|
|||
return false;
|
||||
}
|
||||
|
||||
void AudioQueue::play(uint16_t freq, uint16_t len, uint16_t pause, uint8_t flags, int8_t freqIncr)
|
||||
void AudioQueue::playTone(uint16_t freq, uint16_t len, uint16_t pause, uint8_t flags, int8_t freqIncr)
|
||||
{
|
||||
CoEnterMutexSection(audioMutex);
|
||||
|
||||
|
@ -754,21 +803,21 @@ void AudioQueue::play(uint16_t freq, uint16_t len, uint16_t pause, uint8_t flags
|
|||
freq = BEEP_MIN_FREQ;
|
||||
|
||||
if (flags & PLAY_BACKGROUND) {
|
||||
AudioFragment & fragment = backgroundContext.fragment;
|
||||
backgroundContext.clear();
|
||||
AudioFragment & fragment = varioContext.fragment;
|
||||
fragment.type = FRAGMENT_TONE;
|
||||
fragment.tone.freq = freq;
|
||||
fragment.tone.duration = len;
|
||||
fragment.tone.pause = pause;
|
||||
fragment.tone.reset = (flags & PLAY_NOW);
|
||||
}
|
||||
else {
|
||||
freq += g_eeGeneral.speakerPitch * 15;
|
||||
len = getToneLength(len);
|
||||
|
||||
if (flags & PLAY_NOW) {
|
||||
AudioFragment & fragment = foregroundContext.fragment;
|
||||
AudioFragment & fragment = priorityContext.fragment;
|
||||
if (fragment.type == FRAGMENT_EMPTY) {
|
||||
foregroundContext.clear();
|
||||
priorityContext.clear();
|
||||
fragment.type = FRAGMENT_TONE;
|
||||
fragment.repeat = flags & 0x0f;
|
||||
fragment.tone.freq = freq;
|
||||
|
@ -825,9 +874,9 @@ void AudioQueue::playFile(const char *filename, uint8_t flags, uint8_t id)
|
|||
fragment.id = id;
|
||||
}
|
||||
else if (flags & PLAY_NOW) {
|
||||
AudioFragment & fragment = foregroundContext.fragment;
|
||||
AudioFragment & fragment = priorityContext.fragment;
|
||||
if (fragment.type == FRAGMENT_EMPTY) {
|
||||
foregroundContext.clear();
|
||||
priorityContext.clear();
|
||||
fragment.type = FRAGMENT_FILE;
|
||||
strcpy(fragment.file, filename);
|
||||
fragment.repeat = flags & 0x0f;
|
||||
|
@ -868,7 +917,7 @@ void AudioQueue::stopSD()
|
|||
{
|
||||
sdAvailableSystemAudioFiles = 0;
|
||||
reset();
|
||||
play(0, 0, 100, PLAY_NOW); // insert a 100ms pause
|
||||
playTone(0, 0, 100, PLAY_NOW); // insert a 100ms pause
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -877,8 +926,9 @@ void AudioQueue::reset()
|
|||
{
|
||||
CoEnterMutexSection(audioMutex);
|
||||
widx = ridx; // clean the queue
|
||||
foregroundContext.clear();
|
||||
currentContext.clear();
|
||||
priorityContext.clear();
|
||||
normalContext.tone.clear();
|
||||
varioContext.clear();
|
||||
backgroundContext.clear();
|
||||
CoLeaveMutexSection(audioMutex);
|
||||
}
|
||||
|
@ -907,23 +957,23 @@ void audioEvent(uint8_t e, uint16_t f)
|
|||
switch (e) {
|
||||
// inactivity timer alert
|
||||
case AU_INACTIVITY:
|
||||
audioQueue.play(2250, 80, 20, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(2250, 80, 20, PLAY_REPEAT(2));
|
||||
break;
|
||||
// low battery in tx
|
||||
case AU_TX_BATTERY_LOW:
|
||||
audioQueue.play(1950, 160, 20, PLAY_REPEAT(2), 1);
|
||||
audioQueue.play(2550, 160, 20, PLAY_REPEAT(2), -1);
|
||||
audioQueue.playTone(1950, 160, 20, PLAY_REPEAT(2), 1);
|
||||
audioQueue.playTone(2550, 160, 20, PLAY_REPEAT(2), -1);
|
||||
break;
|
||||
#if defined(PCBSKY9X)
|
||||
case AU_TX_MAH_HIGH:
|
||||
// TODO Rob something better here?
|
||||
audioQueue.play(1950, 160, 20, PLAY_REPEAT(2), 1);
|
||||
audioQueue.play(2550, 160, 20, PLAY_REPEAT(2), -1);
|
||||
audioQueue.playTone(1950, 160, 20, PLAY_REPEAT(2), 1);
|
||||
audioQueue.playTone(2550, 160, 20, PLAY_REPEAT(2), -1);
|
||||
break;
|
||||
case AU_TX_TEMP_HIGH:
|
||||
// TODO Rob something better here?
|
||||
audioQueue.play(1950, 160, 20, PLAY_REPEAT(2), 1);
|
||||
audioQueue.play(2550, 160, 20, PLAY_REPEAT(2), -1);
|
||||
audioQueue.playTone(1950, 160, 20, PLAY_REPEAT(2), 1);
|
||||
audioQueue.playTone(2550, 160, 20, PLAY_REPEAT(2), -1);
|
||||
break;
|
||||
#endif
|
||||
#if defined(VOICE)
|
||||
|
@ -931,43 +981,43 @@ void audioEvent(uint8_t e, uint16_t f)
|
|||
case AU_SWITCH_ALERT:
|
||||
#endif
|
||||
case AU_ERROR:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ, 200, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ, 200, 20, PLAY_NOW);
|
||||
break;
|
||||
// keypad up (seems to be used when going left/right through system menu options. 0-100 scales etc)
|
||||
case AU_KEYPAD_UP:
|
||||
audioQueue.play(BEEP_KEY_UP_FREQ, 80, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_KEY_UP_FREQ, 80, 20, PLAY_NOW);
|
||||
break;
|
||||
// keypad down (seems to be used when going left/right through system menu options. 0-100 scales etc)
|
||||
case AU_KEYPAD_DOWN:
|
||||
audioQueue.play(BEEP_KEY_DOWN_FREQ, 80, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_KEY_DOWN_FREQ, 80, 20, PLAY_NOW);
|
||||
break;
|
||||
// menu display (also used by a few generic beeps)
|
||||
case AU_MENUS:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ, 80, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ, 80, 20, PLAY_NOW);
|
||||
break;
|
||||
// trim move
|
||||
case AU_TRIM_MOVE:
|
||||
audioQueue.play(f, 40, 20, PLAY_NOW);
|
||||
audioQueue.playTone(f, 40, 20, PLAY_NOW);
|
||||
break;
|
||||
// trim center
|
||||
case AU_TRIM_MIDDLE:
|
||||
audioQueue.play(f, 80, 20, PLAY_NOW);
|
||||
audioQueue.playTone(f, 80, 20, PLAY_NOW);
|
||||
break;
|
||||
// trim center
|
||||
case AU_TRIM_END:
|
||||
audioQueue.play(f, 80, 20, PLAY_NOW);
|
||||
audioQueue.playTone(f, 80, 20, PLAY_NOW);
|
||||
break;
|
||||
// warning one
|
||||
case AU_WARNING1:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ, 80, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ, 80, 20, PLAY_NOW);
|
||||
break;
|
||||
// warning two
|
||||
case AU_WARNING2:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ, 160, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ, 160, 20, PLAY_NOW);
|
||||
break;
|
||||
// warning three
|
||||
case AU_WARNING3:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ, 200, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ, 200, 20, PLAY_NOW);
|
||||
break;
|
||||
// pot/stick center
|
||||
case AU_STICK1_MIDDLE:
|
||||
|
@ -982,120 +1032,120 @@ void audioEvent(uint8_t e, uint16_t f)
|
|||
#else
|
||||
case AU_POT3_MIDDLE:
|
||||
#endif
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1500, 80, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1500, 80, 20, PLAY_NOW);
|
||||
break;
|
||||
// mix warning 1
|
||||
case AU_MIX_WARNING_1:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1440, 48, 32);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1440, 48, 32);
|
||||
break;
|
||||
// mix warning 2
|
||||
case AU_MIX_WARNING_2:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1560, 48, 32, PLAY_REPEAT(1));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1560, 48, 32, PLAY_REPEAT(1));
|
||||
break;
|
||||
// mix warning 3
|
||||
case AU_MIX_WARNING_3:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1680, 48, 32, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1680, 48, 32, PLAY_REPEAT(2));
|
||||
break;
|
||||
// timer == 0
|
||||
case AU_TIMER_00:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+150, 300, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+150, 300, 20, PLAY_NOW);
|
||||
break;
|
||||
// timer <= 10 seconds left
|
||||
case AU_TIMER_LT10:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_NOW);
|
||||
break;
|
||||
// timer 20 seconds left
|
||||
case AU_TIMER_20:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_REPEAT(1)|PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_REPEAT(1)|PLAY_NOW);
|
||||
break;
|
||||
// timer 30 seconds left
|
||||
case AU_TIMER_30:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_REPEAT(2)|PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_REPEAT(2)|PLAY_NOW);
|
||||
break;
|
||||
#if defined(PCBTARANIS)
|
||||
case AU_A1_ORANGE:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+600, 200, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+600, 200, 20, PLAY_NOW);
|
||||
break;
|
||||
case AU_A1_RED:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+600, 200, 20, PLAY_REPEAT(1)|PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+600, 200, 20, PLAY_REPEAT(1)|PLAY_NOW);
|
||||
break;
|
||||
case AU_A2_ORANGE:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1500, 200, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1500, 200, 20, PLAY_NOW);
|
||||
break;
|
||||
case AU_A2_RED:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1500, 200, 20, PLAY_REPEAT(1)|PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1500, 200, 20, PLAY_REPEAT(1)|PLAY_NOW);
|
||||
break;
|
||||
case AU_RSSI_ORANGE:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1500, 800, 20, PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1500, 800, 20, PLAY_NOW);
|
||||
break;
|
||||
case AU_RSSI_RED:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1800, 800, 20, PLAY_REPEAT(1)|PLAY_NOW);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1800, 800, 20, PLAY_REPEAT(1)|PLAY_NOW);
|
||||
break;
|
||||
case AU_SWR_RED:
|
||||
audioQueue.play(450, 160, 40, PLAY_REPEAT(2), 1);
|
||||
audioQueue.playTone(450, 160, 40, PLAY_REPEAT(2), 1);
|
||||
break;
|
||||
#endif
|
||||
case AU_FRSKY_BEEP1:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ, 60, 20);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ, 60, 20);
|
||||
break;
|
||||
case AU_FRSKY_BEEP2:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ, 120, 20);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ, 120, 20);
|
||||
break;
|
||||
case AU_FRSKY_BEEP3:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ, 200, 20);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ, 200, 20);
|
||||
break;
|
||||
case AU_FRSKY_WARN1:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+600, 120, 40, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+600, 120, 40, PLAY_REPEAT(2));
|
||||
break;
|
||||
case AU_FRSKY_WARN2:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+900, 120, 40, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+900, 120, 40, PLAY_REPEAT(2));
|
||||
break;
|
||||
case AU_FRSKY_CHEEP:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+900, 80, 20, PLAY_REPEAT(2), 2);
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+900, 80, 20, PLAY_REPEAT(2), 2);
|
||||
break;
|
||||
case AU_FRSKY_RING:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+750, 40, 20, PLAY_REPEAT(10));
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+750, 40, 80, PLAY_REPEAT(1));
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+750, 40, 20, PLAY_REPEAT(10));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+750, 40, 20, PLAY_REPEAT(10));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+750, 40, 80, PLAY_REPEAT(1));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+750, 40, 20, PLAY_REPEAT(10));
|
||||
break;
|
||||
case AU_FRSKY_SCIFI:
|
||||
audioQueue.play(2550, 80, 20, PLAY_REPEAT(2), -1);
|
||||
audioQueue.play(1950, 80, 20, PLAY_REPEAT(2), 1);
|
||||
audioQueue.play(2250, 80, 20, 0);
|
||||
audioQueue.playTone(2550, 80, 20, PLAY_REPEAT(2), -1);
|
||||
audioQueue.playTone(1950, 80, 20, PLAY_REPEAT(2), 1);
|
||||
audioQueue.playTone(2250, 80, 20, 0);
|
||||
break;
|
||||
case AU_FRSKY_ROBOT:
|
||||
audioQueue.play(2250, 40, 20, PLAY_REPEAT(1));
|
||||
audioQueue.play(1650, 120, 20, PLAY_REPEAT(1));
|
||||
audioQueue.play(2550, 120, 20, PLAY_REPEAT(1));
|
||||
audioQueue.playTone(2250, 40, 20, PLAY_REPEAT(1));
|
||||
audioQueue.playTone(1650, 120, 20, PLAY_REPEAT(1));
|
||||
audioQueue.playTone(2550, 120, 20, PLAY_REPEAT(1));
|
||||
break;
|
||||
case AU_FRSKY_CHIRP:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1200, 40, 20, PLAY_REPEAT(2));
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1620, 40, 20, PLAY_REPEAT(3));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1200, 40, 20, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1620, 40, 20, PLAY_REPEAT(3));
|
||||
break;
|
||||
case AU_FRSKY_TADA:
|
||||
audioQueue.play(1650, 80, 40);
|
||||
audioQueue.play(2850, 80, 40);
|
||||
audioQueue.play(3450, 64, 36, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(1650, 80, 40);
|
||||
audioQueue.playTone(2850, 80, 40);
|
||||
audioQueue.playTone(3450, 64, 36, PLAY_REPEAT(2));
|
||||
break;
|
||||
case AU_FRSKY_CRICKET:
|
||||
audioQueue.play(2550, 40, 80, PLAY_REPEAT(3));
|
||||
audioQueue.play(2550, 40, 160, PLAY_REPEAT(1));
|
||||
audioQueue.play(2550, 40, 80, PLAY_REPEAT(3));
|
||||
audioQueue.playTone(2550, 40, 80, PLAY_REPEAT(3));
|
||||
audioQueue.playTone(2550, 40, 160, PLAY_REPEAT(1));
|
||||
audioQueue.playTone(2550, 40, 80, PLAY_REPEAT(3));
|
||||
break;
|
||||
case AU_FRSKY_SIREN:
|
||||
audioQueue.play(450, 160, 40, PLAY_REPEAT(2), 2);
|
||||
audioQueue.playTone(450, 160, 40, PLAY_REPEAT(2), 2);
|
||||
break;
|
||||
case AU_FRSKY_ALARMC:
|
||||
audioQueue.play(1650, 32, 68, PLAY_REPEAT(2));
|
||||
audioQueue.play(2250, 64, 156, PLAY_REPEAT(1));
|
||||
audioQueue.play(1650, 64, 76, PLAY_REPEAT(2));
|
||||
audioQueue.play(2250, 32, 168, PLAY_REPEAT(1));
|
||||
audioQueue.playTone(1650, 32, 68, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(2250, 64, 156, PLAY_REPEAT(1));
|
||||
audioQueue.playTone(1650, 64, 76, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(2250, 32, 168, PLAY_REPEAT(1));
|
||||
break;
|
||||
case AU_FRSKY_RATATA:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1500, 40, 80, PLAY_REPEAT(10));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1500, 40, 80, PLAY_REPEAT(10));
|
||||
break;
|
||||
case AU_FRSKY_TICK:
|
||||
audioQueue.play(BEEP_DEFAULT_FREQ+1500, 40, 400, PLAY_REPEAT(2));
|
||||
audioQueue.playTone(BEEP_DEFAULT_FREQ+1500, 40, 400, PLAY_REPEAT(2));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -47,11 +47,10 @@
|
|||
#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE*AUDIO_BUFFER_DURATION/1000)
|
||||
#define AUDIO_BUFFER_COUNT (3)
|
||||
|
||||
#define BEEP_MIN_FREQ (440)
|
||||
#define BEEP_MIN_FREQ (150)
|
||||
#define BEEP_DEFAULT_FREQ (2250)
|
||||
#define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+150)
|
||||
#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-150)
|
||||
#define BEEP_POINTS_COUNT 100
|
||||
|
||||
#define AUDIO_BUFFER_FREE (0)
|
||||
#define AUDIO_BUFFER_FILLED (1)
|
||||
|
@ -63,9 +62,11 @@ struct AudioBuffer {
|
|||
uint8_t state;
|
||||
};
|
||||
|
||||
#define FRAGMENT_EMPTY 0
|
||||
#define FRAGMENT_TONE 1
|
||||
#define FRAGMENT_FILE 2
|
||||
enum FragmentTypes {
|
||||
FRAGMENT_EMPTY,
|
||||
FRAGMENT_TONE,
|
||||
FRAGMENT_FILE,
|
||||
};
|
||||
|
||||
struct AudioFragment {
|
||||
uint8_t type;
|
||||
|
@ -77,6 +78,7 @@ struct AudioFragment {
|
|||
uint16_t duration;
|
||||
uint16_t pause;
|
||||
int8_t freqIncr;
|
||||
uint8_t reset;
|
||||
} tone;
|
||||
|
||||
char file[AUDIO_FILENAME_MAXLEN+1];
|
||||
|
@ -88,34 +90,57 @@ struct AudioFragment {
|
|||
}
|
||||
};
|
||||
|
||||
class AudioContext {
|
||||
class ToneContext {
|
||||
public:
|
||||
AudioFragment fragment;
|
||||
|
||||
union {
|
||||
#if defined(SDCARD)
|
||||
struct {
|
||||
FIL file;
|
||||
uint8_t codec;
|
||||
uint32_t freq;
|
||||
uint32_t size;
|
||||
uint8_t resampleRatio;
|
||||
uint16_t readSize;
|
||||
} wav;
|
||||
#endif
|
||||
struct {
|
||||
double step;
|
||||
double idx;
|
||||
float volume;
|
||||
uint16_t freq;
|
||||
uint16_t duration;
|
||||
uint16_t pause;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
int16_t points[BEEP_POINTS_COUNT];
|
||||
uint8_t count;
|
||||
uint8_t idx;
|
||||
uint16_t freq;
|
||||
} tone;
|
||||
inline void clear()
|
||||
{
|
||||
memset(this, 0, sizeof(ToneContext));
|
||||
}
|
||||
|
||||
int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
|
||||
};
|
||||
|
||||
class WavContext {
|
||||
public:
|
||||
AudioFragment fragment;
|
||||
|
||||
struct {
|
||||
FIL file;
|
||||
uint8_t codec;
|
||||
uint32_t freq;
|
||||
uint32_t size;
|
||||
uint8_t resampleRatio;
|
||||
uint16_t readSize;
|
||||
} state;
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
fragment.clear();
|
||||
}
|
||||
|
||||
int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
|
||||
};
|
||||
|
||||
class MixedContext {
|
||||
public:
|
||||
union {
|
||||
AudioFragment fragment;
|
||||
ToneContext tone;
|
||||
WavContext wav;
|
||||
};
|
||||
|
||||
int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
|
||||
};
|
||||
|
||||
bool dacQueue(AudioBuffer *buffer);
|
||||
|
@ -130,7 +155,7 @@ class AudioQueue {
|
|||
|
||||
void start();
|
||||
|
||||
void play(uint16_t freq, uint16_t len, uint16_t pause=0, uint8_t flags=0, int8_t freqIncr=0);
|
||||
void playTone(uint16_t freq, uint16_t len, uint16_t pause=0, uint8_t flags=0, int8_t freqIncr=0);
|
||||
|
||||
void playFile(const char *filename, uint8_t flags=0, uint8_t id=0);
|
||||
|
||||
|
@ -178,19 +203,16 @@ class AudioQueue {
|
|||
|
||||
void wakeup();
|
||||
|
||||
int mixAudioContext(AudioContext &context, AudioBuffer *buffer, int beepVolume, int wavVolume, unsigned int fade);
|
||||
int mixBeep(AudioContext &context, AudioBuffer *buffer, int volume, unsigned int fade);
|
||||
int mixWav(AudioContext &context, AudioBuffer *buffer, int volume, unsigned int fade);
|
||||
|
||||
volatile bool state;
|
||||
uint8_t ridx;
|
||||
uint8_t widx;
|
||||
|
||||
AudioFragment fragments[AUDIO_QUEUE_LENGTH];
|
||||
|
||||
AudioContext backgroundContext; // for background music / vario
|
||||
AudioContext currentContext;
|
||||
AudioContext foregroundContext; // for important beeps
|
||||
MixedContext normalContext;
|
||||
WavContext backgroundContext;
|
||||
ToneContext priorityContext;
|
||||
ToneContext varioContext;
|
||||
|
||||
AudioBuffer buffers[AUDIO_BUFFER_COUNT];
|
||||
uint8_t bufferRIdx;
|
||||
|
@ -254,13 +276,11 @@ void audioStart();
|
|||
#define AUDIO_INACTIVITY() AUDIO_BUZZER(audioEvent(AU_INACTIVITY), beep(3))
|
||||
#define AUDIO_MIX_WARNING(x) AUDIO_BUZZER(audioEvent(AU_MIX_WARNING_1+x-1), beep(1))
|
||||
#define AUDIO_POT_MIDDLE(x) AUDIO_BUZZER(audioEvent(AU_STICK1_MIDDLE+x), beep(2))
|
||||
#define AUDIO_VARIO_UP() audioEvent(AU_KEYPAD_UP)
|
||||
#define AUDIO_VARIO_DOWN() audioEvent(AU_KEYPAD_DOWN)
|
||||
#define AUDIO_TRIM_MIDDLE(f) AUDIO_BUZZER(audioEvent(AU_TRIM_MIDDLE, f), beep(2))
|
||||
#define AUDIO_TRIM_END(f) AUDIO_BUZZER(audioEvent(AU_TRIM_END, f), beep(2))
|
||||
#define AUDIO_TRIM(event, f) AUDIO_BUZZER(audioEvent(AU_TRIM_MOVE, f), { if (!IS_KEY_FIRST(event)) warble = true; beep(1); })
|
||||
#define AUDIO_PLAY(p) audioEvent(p)
|
||||
#define AUDIO_VARIO(f, t) audioQueue.play(f, t, 0, PLAY_BACKGROUND)
|
||||
#define AUDIO_VARIO(fq, t, p, f) audioQueue.playTone(fq, t, p, f)
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#define AUDIO_A1_ORANGE() audioEvent(AU_A1_ORANGE)
|
||||
|
|
|
@ -149,10 +149,14 @@ enum menuGeneralSetupItems {
|
|||
IF_VOICE(ITEM_SETUP_SPEAKER_VOLUME)
|
||||
IF_CPUARM(ITEM_SETUP_BEEP_VOLUME)
|
||||
IF_CPUARM(ITEM_SETUP_WAV_VOLUME)
|
||||
IF_CPUARM(ITEM_SETUP_VARIO_VOLUME)
|
||||
IF_CPUARM(ITEM_SETUP_BACKGROUND_VOLUME)
|
||||
ITEM_SETUP_BEEP_LENGTH,
|
||||
IF_AUDIO(ITEM_SETUP_SPEAKER_PITCH)
|
||||
IF_CPUARM(ITEM_SETUP_VARIO_LABEL)
|
||||
IF_CPUARM(ITEM_SETUP_VARIO_VOLUME)
|
||||
IF_CPUARM(ITEM_SETUP_VARIO_PITCH)
|
||||
IF_CPUARM(ITEM_SETUP_VARIO_RANGE)
|
||||
IF_CPUARM(ITEM_SETUP_VARIO_REPEAT)
|
||||
IF_HAPTIC(ITEM_SETUP_HAPTIC_LABEL)
|
||||
IF_HAPTIC(ITEM_SETUP_HAPTIC_MODE)
|
||||
IF_HAPTIC(ITEM_SETUP_HAPTIC_LENGTH)
|
||||
|
@ -211,7 +215,7 @@ void menuGeneralSetup(uint8_t event)
|
|||
}
|
||||
#endif
|
||||
|
||||
MENU(STR_MENURADIOSETUP, menuTabDiag, e_Setup, ITEM_SETUP_MAX+1, {0, IF_RTCLOCK(2) IF_RTCLOCK(2) IF_BATTGRAPH(1) LABEL(SOUND), IF_AUDIO(0) IF_BUZZER(0) IF_VOICE(0) IF_CPUARM(0) IF_CPUARM(0) IF_CPUARM(0) IF_CPUARM(0) 0, IF_AUDIO(0) IF_HAPTIC(LABEL(HAPTIC)) IF_HAPTIC(0) IF_HAPTIC(0) IF_HAPTIC(0) 0, LABEL(ALARMS), 0, CASE_PCBSKY9X(0) CASE_PCBSKY9X(0) 0, 0, 0, IF_ROTARY_ENCODERS(0) LABEL(BACKLIGHT), 0, 0, IF_CPUARM(0) CASE_PWM_BACKLIGHT(0) CASE_PWM_BACKLIGHT(0) 0, IF_SPLASH(0) IF_GPS(0) IF_GPS(0) IF_PXX(0) IF_CPUARM(0) IF_CPUARM(0) IF_FAI_CHOICE(0) 0, LABEL(TX_MODE), CASE_PCBTARANIS(0) 1/*to force edit mode*/});
|
||||
MENU(STR_MENURADIOSETUP, menuTabDiag, e_Setup, ITEM_SETUP_MAX+1, {0, IF_RTCLOCK(2) IF_RTCLOCK(2) IF_BATTGRAPH(1) LABEL(SOUND), IF_AUDIO(0) IF_BUZZER(0) IF_VOICE(0) IF_CPUARM(0) IF_CPUARM(0) IF_CPUARM(0) 0, IF_AUDIO(0) IF_CPUARM(LABEL(VARIO)) IF_CPUARM(0) IF_CPUARM(0) IF_CPUARM(0) IF_CPUARM(0) IF_HAPTIC(LABEL(HAPTIC)) IF_HAPTIC(0) IF_HAPTIC(0) IF_HAPTIC(0) 0, LABEL(ALARMS), 0, CASE_PCBSKY9X(0) CASE_PCBSKY9X(0) 0, 0, 0, IF_ROTARY_ENCODERS(0) LABEL(BACKLIGHT), 0, 0, IF_CPUARM(0) CASE_PWM_BACKLIGHT(0) CASE_PWM_BACKLIGHT(0) 0, IF_SPLASH(0) IF_GPS(0) IF_GPS(0) IF_PXX(0) IF_CPUARM(0) IF_CPUARM(0) IF_FAI_CHOICE(0) 0, LABEL(TX_MODE), CASE_PCBTARANIS(0) 1/*to force edit mode*/});
|
||||
|
||||
uint8_t sub = m_posVert - 1;
|
||||
|
||||
|
@ -357,9 +361,6 @@ void menuGeneralSetup(uint8_t event)
|
|||
case ITEM_SETUP_WAV_VOLUME:
|
||||
SLIDER_5POS(y, g_eeGeneral.wavVolume, STR_WAV_VOLUME, event, attr);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_VOLUME:
|
||||
SLIDER_5POS(y, g_eeGeneral.varioVolume, STR_VARIO_VOLUME, event, attr);
|
||||
break;
|
||||
case ITEM_SETUP_BACKGROUND_VOLUME:
|
||||
SLIDER_5POS(y, g_eeGeneral.backgroundVolume, STR_BG_VOLUME, event, attr);
|
||||
break;
|
||||
|
@ -379,6 +380,33 @@ void menuGeneralSetup(uint8_t event)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_SETUP_VARIO_LABEL:
|
||||
lcd_putsLeft(y, STR_VARIO);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_VOLUME:
|
||||
SLIDER_5POS(y, g_eeGeneral.varioVolume, TR_SPEAKER_VOLUME, event, attr);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_PITCH:
|
||||
lcd_putsLeft(y, "\001Pitch at Zero");
|
||||
lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10), attr|LEFT);
|
||||
lcd_putsAtt(lcdLastPos, y, "Hz", attr);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioPitch, -40, 40);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_RANGE:
|
||||
lcd_putsLeft(y, "\001Pitch at Max");
|
||||
lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10)+VARIO_FREQUENCY_RANGE+(g_eeGeneral.varioRange*10), attr|LEFT);
|
||||
lcd_putsAtt(lcdLastPos, y, "Hz", attr);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioRange, -80, 80);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_REPEAT:
|
||||
lcd_putsLeft(y, "\001Repeat at Zero");
|
||||
lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_REPEAT_ZERO+(g_eeGeneral.varioRepeat*10), attr|LEFT);
|
||||
lcd_putsAtt(lcdLastPos, y, "ms", attr);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioRepeat, -30, 50);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(HAPTIC)
|
||||
case ITEM_SETUP_HAPTIC_LABEL:
|
||||
lcd_putsLeft(y, STR_HAPTIC_LABEL);
|
||||
|
|
|
@ -5643,10 +5643,7 @@ void menuModelTelemetry(uint8_t event)
|
|||
}
|
||||
#else
|
||||
lcd_outdezAtt(TELEM_COL2, y, -10+g_model.frsky.varioMin, (m_posHorz<=0 ? attr : 0)|LEFT);
|
||||
if (g_model.frsky.varioCenterMin == -16)
|
||||
lcd_putsAtt(TELEM_COL2+4*FW-2, y, STR_OFF, m_posHorz==1 ? attr : 0);
|
||||
else
|
||||
lcd_outdezAtt(TELEM_COL2+7*FW-2, y, -5+g_model.frsky.varioCenterMin, ((m_posHorz<0 || m_posHorz==1) ? attr : 0)|PREC1);
|
||||
lcd_outdezAtt(TELEM_COL2+7*FW-2, y, -5+g_model.frsky.varioCenterMin, ((m_posHorz<0 || m_posHorz==1) ? attr : 0)|PREC1);
|
||||
lcd_outdezAtt(TELEM_COL2+10*FW, y, 5+g_model.frsky.varioCenterMax, ((m_posHorz<0 || m_posHorz==2) ? attr : 0)|PREC1);
|
||||
lcd_outdezAtt(TELEM_COL2+13*FW+2, y, 10+g_model.frsky.varioMax, ((m_posHorz<0 || m_posHorz==3) ? attr : 0));
|
||||
if (attr && (s_editMode>0 || p1valdiff)) {
|
||||
|
|
|
@ -114,7 +114,55 @@ void getGpsDistance()
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(FRSKY) && defined(VARIO)
|
||||
#if defined(CPUARM)
|
||||
|
||||
void varioWakeup()
|
||||
{
|
||||
if (isFunctionActive(FUNCTION_VARIO)) {
|
||||
int varioFreq, varioDuration, varioPause=0;
|
||||
uint8_t varioFlags;
|
||||
|
||||
int verticalSpeed = frskyData.hub.varioSpeed;
|
||||
|
||||
#if 0
|
||||
if (g_model.frsky.varioSource == VARIO_SOURCE_DTE) {
|
||||
#warning "Ele stick for vario tests"
|
||||
verticalSpeed = getValue(MIXSRC_Ele);
|
||||
}
|
||||
#endif
|
||||
|
||||
int varioCenterMin = (int)g_model.frsky.varioCenterMin * 10 - 50;
|
||||
int varioCenterMax = (int)g_model.frsky.varioCenterMax * 10 + 50;
|
||||
int varioMax = (10+(int)g_model.frsky.varioMax) * 100;
|
||||
int varioMin = (-10+(int)g_model.frsky.varioMin) * 100;
|
||||
|
||||
if (verticalSpeed > varioMax)
|
||||
verticalSpeed = varioMax;
|
||||
else if (verticalSpeed < varioMin)
|
||||
verticalSpeed = varioMin;
|
||||
|
||||
if (verticalSpeed > varioCenterMin) {
|
||||
varioFreq = VARIO_FREQUENCY_ZERO + (g_eeGeneral.varioPitch*10) + (((VARIO_FREQUENCY_RANGE+(g_eeGeneral.varioRange*10)) * (verticalSpeed-varioCenterMin)) / varioMax);
|
||||
int varioPeriod = VARIO_REPEAT_MAX + ((VARIO_REPEAT_ZERO+(g_eeGeneral.varioRepeat*10)-VARIO_REPEAT_MAX) * (varioMax-verticalSpeed) * (varioMax-verticalSpeed)) / ((varioMax-varioCenterMin) * (varioMax-varioCenterMin));
|
||||
if (verticalSpeed >= varioCenterMax || varioCenterMin == varioCenterMax)
|
||||
varioDuration = varioPeriod / 5;
|
||||
else
|
||||
varioDuration = varioPeriod * (85 - (((verticalSpeed-varioCenterMin) * 25) / (varioCenterMax-varioCenterMin))) / 100;
|
||||
varioPause = varioPeriod - varioDuration;
|
||||
varioFlags = PLAY_BACKGROUND;
|
||||
}
|
||||
else {
|
||||
varioFreq = VARIO_FREQUENCY_ZERO + (g_eeGeneral.varioPitch*10) - (((VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10)-((VARIO_FREQUENCY_ZERO + (g_eeGeneral.varioPitch*10))/2)) * (verticalSpeed-varioCenterMin)) / varioMin);
|
||||
varioDuration = 80; // continuous beep: we will enter again here before the tone ends
|
||||
varioFlags = PLAY_BACKGROUND|PLAY_NOW;
|
||||
}
|
||||
|
||||
AUDIO_VARIO(varioFreq, varioDuration, varioPause, varioFlags);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(FRSKY) && defined(VARIO)
|
||||
|
||||
void varioWakeup()
|
||||
{
|
||||
static tmr10ms_t s_varioTmr;
|
||||
|
@ -135,60 +183,35 @@ void varioWakeup()
|
|||
verticalSpeed = (verticalSpeed * 10) / ((varioMax-varioCenterMax) / 100);
|
||||
|
||||
if ((int16_t)(s_varioTmr-tmr10ms) < 0) {
|
||||
uint8_t SoundVarioBeepTime = (1600 - verticalSpeed) / 100;
|
||||
uint8_t SoundVarioBeepFreq = (verticalSpeed * 10 + 16000) >> 8;
|
||||
s_varioTmr = tmr10ms + (SoundVarioBeepTime*2);
|
||||
AUDIO_VARIO(SoundVarioBeepFreq, SoundVarioBeepTime);
|
||||
uint8_t varioFreq = (verticalSpeed * 10 + 16000) >> 8;
|
||||
uint8_t varioDuration = (1600 - verticalSpeed) / 100;
|
||||
s_varioTmr = tmr10ms + (varioDuration*2);
|
||||
AUDIO_VARIO(varioFreq, varioDuration);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int16_t varioCenterMax = (int16_t)g_model.frsky.varioCenterMax * 10 + 50;
|
||||
if (verticalSpeed >= varioCenterMax) {
|
||||
verticalSpeed = verticalSpeed - varioCenterMax;
|
||||
int16_t varioMax = (10+(int16_t)g_model.frsky.varioMax) * 100;
|
||||
if (verticalSpeed > varioMax) verticalSpeed = varioMax;
|
||||
verticalSpeed = (verticalSpeed * 10) / ((varioMax-varioCenterMax) / 100);
|
||||
}
|
||||
else {
|
||||
int16_t varioCenterMin = (int16_t)g_model.frsky.varioCenterMin * 10 - 50;
|
||||
if (verticalSpeed <= varioCenterMin) {
|
||||
verticalSpeed = verticalSpeed - varioCenterMin;
|
||||
int16_t varioMin = (-10+(int16_t)g_model.frsky.varioMin) * 100;
|
||||
if (verticalSpeed < varioMin) verticalSpeed = varioMin;
|
||||
verticalSpeed = (verticalSpeed * 10) / ((varioCenterMin-varioMin) / 100);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int varioCenterMin = (int)g_model.frsky.varioCenterMin * 10 - 50;
|
||||
int varioCenterMax = (int)g_model.frsky.varioCenterMax * 10 + 50;
|
||||
int varioMax = (10+(int)g_model.frsky.varioMax) * 100;
|
||||
int varioMin = (-10+(int)g_model.frsky.varioMin) * 100;
|
||||
|
||||
if (verticalSpeed < 0 || (int16_t)(s_varioTmr-tmr10ms) < 0) {
|
||||
#if defined(CPUARM)
|
||||
int SoundVarioBeepTime;
|
||||
int SoundVarioBeepFreq;
|
||||
if (verticalSpeed > varioMax)
|
||||
verticalSpeed = varioMax;
|
||||
else if (verticalSpeed < varioMin)
|
||||
verticalSpeed = varioMin;
|
||||
|
||||
if ((int16_t)(s_varioTmr - tmr10ms) < 0) {
|
||||
uint8_t varioFreq, varioDuration;
|
||||
if (verticalSpeed > 0) {
|
||||
SoundVarioBeepTime = max(5, 320 - (verticalSpeed >> 2));
|
||||
SoundVarioBeepFreq = 1000 + verticalSpeed;
|
||||
varioFreq = (verticalSpeed * 4 + 8000) >> 7;
|
||||
varioDuration = (8000 - verticalSpeed * 5) / 100;
|
||||
}
|
||||
else {
|
||||
SoundVarioBeepTime = 80;
|
||||
SoundVarioBeepFreq = (verticalSpeed * 3 + 8000) >> 3;
|
||||
varioFreq = (verticalSpeed * 3 + 8000) >> 7;
|
||||
varioDuration = 20;
|
||||
}
|
||||
s_varioTmr = tmr10ms + (SoundVarioBeepTime/5);
|
||||
#else
|
||||
uint8_t SoundVarioBeepTime;
|
||||
uint8_t SoundVarioBeepFreq;
|
||||
if (verticalSpeed > 0) {
|
||||
SoundVarioBeepTime = (8000 - verticalSpeed * 5) / 100;
|
||||
SoundVarioBeepFreq = (verticalSpeed * 4 + 8000) >> 7;
|
||||
}
|
||||
else {
|
||||
SoundVarioBeepTime = 20;
|
||||
SoundVarioBeepFreq = (verticalSpeed * 3 + 8000) >> 7;
|
||||
}
|
||||
s_varioTmr = tmr10ms + (SoundVarioBeepTime/2);
|
||||
#endif
|
||||
AUDIO_VARIO(SoundVarioBeepFreq, SoundVarioBeepTime);
|
||||
s_varioTmr = tmr10ms + (varioDuration/2);
|
||||
AUDIO_VARIO(varioFreq, varioDuration);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -220,4 +243,5 @@ void varioWakeup()
|
|||
s_varioTmr = tmr10ms;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -239,6 +239,9 @@ enum BeeperMode {
|
|||
int8_t beepVolume; \
|
||||
int8_t wavVolume; \
|
||||
int8_t varioVolume; \
|
||||
int8_t varioPitch; \
|
||||
int8_t varioRange; \
|
||||
int8_t varioRepeat; \
|
||||
int8_t backgroundVolume;
|
||||
#endif
|
||||
|
||||
|
@ -1015,7 +1018,11 @@ enum VarioSource {
|
|||
VARIO_SOURCE_VARIO,
|
||||
VARIO_SOURCE_A1,
|
||||
VARIO_SOURCE_A2,
|
||||
VARIO_SOURCE_LAST = VARIO_SOURCE_A2
|
||||
#if defined(FRSKY_SPORT)
|
||||
VARIO_SOURCE_DTE,
|
||||
#endif
|
||||
VARIO_SOURCE_COUNT,
|
||||
VARIO_SOURCE_LAST = VARIO_SOURCE_COUNT-1
|
||||
};
|
||||
|
||||
#if defined(FRSKY_HUB)
|
||||
|
|
|
@ -2663,7 +2663,7 @@ uint8_t checkTrim(uint8_t event)
|
|||
thro = (idx==THR_STICK && g_model.thrTrim);
|
||||
#endif
|
||||
int8_t trimInc = g_model.trimInc + 1;
|
||||
int8_t v = (trimInc==-1) ? min(32, abs(before)/4+1) : (1 << trimInc);
|
||||
int8_t v = (trimInc==-1) ? min(32, abs(before)/4+1) : (1 << trimInc); // TODO flash saving if (trimInc < 0)
|
||||
if (thro) v = 4; // if throttle trim and trim trottle then step=4
|
||||
int16_t after = (k&1) ? before + v : before - v; // positive = k&1
|
||||
#if defined(CPUARM)
|
||||
|
@ -3601,11 +3601,6 @@ void evalFunctions()
|
|||
lastFunctionTime[i] = 0;
|
||||
#if defined(CPUARM)
|
||||
fnSwitchDuration[i] = 0;
|
||||
#endif
|
||||
#if defined(CPUARM) && defined(SDCARD)
|
||||
if (CFN_FUNC(sd) == FUNC_BACKGND_MUSIC && isFunctionActive(FUNCTION_BACKGND_MUSIC)) {
|
||||
STOP_PLAY(i+1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -4671,7 +4666,7 @@ void perMain()
|
|||
|
||||
checkBacklight();
|
||||
|
||||
#if defined(FRSKY) || defined(MAVLINK)
|
||||
#if !defined(CPUARM) && (defined(FRSKY) || defined(MAVLINK))
|
||||
telemetryWakeup();
|
||||
#endif
|
||||
|
||||
|
@ -5329,6 +5324,10 @@ void mixerTask(void * pdata)
|
|||
CoLeaveMutexSection(mixerMutex);
|
||||
if (tick10ms) checkTrims();
|
||||
|
||||
#if defined(FRSKY) || defined(MAVLINK)
|
||||
telemetryWakeup();
|
||||
#endif
|
||||
|
||||
if (heartbeat == HEART_WDT_CHECK) {
|
||||
wdt_reset();
|
||||
heartbeat = 0;
|
||||
|
|
|
@ -1354,6 +1354,10 @@ enum FunctionsActive {
|
|||
#endif
|
||||
};
|
||||
|
||||
#define VARIO_FREQUENCY_ZERO 700/*Hz*/
|
||||
#define VARIO_FREQUENCY_RANGE 1000/*Hz*/
|
||||
#define VARIO_REPEAT_ZERO 500/*ms*/
|
||||
#define VARIO_REPEAT_MAX 80/*ms*/
|
||||
|
||||
extern MASK_FUNC_TYPE activeFunctions;
|
||||
extern MASK_CFN_TYPE activeFnSwitches;
|
||||
|
|
|
@ -654,8 +654,9 @@ void telemetryWakeup()
|
|||
#endif
|
||||
|
||||
#if defined(VARIO)
|
||||
if (TELEMETRY_STREAMING() && !IS_FAI_ENABLED())
|
||||
if (TELEMETRY_STREAMING() && !IS_FAI_ENABLED()) {
|
||||
varioWakeup();
|
||||
}
|
||||
#endif
|
||||
|
||||
static tmr10ms_t alarmsCheckTime = 0;
|
||||
|
|
|
@ -303,11 +303,11 @@
|
|||
#define LEN_VOLTSRC "\003"
|
||||
#define TR_VOLTSRC "---""A1\0""A2\0""FAS""Cel"
|
||||
|
||||
#define LEN_VARIOSRC "\005"
|
||||
#define LEN_VARIOSRC "\004"
|
||||
#if defined(FRSKY_SPORT)
|
||||
#define TR_VARIOSRC "Vario""A1\0 ""A2\0"
|
||||
#define TR_VARIOSRC "VSpd""A1\0 ""A2\0 ""dTE\0"
|
||||
#else
|
||||
#define TR_VARIOSRC "Alti\0""Alti+""Vario""A1\0 ""A2\0"
|
||||
#define TR_VARIOSRC "Alt\0""Alt+""VSpd""A1\0 ""A2\0"
|
||||
#endif
|
||||
|
||||
#define LEN_VSCREEN "\004"
|
||||
|
@ -620,7 +620,7 @@
|
|||
#define TR_ALARMSWARN "ALARMS"
|
||||
#define TR_SWITCHWARN TR("SWITCH","CONTROL")
|
||||
#define TR_INVERT_THR TR("Invert Thr?","Invert Throttle?")
|
||||
#define TR_SPEAKER_VOLUME INDENT "Volume"
|
||||
#define TR_SPEAKER_VOLUME INDENT "Volume" // TODO could be TR_VOLUME ?
|
||||
#define TR_LCD "LCD"
|
||||
#define TR_BRIGHTNESS INDENT "Brightness"
|
||||
#define TR_CPU_TEMP "CPU Temp.\016>"
|
||||
|
@ -798,7 +798,7 @@
|
|||
|
||||
#define TR_BEEP_VOLUME "Beep Volume"
|
||||
#define TR_WAV_VOLUME "Wav Volume"
|
||||
#define TR_VARIO_VOLUME "Vario Volume"
|
||||
#define TR_VARIO_VOLUME "Vario Volume" // TODO may be removed
|
||||
#define TR_BG_VOLUME "Bg Volume"
|
||||
|
||||
#define TR_TOP_BAR "Top Bar"
|
||||
|
|
51
radio/util/codecs.py
Normal file
51
radio/util/codecs.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
#!/bin/env python
|
||||
|
||||
SIGN_BIT = (0x80) # Sign bit for a A-law byte.
|
||||
QUANT_MASK = (0xf) # Quantization field mask.
|
||||
SEG_SHIFT = (4) # Left shift for segment number.
|
||||
SEG_MASK = (0x70) # Segment field mask.
|
||||
BIAS = (0x84) # Bias for linear code.
|
||||
|
||||
def alaw2linear(a_val):
|
||||
a_val ^= 0x55
|
||||
|
||||
t = a_val & QUANT_MASK
|
||||
seg = (a_val & SEG_MASK) >> SEG_SHIFT
|
||||
if (seg):
|
||||
t = (t + t + 1 + 32) << (seg + 2)
|
||||
else:
|
||||
t = (t + t + 1 ) << 3
|
||||
|
||||
if a_val & SIGN_BIT:
|
||||
return t
|
||||
else:
|
||||
return -t
|
||||
|
||||
def ulaw2linear(u_val):
|
||||
# Complement to obtain normal u-law value.
|
||||
u_val = ~u_val
|
||||
|
||||
# Extract and bias the quantization bits. Then
|
||||
# shift up by the segment number and subtract out the bias.
|
||||
t = ((u_val & QUANT_MASK) << 3) + BIAS
|
||||
t <<= (u_val & SEG_MASK) >> SEG_SHIFT
|
||||
|
||||
if u_val & SIGN_BIT:
|
||||
return (BIAS - t)
|
||||
else:
|
||||
return (t - BIAS)
|
||||
|
||||
def pcmTable(fn):
|
||||
result = []
|
||||
for i in range(256):
|
||||
result.append(fn(i))
|
||||
return result
|
||||
|
||||
def tableToString(name, table):
|
||||
result = 'const int16_t ' + name + '[256] = { '
|
||||
result += ', '.join([str(i) for i in table])
|
||||
result += ' };'
|
||||
return result
|
||||
|
||||
print tableToString('alawTable', pcmTable(alaw2linear))
|
||||
print tableToString('ulawTable', pcmTable(ulaw2linear))
|
29
radio/util/sinus.py
Normal file
29
radio/util/sinus.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
#!/bin/env python
|
||||
|
||||
import math
|
||||
|
||||
samples = 1024
|
||||
amplitudes = (32000, 0, 4000, 0, 4000)
|
||||
|
||||
max = 0
|
||||
min = 0
|
||||
|
||||
for i in range(samples):
|
||||
sample = 0.0
|
||||
for harmonic, amplitude in enumerate(amplitudes):
|
||||
sample += math.sin(math.pi*2*i*(harmonic+1)/samples) * amplitude / 2
|
||||
sample = int(sample)
|
||||
if sample > max:
|
||||
max = sample
|
||||
elif sample < min:
|
||||
min = sample
|
||||
print "%d," % sample,
|
||||
if i % 10 == 9:
|
||||
print
|
||||
|
||||
print
|
||||
print 'Range is:', min, max
|
||||
|
||||
if max > 32767 or min < -32768:
|
||||
print "Invalid range!"
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue