mirror of
https://github.com/opentx/opentx.git
synced 2025-07-23 16:25:16 +03:00
Audio wav files may not be queued and repeated as others.
This commit is contained in:
parent
8989ce4e6c
commit
602ff6ca46
6 changed files with 273 additions and 249 deletions
|
@ -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. */
|
||||||
|
|
|
@ -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,23 +158,29 @@ 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)) {
|
||||||
|
@ -221,12 +202,17 @@ void audioTask(void* pdata)
|
||||||
read = 0;
|
read = 0;
|
||||||
uint16_t bufsize = (pcmCodec == CODEC_ID_PCM_S16LE ? 2*WAV_BUFFER_SIZE : WAV_BUFFER_SIZE);
|
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) {
|
if (result != FR_OK || f_read(&wavFile, (uint8_t *)bufdata, bufsize, &read) != FR_OK || read != bufsize) {
|
||||||
|
current.file[0] = 0;
|
||||||
|
current.file[1] = 0;
|
||||||
|
if (pcmCodec == CODEC_ID_PCM_S16LE) {
|
||||||
DACC->DACC_TNCR = read/4;
|
DACC->DACC_TNCR = read/4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DACC->DACC_TNCR = read/2;
|
||||||
|
}
|
||||||
toneStop();
|
toneStop();
|
||||||
toneWavFile[0] = '\0';
|
|
||||||
toneWavFile[1] = '\0';
|
|
||||||
f_close(&wavFile);
|
f_close(&wavFile);
|
||||||
audioState = 0;
|
CoSetFlag(audioFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcmCodec == CODEC_ID_PCM_S16LE) {
|
if (pcmCodec == CODEC_ID_PCM_S16LE) {
|
||||||
|
@ -245,8 +231,8 @@ void audioTask(void* pdata)
|
||||||
bufdata[i] = 0x8000;
|
bufdata[i] = 0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toneWavFile[1]) {
|
if (current.file[1]) {
|
||||||
toneWavFile[1] = '\0';
|
current.file[1] = 0;
|
||||||
register Dacc *dacptr = DACC;
|
register Dacc *dacptr = DACC;
|
||||||
dacptr->DACC_TPR = CONVERT_PTR(wavSamplesArray);
|
dacptr->DACC_TPR = CONVERT_PTR(wavSamplesArray);
|
||||||
dacptr->DACC_TNPR = CONVERT_PTR(wavSamplesBuffer);
|
dacptr->DACC_TNPR = CONVERT_PTR(wavSamplesBuffer);
|
||||||
|
@ -257,50 +243,46 @@ void audioTask(void* pdata)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (toneTimeLeft > 0) {
|
if (current.duration > 0) {
|
||||||
// TODO function for that ...
|
// TODO function for that ...
|
||||||
setFrequency(toneFreq * 6100 / 2);
|
setFrequency(current.freq * 6100 / 2);
|
||||||
if (toneFreqIncr) {
|
if (current.freqIncr) {
|
||||||
CoSetTmrCnt(audioTimer, 5/*10ms*/, 0);
|
CoSetTmrCnt(audioTimer, 5/*10ms*/, 0);
|
||||||
toneFreq += toneFreqIncr;
|
current.freq += current.freqIncr;
|
||||||
toneTimeLeft--;
|
current.duration--;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CoSetTmrCnt(audioTimer, toneTimeLeft*5, 0);
|
CoSetTmrCnt(audioTimer, current.duration*5, 0);
|
||||||
toneTimeLeft = 0;
|
current.duration = 0;
|
||||||
}
|
}
|
||||||
toneStart();
|
toneStart();
|
||||||
CoStartTmr(audioTimer);
|
CoStartTmr(audioTimer);
|
||||||
}
|
}
|
||||||
else if (tonePause > 0) {
|
else if (current.pause > 0) {
|
||||||
CoSetTmrCnt(audioTimer, tonePause*5, 0);
|
CoSetTmrCnt(audioTimer, current.pause*5, 0);
|
||||||
tonePause = 0;
|
current.pause = 0;
|
||||||
toneStop();
|
toneStop();
|
||||||
CoStartTmr(audioTimer);
|
CoStartTmr(audioTimer);
|
||||||
}
|
}
|
||||||
else if (t_queueRidx != t_queueWidx) {
|
else if (ridx != widx) {
|
||||||
toneFreq = queueToneFreq[t_queueRidx];
|
memcpy(¤t, &fragments[ridx], sizeof(current));
|
||||||
toneTimeLeft = queueToneLength[t_queueRidx];
|
if (!fragments[ridx].repeat--) {
|
||||||
toneFreqIncr = queueToneFreqIncr[t_queueRidx];
|
ridx = (ridx + 1) % AUDIO_QUEUE_LENGTH;
|
||||||
tonePause = queueTonePause[t_queueRidx];
|
|
||||||
if (!queueToneRepeat[t_queueRidx]--) {
|
|
||||||
t_queueRidx = (t_queueRidx + 1) % AUDIO_QUEUE_LENGTH;
|
|
||||||
}
|
}
|
||||||
CoSetFlag(audioFlag);
|
CoSetFlag(audioFlag);
|
||||||
}
|
}
|
||||||
else if (tone2TimeLeft > 0) {
|
else if (background.duration > 0) {
|
||||||
CoSetTmrCnt(audioTimer, tone2TimeLeft*5, 0);
|
CoSetTmrCnt(audioTimer, background.duration*5, 0);
|
||||||
tone2TimeLeft = 0;
|
background.duration = 0;
|
||||||
setFrequency(tone2Freq * 6100 / 2);
|
setFrequency(background.freq * 6100 / 2);
|
||||||
toneStart();
|
toneStart();
|
||||||
CoStartTmr(audioTimer);
|
CoStartTmr(audioTimer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
audioState = 0;
|
state = 0;
|
||||||
toneStop();
|
toneStop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t getToneLength(uint8_t tLen)
|
inline uint8_t getToneLength(uint8_t tLen)
|
||||||
{
|
{
|
||||||
|
@ -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(¤t, 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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue