1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-23 08:15:17 +03:00

Audio wav files may not be queued and repeated as others.

This commit is contained in:
bsongis 2012-07-04 10:33:17 +00:00
parent 8989ce4e6c
commit 602ff6ca46
6 changed files with 273 additions and 249 deletions

View file

@ -14,7 +14,7 @@
/ Functions and Buffer Configurations / Functions and Buffer Configurations
/----------------------------------------------------------------------------*/ /----------------------------------------------------------------------------*/
#define _FS_TINY 1 /* 0:Normal or 1:Tiny */ #define _FS_TINY 0 /* 0:Normal or 1:Tiny */
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system /* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
/ object instead of the sector buffer in the individual file object for file / object instead of the sector buffer in the individual file object for file
/ data transfer. This reduces memory consumption 512 bytes each file object. */ / data transfer. This reduces memory consumption 512 bytes each file object. */

View file

@ -136,36 +136,11 @@ void alawInit()
alawTable[i] = (0x8000 + alaw2linear(i)) >> 4; alawTable[i] = (0x8000 + alaw2linear(i)) >> 4;
} }
uint8_t audioState = 0; AudioQueue audioQueue;
uint8_t t_queueRidx; AudioQueue::AudioQueue()
uint8_t t_queueWidx;
uint8_t toneFreq;
int8_t toneFreqIncr;
uint8_t toneTimeLeft;
uint8_t tonePause;
uint8_t tone2Freq;
uint8_t tone2TimeLeft;
uint8_t tone2Pause;
char toneWavFile[32+1] = "";
// queue arrays
uint8_t queueToneFreq[AUDIO_QUEUE_LENGTH];
int8_t queueToneFreqIncr[AUDIO_QUEUE_LENGTH];
uint8_t queueToneLength[AUDIO_QUEUE_LENGTH];
uint8_t queueTonePause[AUDIO_QUEUE_LENGTH];
uint8_t queueToneRepeat[AUDIO_QUEUE_LENGTH];
void audioInit()
{ {
toneTimeLeft = 0; memset(this, 0, sizeof(AudioQueue));
tonePause = 0;
t_queueRidx = 0;
t_queueWidx = 0;
} }
void audioTimerHandle(void) void audioTimerHandle(void)
@ -183,122 +158,129 @@ extern uint16_t Sine_values[];
uint8_t pcmCodec; uint8_t pcmCodec;
void audioTask(void* pdata) void audioTask(void* pdata)
{
while (1) {
CoWaitForSingleFlag(audioFlag, 0);
audioQueue.wakeup();
}
}
void AudioQueue::wakeup()
{ {
#if defined(SDCARD) && !defined(SIMU) #if defined(SDCARD) && !defined(SIMU)
static FIL wavFile; static FIL wavFile;
#endif #endif
while (1) {
CoWaitForSingleFlag(audioFlag, 0);
audioState = 1; // TODO #define
#if defined(SDCARD) && !defined(SIMU) #if defined(SDCARD) && !defined(SIMU)
if (toneWavFile[0]) { if (current.file[0]) {
FRESULT result = FR_OK; FRESULT result = FR_OK;
UINT read = 0; UINT read = 0;
uint16_t * bufdata = wavSamplesBuffer; uint16_t * bufdata = wavSamplesBuffer;
if (toneWavFile[1]) { if (current.file[1]) {
result = f_open(&wavFile, toneWavFile, FA_OPEN_EXISTING | FA_READ); result = f_open(&wavFile, current.file, FA_OPEN_EXISTING | FA_READ);
if (result == FR_OK) { if (result == FR_OK) {
result = f_read(&wavFile, (uint8_t *)wavSamplesArray, WAV_HEADER_SIZE, &read); result = f_read(&wavFile, (uint8_t *)wavSamplesArray, WAV_HEADER_SIZE, &read);
if (result == FR_OK && read == WAV_HEADER_SIZE && !memcmp(wavSamplesArray, "RIFF", 4)) { if (result == FR_OK && read == WAV_HEADER_SIZE && !memcmp(wavSamplesArray, "RIFF", 4)) {
CoSetFlag(audioFlag); CoSetFlag(audioFlag);
bufdata = wavSamplesArray; bufdata = wavSamplesArray;
wavSamplesBuffer = wavSamplesArray + WAV_BUFFER_SIZE; wavSamplesBuffer = wavSamplesArray + WAV_BUFFER_SIZE;
pcmCodec = wavSamplesArray[10]; pcmCodec = wavSamplesArray[10];
setFrequency(wavSamplesArray[12]); setFrequency(wavSamplesArray[12]);
if (pcmCodec != CODEC_ID_PCM_S16LE) { if (pcmCodec != CODEC_ID_PCM_S16LE) {
result = f_read(&wavFile, (uint8_t *)wavSamplesArray, 12, &read); result = f_read(&wavFile, (uint8_t *)wavSamplesArray, 12, &read);
}
}
else {
result = FR_DENIED;
} }
} }
} else {
result = FR_DENIED;
read = 0; }
uint16_t bufsize = (pcmCodec == CODEC_ID_PCM_S16LE ? 2*WAV_BUFFER_SIZE : WAV_BUFFER_SIZE);
if (result != FR_OK || f_read(&wavFile, (uint8_t *)bufdata, bufsize, &read) != FR_OK || read != bufsize) {
DACC->DACC_TNCR = read/4;
toneStop();
toneWavFile[0] = '\0';
toneWavFile[1] = '\0';
f_close(&wavFile);
audioState = 0;
}
if (pcmCodec == CODEC_ID_PCM_S16LE) {
read /= 2;
uint32_t i = 0;
for (; i<read; i++)
bufdata[i] = ((uint16_t)0x8000 + ((int16_t)(bufdata[i]))) >> 4;
for (; i<WAV_BUFFER_SIZE; i++)
bufdata[i] = 0x8000;
}
else if (pcmCodec == CODEC_ID_PCM_ALAW) {
int32_t i;
for (i=read-1; i>=0; i--)
bufdata[i] = alawTable[((uint8_t *)bufdata)[i]];
for (i=read; i<WAV_BUFFER_SIZE; i++)
bufdata[i] = 0x8000;
}
if (toneWavFile[1]) {
toneWavFile[1] = '\0';
register Dacc *dacptr = DACC;
dacptr->DACC_TPR = CONVERT_PTR(wavSamplesArray);
dacptr->DACC_TNPR = CONVERT_PTR(wavSamplesBuffer);
dacptr->DACC_TCR = WAV_BUFFER_SIZE/2;
dacptr->DACC_TNCR = WAV_BUFFER_SIZE/2;
toneStart();
} }
} }
else
#endif read = 0;
if (toneTimeLeft > 0) { uint16_t bufsize = (pcmCodec == CODEC_ID_PCM_S16LE ? 2*WAV_BUFFER_SIZE : WAV_BUFFER_SIZE);
// TODO function for that ... if (result != FR_OK || f_read(&wavFile, (uint8_t *)bufdata, bufsize, &read) != FR_OK || read != bufsize) {
setFrequency(toneFreq * 6100 / 2); current.file[0] = 0;
if (toneFreqIncr) { current.file[1] = 0;
CoSetTmrCnt(audioTimer, 5/*10ms*/, 0); if (pcmCodec == CODEC_ID_PCM_S16LE) {
toneFreq += toneFreqIncr; DACC->DACC_TNCR = read/4;
toneTimeLeft--;
} }
else { else {
CoSetTmrCnt(audioTimer, toneTimeLeft*5, 0); DACC->DACC_TNCR = read/2;
toneTimeLeft = 0;
} }
toneStart();
CoStartTmr(audioTimer);
}
else if (tonePause > 0) {
CoSetTmrCnt(audioTimer, tonePause*5, 0);
tonePause = 0;
toneStop(); toneStop();
CoStartTmr(audioTimer); f_close(&wavFile);
}
else if (t_queueRidx != t_queueWidx) {
toneFreq = queueToneFreq[t_queueRidx];
toneTimeLeft = queueToneLength[t_queueRidx];
toneFreqIncr = queueToneFreqIncr[t_queueRidx];
tonePause = queueTonePause[t_queueRidx];
if (!queueToneRepeat[t_queueRidx]--) {
t_queueRidx = (t_queueRidx + 1) % AUDIO_QUEUE_LENGTH;
}
CoSetFlag(audioFlag); CoSetFlag(audioFlag);
} }
else if (tone2TimeLeft > 0) {
CoSetTmrCnt(audioTimer, tone2TimeLeft*5, 0); if (pcmCodec == CODEC_ID_PCM_S16LE) {
tone2TimeLeft = 0; read /= 2;
setFrequency(tone2Freq * 6100 / 2); uint32_t i = 0;
for (; i<read; i++)
bufdata[i] = ((uint16_t)0x8000 + ((int16_t)(bufdata[i]))) >> 4;
for (; i<WAV_BUFFER_SIZE; i++)
bufdata[i] = 0x8000;
}
else if (pcmCodec == CODEC_ID_PCM_ALAW) {
int32_t i;
for (i=read-1; i>=0; i--)
bufdata[i] = alawTable[((uint8_t *)bufdata)[i]];
for (i=read; i<WAV_BUFFER_SIZE; i++)
bufdata[i] = 0x8000;
}
if (current.file[1]) {
current.file[1] = 0;
register Dacc *dacptr = DACC;
dacptr->DACC_TPR = CONVERT_PTR(wavSamplesArray);
dacptr->DACC_TNPR = CONVERT_PTR(wavSamplesBuffer);
dacptr->DACC_TCR = WAV_BUFFER_SIZE/2;
dacptr->DACC_TNCR = WAV_BUFFER_SIZE/2;
toneStart(); toneStart();
CoStartTmr(audioTimer); }
}
else
#endif
if (current.duration > 0) {
// TODO function for that ...
setFrequency(current.freq * 6100 / 2);
if (current.freqIncr) {
CoSetTmrCnt(audioTimer, 5/*10ms*/, 0);
current.freq += current.freqIncr;
current.duration--;
} }
else { else {
audioState = 0; CoSetTmrCnt(audioTimer, current.duration*5, 0);
toneStop(); current.duration = 0;
} }
toneStart();
CoStartTmr(audioTimer);
}
else if (current.pause > 0) {
CoSetTmrCnt(audioTimer, current.pause*5, 0);
current.pause = 0;
toneStop();
CoStartTmr(audioTimer);
}
else if (ridx != widx) {
memcpy(&current, &fragments[ridx], sizeof(current));
if (!fragments[ridx].repeat--) {
ridx = (ridx + 1) % AUDIO_QUEUE_LENGTH;
}
CoSetFlag(audioFlag);
}
else if (background.duration > 0) {
CoSetTmrCnt(audioTimer, background.duration*5, 0);
background.duration = 0;
setFrequency(background.freq * 6100 / 2);
toneStart();
CoStartTmr(audioTimer);
}
else {
state = 0;
toneStop();
} }
} }
@ -314,24 +296,23 @@ inline uint8_t getToneLength(uint8_t tLen)
return result; return result;
} }
void pause(uint8_t tLen) void AudioQueue::pause(uint8_t tLen)
{ {
play(0, 0, tLen); // a pause play(0, 0, tLen); // a pause
} }
extern OS_MutexID audioMutex; extern OS_MutexID audioMutex;
void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, void AudioQueue::play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlags, int8_t tFreqIncr)
uint8_t tFlags, int8_t tFreqIncr)
{ {
CoEnterMutexSection(audioMutex); CoEnterMutexSection(audioMutex);
if (tFlags & PLAY_SOUND_VARIO) { if (tFlags & PLAY_SOUND_VARIO) {
tone2Freq = tFreq; background.freq = tFreq;
tone2TimeLeft = tLen; background.duration = tLen;
tone2Pause = tPause; background.pause = tPause;
if (audioState == 0) { if (state == 0) {
audioState = 1; state = 1;
CoSetFlag(audioFlag); CoSetFlag(audioFlag);
} }
} }
@ -340,14 +321,14 @@ void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause,
tFreq += g_eeGeneral.speakerPitch + BEEP_OFFSET; // add pitch compensator tFreq += g_eeGeneral.speakerPitch + BEEP_OFFSET; // add pitch compensator
} }
tLen = getToneLength(tLen); tLen = getToneLength(tLen);
if ((tFlags & PLAY_NOW) || !audioBusy()) { if ((tFlags & PLAY_NOW) || !busy()) {
toneWavFile[0] = '\0'; state = 1;
toneFreq = tFreq; current.file[0] = '\0';
toneTimeLeft = tLen; current.freq = tFreq;
tonePause = tPause; current.duration = tLen;
toneFreqIncr = tFreqIncr; current.pause = tPause;
t_queueWidx = t_queueRidx; current.freqIncr = tFreqIncr;
audioState = 1; widx = ridx;
CoSetFlag(audioFlag); CoSetFlag(audioFlag);
} }
else { else {
@ -356,14 +337,16 @@ void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause,
tFlags &= 0x0f; tFlags &= 0x0f;
if (tFlags) { if (tFlags) {
uint8_t next_queueWidx = (t_queueWidx + 1) % AUDIO_QUEUE_LENGTH; uint8_t next_widx = (widx + 1) % AUDIO_QUEUE_LENGTH;
if (next_queueWidx != t_queueRidx) { if (next_widx != ridx) {
queueToneFreq[t_queueWidx] = tFreq; AudioFragment & fragment = fragments[widx];
queueToneLength[t_queueWidx] = tLen; memset(&fragment, 0, sizeof(fragment));
queueTonePause[t_queueWidx] = tPause; fragment.freq = tFreq;
queueToneRepeat[t_queueWidx] = tFlags - 1; fragment.duration = tLen;
queueToneFreqIncr[t_queueWidx] = tFreqIncr; fragment.pause = tPause;
t_queueWidx = next_queueWidx; fragment.repeat = tFlags - 1;
fragment.freqIncr = tFreqIncr;
widx = next_widx;
} }
} }
} }
@ -371,10 +354,32 @@ void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause,
CoLeaveMutexSection(audioMutex); CoLeaveMutexSection(audioMutex);
} }
void playFile(const char *filename) void AudioQueue::playFile(const char *filename, uint8_t flags)
{ {
CoEnterMutexSection(audioMutex); CoEnterMutexSection(audioMutex);
strcpy(toneWavFile, filename);
if ((flags & PLAY_NOW) || !busy()) {
state = 1;
memset(&current, 0, sizeof(current));
strcpy(current.file, filename);
widx = ridx;
CoSetFlag(audioFlag);
}
else {
flags++;
}
flags &= 0x0f;
if (flags) {
uint8_t next_widx = (widx + 1) % AUDIO_QUEUE_LENGTH;
if (next_widx != ridx) {
AudioFragment & fragment = fragments[widx];
memset(&fragment, 0, sizeof(fragment));
strcpy(current.file, filename);
fragment.repeat = flags - 1;
widx = next_widx;
}
}
CoSetFlag(audioFlag); CoSetFlag(audioFlag);
CoLeaveMutexSection(audioMutex); CoLeaveMutexSection(audioMutex);
} }
@ -394,163 +399,163 @@ void audioEvent(uint8_t e, uint8_t f)
if (g_eeGeneral.beeperMode>0 || (g_eeGeneral.beeperMode==0 && e>=AU_TRIM_MOVE) || (g_eeGeneral.beeperMode>=-1 && e<=AU_ERROR)) { if (g_eeGeneral.beeperMode>0 || (g_eeGeneral.beeperMode==0 && e>=AU_TRIM_MOVE) || (g_eeGeneral.beeperMode>=-1 && e<=AU_ERROR)) {
if (e < AU_FRSKY_FIRST && isAudioFileAvailable(e, filename)) { if (e < AU_FRSKY_FIRST && isAudioFileAvailable(e, filename)) {
playFile(filename); audioQueue.playFile(filename);
} }
else if (e < AU_FRSKY_FIRST || !audioBusy()) { else if (e < AU_FRSKY_FIRST || !audioQueue.busy()) {
switch (e) { switch (e) {
// inactivity timer alert // inactivity timer alert
case AU_INACTIVITY: case AU_INACTIVITY:
play(70, 20, 4, 2|PLAY_NOW); audioQueue.play(70, 20, 4, 2|PLAY_NOW);
break; break;
// low battery in tx // low battery in tx
case AU_TX_BATTERY_LOW: case AU_TX_BATTERY_LOW:
if (!audioBusy()) { if (!audioQueue.busy()) {
play(60, 40, 6, 2, 1); audioQueue.play(60, 40, 6, 2, 1);
play(80, 40, 6, 2, -1); audioQueue.play(80, 40, 6, 2, -1);
} }
break; break;
// error // error
case AU_ERROR: case AU_ERROR:
play(BEEP_DEFAULT_FREQ, 50, 2, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ, 50, 2, PLAY_NOW);
break; break;
// keypad up (seems to be used when going left/right through system menu options. 0-100 scales etc) // keypad up (seems to be used when going left/right through system menu options. 0-100 scales etc)
case AU_KEYPAD_UP: case AU_KEYPAD_UP:
play(BEEP_KEY_UP_FREQ, 20, 2, PLAY_NOW); audioQueue.play(BEEP_KEY_UP_FREQ, 20, 2, PLAY_NOW);
break; break;
// keypad down (seems to be used when going left/right through system menu options. 0-100 scales etc) // keypad down (seems to be used when going left/right through system menu options. 0-100 scales etc)
case AU_KEYPAD_DOWN: case AU_KEYPAD_DOWN:
play(BEEP_KEY_DOWN_FREQ, 20, 2, PLAY_NOW); audioQueue.play(BEEP_KEY_DOWN_FREQ, 20, 2, PLAY_NOW);
break; break;
// menu display (also used by a few generic beeps) // menu display (also used by a few generic beeps)
case AU_MENUS: case AU_MENUS:
play(BEEP_DEFAULT_FREQ, 20, 4, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ, 20, 4, PLAY_NOW);
break; break;
// trim move // trim move
case AU_TRIM_MOVE: case AU_TRIM_MOVE:
play(f, 12, 2, PLAY_NOW); audioQueue.play(f, 12, 2, PLAY_NOW);
break; break;
// trim center // trim center
case AU_TRIM_MIDDLE: case AU_TRIM_MIDDLE:
play(f, 20, 4, PLAY_NOW); audioQueue.play(f, 20, 4, PLAY_NOW);
break; break;
// trim center // trim center
case AU_TRIM_END: case AU_TRIM_END:
play(f, 20, 4, PLAY_NOW); audioQueue.play(f, 20, 4, PLAY_NOW);
break; break;
// warning one // warning one
case AU_WARNING1: case AU_WARNING1:
play(BEEP_DEFAULT_FREQ, 20, 2, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ, 20, 2, PLAY_NOW);
break; break;
// warning two // warning two
case AU_WARNING2: case AU_WARNING2:
play(BEEP_DEFAULT_FREQ, 40, 2, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ, 40, 2, PLAY_NOW);
break; break;
// warning three // warning three
case AU_WARNING3: case AU_WARNING3:
play(BEEP_DEFAULT_FREQ, 50, 2, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ, 50, 2, PLAY_NOW);
break; break;
// startup tune // startup tune
case AU_TADA: case AU_TADA:
play(50, 20, 10); audioQueue.play(50, 20, 10);
play(90, 20, 10); audioQueue.play(90, 20, 10);
play(110, 10, 8, 2); audioQueue.play(110, 10, 8, 2);
break; break;
// pot/stick center // pot/stick center
case AU_POT_STICK_MIDDLE: case AU_POT_STICK_MIDDLE:
play(BEEP_DEFAULT_FREQ + 50, 20, 2, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ + 50, 20, 2, PLAY_NOW);
break; break;
// mix warning 1 // mix warning 1
case AU_MIX_WARNING_1: case AU_MIX_WARNING_1:
play(BEEP_DEFAULT_FREQ + 50, 12, 0, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ + 50, 12, 0, PLAY_NOW);
break; break;
// mix warning 2 // mix warning 2
case AU_MIX_WARNING_2: case AU_MIX_WARNING_2:
play(BEEP_DEFAULT_FREQ + 52, 12, 0, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ + 52, 12, 0, PLAY_NOW);
break; break;
// mix warning 3 // mix warning 3
case AU_MIX_WARNING_3: case AU_MIX_WARNING_3:
play(BEEP_DEFAULT_FREQ + 54, 12, 0, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ + 54, 12, 0, PLAY_NOW);
break; break;
// time 30 seconds left // time 30 seconds left
case AU_TIMER_30: case AU_TIMER_30:
play(BEEP_DEFAULT_FREQ + 50, 30, 6, 2|PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ + 50, 30, 6, 2|PLAY_NOW);
break; break;
// time 20 seconds left // time 20 seconds left
case AU_TIMER_20: case AU_TIMER_20:
play(BEEP_DEFAULT_FREQ + 50, 30, 6, 1|PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ + 50, 30, 6, 1|PLAY_NOW);
break; break;
// time 10 seconds left // time 10 seconds left
case AU_TIMER_10: case AU_TIMER_10:
play(BEEP_DEFAULT_FREQ + 50, 30, 6, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ + 50, 30, 6, PLAY_NOW);
break; break;
// time <3 seconds left // time <3 seconds left
case AU_TIMER_LT3: case AU_TIMER_LT3:
play(BEEP_DEFAULT_FREQ + 50, 30, 6, PLAY_NOW); audioQueue.play(BEEP_DEFAULT_FREQ + 50, 30, 6, PLAY_NOW);
break; break;
case AU_FRSKY_WARN1: case AU_FRSKY_WARN1:
play(BEEP_DEFAULT_FREQ+20,30,10,2); audioQueue.play(BEEP_DEFAULT_FREQ+20,30,10,2);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_WARN2: case AU_FRSKY_WARN2:
play(BEEP_DEFAULT_FREQ+30,30,10,2); audioQueue.play(BEEP_DEFAULT_FREQ+30,30,10,2);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_CHEEP: case AU_FRSKY_CHEEP:
play(BEEP_DEFAULT_FREQ+30,20,4,2,2); audioQueue.play(BEEP_DEFAULT_FREQ+30,20,4,2,2);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_RING: case AU_FRSKY_RING:
play(BEEP_DEFAULT_FREQ+25,10,4,10); audioQueue.play(BEEP_DEFAULT_FREQ+25,10,4,10);
play(BEEP_DEFAULT_FREQ+25,10,20,1); audioQueue.play(BEEP_DEFAULT_FREQ+25,10,20,1);
play(BEEP_DEFAULT_FREQ+25,10,4,10); audioQueue.play(BEEP_DEFAULT_FREQ+25,10,4,10);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_SCIFI: case AU_FRSKY_SCIFI:
play(80,20,6,2,-1); audioQueue.play(80,20,6,2,-1);
play(60,20,6,2,1); audioQueue.play(60,20,6,2,1);
play(70,20,2,0); audioQueue.play(70,20,2,0);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_ROBOT: case AU_FRSKY_ROBOT:
play(70,10,2,1); audioQueue.play(70,10,2,1);
play(50,30,4,1); audioQueue.play(50,30,4,1);
play(80,30,4,1); audioQueue.play(80,30,4,1);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_CHIRP: case AU_FRSKY_CHIRP:
play(BEEP_DEFAULT_FREQ+40,10,2,2); audioQueue.play(BEEP_DEFAULT_FREQ+40,10,2,2);
play(BEEP_DEFAULT_FREQ+54,10,2,3); audioQueue.play(BEEP_DEFAULT_FREQ+54,10,2,3);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_TADA: case AU_FRSKY_TADA:
play(50,10,10); audioQueue.play(50,10,10);
play(90,10,10); audioQueue.play(90,10,10);
play(110,6,8,2); audioQueue.play(110,6,8,2);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_CRICKET: case AU_FRSKY_CRICKET:
play(80,10,20,3); audioQueue.play(80,10,20,3);
play(80,10,40,1); audioQueue.play(80,10,40,1);
play(80,10,20,3); audioQueue.play(80,10,20,3);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_SIREN: case AU_FRSKY_SIREN:
play(10,40,10,2,1); audioQueue.play(10,40,10,2,1);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_ALARMC: case AU_FRSKY_ALARMC:
play(50,8,20,2); audioQueue.play(50,8,20,2);
play(70,16,40,1); audioQueue.play(70,16,40,1);
play(50,16,20,2); audioQueue.play(50,16,20,2);
play(70,8,40,1); audioQueue.play(70,8,40,1);
pause(200); audioQueue.pause(200);
break; break;
case AU_FRSKY_RATATA: case AU_FRSKY_RATATA:
play(BEEP_DEFAULT_FREQ+50,10,20,10); audioQueue.play(BEEP_DEFAULT_FREQ+50,10,20,10);
break; break;
case AU_FRSKY_TICK: case AU_FRSKY_TICK:
play(BEEP_DEFAULT_FREQ+50,10,100,2); audioQueue.play(BEEP_DEFAULT_FREQ+50,10,100,2);
pause(200); audioQueue.pause(200);
break; break;
default: default:
break; break;

View file

@ -31,7 +31,6 @@
* *
*/ */
#ifndef audio_h #ifndef audio_h
#define audio_h #define audio_h
@ -41,41 +40,61 @@
#define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+5) #define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+5)
#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-5) #define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-5)
extern uint8_t audioState; class ToneFragment {
public:
uint8_t freq;
uint8_t duration;
uint8_t pause;
uint8_t repeat;
int8_t freqIncr;
};
extern uint8_t t_queueRidx; class AudioFragment : public ToneFragment {
extern uint8_t t_queueWidx; public:
char file[32+1];
};
extern uint8_t toneFreq; extern "C" void DAC_IRQHandler();
extern uint8_t toneTimeLeft;
extern uint8_t tonePause;
extern char toneWavFile[32+1]; class AudioQueue {
// vario friend void audioTask(void* pdata);
extern uint8_t tone2Freq; friend void DAC_IRQHandler();
extern uint8_t tone2TimeLeft;
extern uint8_t tone2Pause;
// queue arrays public:
extern uint8_t queueToneFreq[AUDIO_QUEUE_LENGTH];
// int8_t queueToneFreqIncr[AUDIO_QUEUE_LENGTH]; AudioQueue();
extern uint8_t queueToneLength[AUDIO_QUEUE_LENGTH];
extern uint8_t queueTonePause[AUDIO_QUEUE_LENGTH]; void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlags=0, int8_t tFreqIncr=0);
extern uint8_t queueToneRepeat[AUDIO_QUEUE_LENGTH];
void playFile(const char *filename, uint8_t tFlags=0);
void pause(uint8_t tLen);
bool busy()
{
return (state != 0);
}
protected:
void wakeup();
uint8_t state;
uint8_t ridx;
uint8_t widx;
AudioFragment fragments[AUDIO_QUEUE_LENGTH];
ToneFragment background; // for vario
AudioFragment current;
};
extern AudioQueue audioQueue;
void alawInit(); void alawInit();
extern "C" void retrieveAvailableAudioFiles(); extern "C" void retrieveAvailableAudioFiles();
void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlags=0, int8_t tFreqIncr=0);
void playFile(const char *filename);
void pause(uint8_t tLen);
inline bool audioBusy()
{
return (audioState != 0);
}
void audioEvent(uint8_t e, uint8_t f=BEEP_DEFAULT_FREQ); void audioEvent(uint8_t e, uint8_t f=BEEP_DEFAULT_FREQ);
#define AUDIO_KEYPAD_UP() audioEvent(AU_KEYPAD_UP) #define AUDIO_KEYPAD_UP() audioEvent(AU_KEYPAD_UP)
@ -101,7 +120,7 @@ void audioEvent(uint8_t e, uint8_t f=BEEP_DEFAULT_FREQ);
#define AUDIO_TRIM_END(f) audioEvent(AU_TRIM_END, f) #define AUDIO_TRIM_END(f) audioEvent(AU_TRIM_END, f)
#define AUDIO_TRIM(event, f) audioEvent(AU_TRIM_MOVE, f) #define AUDIO_TRIM(event, f) audioEvent(AU_TRIM_MOVE, f)
#define AUDIO_PLAY(p) audioEvent(p) #define AUDIO_PLAY(p) audioEvent(p)
#define AUDIO_VARIO(f, t) play(f, t, 0, PLAY_SOUND_VARIO) #define AUDIO_VARIO(f, t) audioQueue.play(f, t, 0, PLAY_SOUND_VARIO)
#define AUDIO_HEARTBEAT() #define AUDIO_HEARTBEAT()

View file

@ -177,7 +177,7 @@ uint16_t *wavSamplesBuffer;
extern "C" void DAC_IRQHandler() extern "C" void DAC_IRQHandler()
{ {
// Data for PDC must NOT be in flash, PDC needs a RAM source. // Data for PDC must NOT be in flash, PDC needs a RAM source.
if (toneWavFile[0]) { if (audioQueue.current.file[0]) {
CoEnterISR(); // Enter the interrupt CoEnterISR(); // Enter the interrupt
CoSetFlag(audioFlag); CoSetFlag(audioFlag);
CoExitISR(); // Exit the interrupt CoExitISR(); // Exit the interrupt

View file

@ -645,7 +645,7 @@ void menuProcSd(uint8_t event)
f_getcwd(lfn, SD_SCREEN_FILE_LENGTH); f_getcwd(lfn, SD_SCREEN_FILE_LENGTH);
strcat_P(lfn, PSTR("/")); strcat_P(lfn, PSTR("/"));
strcat(lfn, reusableBuffer.sd.lines[index]); strcat(lfn, reusableBuffer.sd.lines[index]);
playFile(lfn); audioQueue.playFile(lfn);
} }
#endif #endif
} }

View file

@ -1701,12 +1701,12 @@ void evalFunctions()
#if defined(PCBARM) && defined(SDCARD) #if defined(PCBARM) && defined(SDCARD)
else if (sd->func == FUNC_PLAY_TRACK) { else if (sd->func == FUNC_PLAY_TRACK) {
if (!audioBusy()) { if (!audioQueue.busy()) {
char lfn[32] = SOUNDS_PATH "/"; char lfn[32] = SOUNDS_PATH "/";
strncpy(lfn+sizeof(SOUNDS_PATH), sd->param, sizeof(sd->param)); strncpy(lfn+sizeof(SOUNDS_PATH), sd->param, sizeof(sd->param));
lfn[sizeof(SOUNDS_PATH)+sizeof(sd->param)] = '\0'; lfn[sizeof(SOUNDS_PATH)+sizeof(sd->param)] = '\0';
strcat(lfn+sizeof(SOUNDS_PATH), SOUNDS_EXT); strcat(lfn+sizeof(SOUNDS_PATH), SOUNDS_EXT);
playFile(lfn); audioQueue.playFile(lfn);
} }
} }
else if (sd->func == FUNC_VOLUME) { else if (sd->func == FUNC_VOLUME) {