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

Fixes #3462: PlayTone check for min/max frequency added. Fixes Lua playTone() crash when called with abnormal parameter values. (#3468) (ported from master)

This commit is contained in:
Damjan Adamic 2016-05-06 22:44:43 +02:00
parent 8cd677d697
commit 6349ff9496
3 changed files with 437 additions and 424 deletions

View file

@ -657,12 +657,26 @@ int ToneContext::mixBuffer(AudioBuffer * buffer, int volume, unsigned int fade)
if (fragment.tone.freq != state.freq) { if (fragment.tone.freq != state.freq) {
state.freq = fragment.tone.freq; state.freq = fragment.tone.freq;
state.step = double(DIM(sineValues)*fragment.tone.freq) / AUDIO_SAMPLE_RATE; state.step = limit<double>(1, double(DIM(sineValues)*fragment.tone.freq) / AUDIO_SAMPLE_RATE, 512);
state.volume = evalVolumeRatio(fragment.tone.freq, volume); state.volume = evalVolumeRatio(fragment.tone.freq, volume);
} }
if (fragment.tone.freqIncr) { if (fragment.tone.freqIncr) {
fragment.tone.freq += AUDIO_BUFFER_DURATION * fragment.tone.freqIncr; int freqChange = AUDIO_BUFFER_DURATION * fragment.tone.freqIncr;
if (freqChange > 0) {
fragment.tone.freq += freqChange;
if (fragment.tone.freq > BEEP_MAX_FREQ) {
fragment.tone.freq = BEEP_MAX_FREQ;
}
}
else {
if (fragment.tone.freq > BEEP_MIN_FREQ - freqChange) {
fragment.tone.freq += freqChange;
}
else {
fragment.tone.freq = BEEP_MIN_FREQ;
}
}
} }
if (remainingDuration > AUDIO_BUFFER_DURATION) { if (remainingDuration > AUDIO_BUFFER_DURATION) {

View file

@ -1,416 +1,417 @@
/* /*
* Copyright (C) OpenTX * Copyright (C) OpenTX
* *
* Based on code named * Based on code named
* th9x - http://code.google.com/p/th9x * th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x * er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x * gruvin9x - http://code.google.com/p/gruvin9x
* *
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef _AUDIO_ARM_H_ #ifndef _AUDIO_ARM_H_
#define _AUDIO_ARM_H_ #define _AUDIO_ARM_H_
#include <stddef.h> #include <stddef.h>
#include "ff.h" #include "ff.h"
#define AUDIO_FILENAME_MAXLEN (42) // max length (example: /SOUNDS/fr/123456789012/1234567890-off.wav) #define AUDIO_FILENAME_MAXLEN (42) // max length (example: /SOUNDS/fr/123456789012/1234567890-off.wav)
#define AUDIO_QUEUE_LENGTH (20) #define AUDIO_QUEUE_LENGTH (20)
#define AUDIO_SAMPLE_RATE (32000) #define AUDIO_SAMPLE_RATE (32000)
#define AUDIO_BUFFER_DURATION (10) #define AUDIO_BUFFER_DURATION (10)
#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE*AUDIO_BUFFER_DURATION/1000) #define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE*AUDIO_BUFFER_DURATION/1000)
#if defined(SIMU_AUDIO) #if defined(SIMU_AUDIO)
#define AUDIO_BUFFER_COUNT (10) // simulator needs more buffers for smooth audio #define AUDIO_BUFFER_COUNT (10) // simulator needs more buffers for smooth audio
#elif defined(PCBHORUS) #elif defined(PCBHORUS)
#define AUDIO_BUFFER_COUNT (2) #define AUDIO_BUFFER_COUNT (2)
#else #else
#define AUDIO_BUFFER_COUNT (3) #define AUDIO_BUFFER_COUNT (3)
#endif #endif
#define BEEP_MIN_FREQ (150) #define BEEP_MIN_FREQ (150)
#define BEEP_DEFAULT_FREQ (2250) #define BEEP_MAX_FREQ (15000)
#define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+150) #define BEEP_DEFAULT_FREQ (2250)
#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-150) #define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+150)
#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-150)
enum AudioBufferState
{ enum AudioBufferState
AUDIO_BUFFER_FREE, {
AUDIO_BUFFER_FILLED, AUDIO_BUFFER_FREE,
AUDIO_BUFFER_PLAYING AUDIO_BUFFER_FILLED,
}; AUDIO_BUFFER_PLAYING
};
#if defined(SIMU)
typedef uint16_t audio_data_t; #if defined(SIMU)
#define AUDIO_DATA_SILENCE 0x8000 typedef uint16_t audio_data_t;
#define AUDIO_DATA_MIN 0 #define AUDIO_DATA_SILENCE 0x8000
#define AUDIO_DATA_MAX 0xffff #define AUDIO_DATA_MIN 0
#define AUDIO_BITS_PER_SAMPLE 16 #define AUDIO_DATA_MAX 0xffff
#elif defined(PCBHORUS) #define AUDIO_BITS_PER_SAMPLE 16
typedef int16_t audio_data_t; #elif defined(PCBHORUS)
#define AUDIO_DATA_SILENCE 0 typedef int16_t audio_data_t;
#define AUDIO_DATA_MIN INT16_MIN #define AUDIO_DATA_SILENCE 0
#define AUDIO_DATA_MAX INT16_MAX #define AUDIO_DATA_MIN INT16_MIN
#define AUDIO_BITS_PER_SAMPLE 16 #define AUDIO_DATA_MAX INT16_MAX
#else #define AUDIO_BITS_PER_SAMPLE 16
typedef uint16_t audio_data_t; #else
#define AUDIO_DATA_SILENCE (0x8000 >> 4) typedef uint16_t audio_data_t;
#define AUDIO_DATA_MIN 0 #define AUDIO_DATA_SILENCE (0x8000 >> 4)
#define AUDIO_DATA_MAX 0x0fff #define AUDIO_DATA_MIN 0
#define AUDIO_BITS_PER_SAMPLE 12 #define AUDIO_DATA_MAX 0x0fff
#endif #define AUDIO_BITS_PER_SAMPLE 12
#endif
struct AudioBuffer {
audio_data_t data[AUDIO_BUFFER_SIZE]; struct AudioBuffer {
uint16_t size; audio_data_t data[AUDIO_BUFFER_SIZE];
uint8_t state; uint16_t size;
}; uint8_t state;
};
extern AudioBuffer audioBuffers[AUDIO_BUFFER_COUNT];
extern AudioBuffer audioBuffers[AUDIO_BUFFER_COUNT];
enum FragmentTypes {
FRAGMENT_EMPTY, enum FragmentTypes {
FRAGMENT_TONE, FRAGMENT_EMPTY,
FRAGMENT_FILE, FRAGMENT_TONE,
}; FRAGMENT_FILE,
};
struct AudioFragment {
uint8_t type; struct AudioFragment {
uint8_t id; uint8_t type;
uint8_t repeat; uint8_t id;
union { uint8_t repeat;
struct { union {
uint16_t freq; struct {
uint16_t duration; uint16_t freq;
uint16_t pause; uint16_t duration;
int8_t freqIncr; uint16_t pause;
uint8_t reset; int8_t freqIncr;
} tone; uint8_t reset;
} tone;
char file[AUDIO_FILENAME_MAXLEN+1];
}; char file[AUDIO_FILENAME_MAXLEN+1];
};
void clear()
{ void clear()
memset(this, 0, sizeof(AudioFragment)); {
} memset(this, 0, sizeof(AudioFragment));
}; }
};
class ToneContext {
public: class ToneContext {
AudioFragment fragment; public:
AudioFragment fragment;
struct {
double step; struct {
double idx; double step;
float volume; double idx;
uint16_t freq; float volume;
uint16_t duration; uint16_t freq;
uint16_t pause; uint16_t duration;
} state; uint16_t pause;
} state;
inline void setFragment(AudioFragment & fragment)
{ inline void setFragment(AudioFragment & fragment)
this->fragment = fragment; {
memset(&state, 0, sizeof(state)); this->fragment = fragment;
} memset(&state, 0, sizeof(state));
}
inline void clear()
{ inline void clear()
memset(this, 0, sizeof(ToneContext)); {
} memset(this, 0, sizeof(ToneContext));
}
int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
}; int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
};
class WavContext {
public: class WavContext {
AudioFragment fragment; public:
AudioFragment fragment;
struct {
FIL file; struct {
uint8_t codec; FIL file;
uint32_t freq; uint8_t codec;
uint32_t size; uint32_t freq;
uint8_t resampleRatio; uint32_t size;
uint16_t readSize; uint8_t resampleRatio;
} state; uint16_t readSize;
} state;
inline void clear()
{ inline void clear()
fragment.clear(); {
} fragment.clear();
}
int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
}; int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
};
class MixedContext {
public: class MixedContext {
union { public:
AudioFragment fragment; union {
ToneContext tone; AudioFragment fragment;
WavContext wav; ToneContext tone;
}; WavContext wav;
};
int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
}; int mixBuffer(AudioBuffer *buffer, int volume, unsigned int fade);
};
void audioPushBuffer(AudioBuffer * buffer);
void audioPushBuffer(AudioBuffer * buffer);
class AudioQueue {
class AudioQueue {
friend void audioTask(void* pdata);
#if defined(SIMU_AUDIO) friend void audioTask(void* pdata);
friend void *audioThread(void *); #if defined(SIMU_AUDIO)
#endif friend void *audioThread(void *);
#if defined(CLI) #endif
friend void printAudioVars(); #if defined(CLI)
#endif friend void printAudioVars();
public: #endif
public:
AudioQueue();
AudioQueue();
void start();
void start();
void playTone(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);
void playFile(const char *filename, uint8_t flags=0, uint8_t id=0);
void stopPlay(uint8_t id);
void stopPlay(uint8_t id);
void stopAll();
void stopAll();
void flush();
void flush();
void pause(uint16_t tLen);
void pause(uint16_t tLen);
void stopSD();
void stopSD();
bool isPlaying(uint8_t id);
bool isPlaying(uint8_t id);
bool started()
{ bool started()
return state; {
} return state;
}
bool empty()
{ bool empty()
return ridx == widx; {
} return ridx == widx;
}
inline AudioBuffer * getNextFilledBuffer()
{ inline AudioBuffer * getNextFilledBuffer()
if (audioBuffers[bufferRIdx].state == AUDIO_BUFFER_PLAYING) { {
audioBuffers[bufferRIdx].state = AUDIO_BUFFER_FREE; if (audioBuffers[bufferRIdx].state == AUDIO_BUFFER_PLAYING) {
bufferRIdx = nextBufferIdx(bufferRIdx); audioBuffers[bufferRIdx].state = AUDIO_BUFFER_FREE;
} bufferRIdx = nextBufferIdx(bufferRIdx);
}
uint8_t idx = bufferRIdx;
do { uint8_t idx = bufferRIdx;
AudioBuffer * buffer = &audioBuffers[idx]; do {
if (buffer->state == AUDIO_BUFFER_FILLED) { AudioBuffer * buffer = &audioBuffers[idx];
buffer->state = AUDIO_BUFFER_PLAYING; if (buffer->state == AUDIO_BUFFER_FILLED) {
bufferRIdx = idx; buffer->state = AUDIO_BUFFER_PLAYING;
return buffer; bufferRIdx = idx;
} return buffer;
idx = nextBufferIdx(idx); }
} while (idx != bufferWIdx); //this fixes a bug if all buffers are filled idx = nextBufferIdx(idx);
} while (idx != bufferWIdx); //this fixes a bug if all buffers are filled
return NULL;
} return NULL;
}
bool filledAtleast(int noBuffers) {
int count = 0; bool filledAtleast(int noBuffers) {
for(int n= 0; n<AUDIO_BUFFER_COUNT; ++n) { int count = 0;
if (audioBuffers[n].state == AUDIO_BUFFER_FILLED) { for(int n= 0; n<AUDIO_BUFFER_COUNT; ++n) {
if (++count >= noBuffers) { if (audioBuffers[n].state == AUDIO_BUFFER_FILLED) {
return true; if (++count >= noBuffers) {
} return true;
} }
} }
return false; }
} return false;
}
protected:
protected:
void wakeup();
void wakeup();
volatile bool state;
uint8_t ridx; volatile bool state;
uint8_t widx; uint8_t ridx;
uint8_t widx;
AudioFragment fragments[AUDIO_QUEUE_LENGTH];
AudioFragment fragments[AUDIO_QUEUE_LENGTH];
MixedContext normalContext;
WavContext backgroundContext; MixedContext normalContext;
ToneContext priorityContext; WavContext backgroundContext;
ToneContext varioContext; ToneContext priorityContext;
ToneContext varioContext;
uint8_t bufferRIdx;
uint8_t bufferWIdx; uint8_t bufferRIdx;
uint8_t bufferWIdx;
inline uint8_t nextBufferIdx(uint8_t idx)
{ inline uint8_t nextBufferIdx(uint8_t idx)
return (idx == AUDIO_BUFFER_COUNT-1 ? 0 : idx+1); {
} return (idx == AUDIO_BUFFER_COUNT-1 ? 0 : idx+1);
}
inline AudioBuffer * getEmptyBuffer()
{ inline AudioBuffer * getEmptyBuffer()
AudioBuffer * buffer = &audioBuffers[bufferWIdx]; {
if (buffer->state == AUDIO_BUFFER_FREE) AudioBuffer * buffer = &audioBuffers[bufferWIdx];
return buffer; if (buffer->state == AUDIO_BUFFER_FREE)
else return buffer;
return NULL; else
} return NULL;
}; }
};
extern AudioQueue audioQueue;
extern AudioQueue audioQueue;
enum {
ID_PLAY_FROM_SD_MANAGER = 254, enum {
ID_PLAY_BYE = 255 ID_PLAY_FROM_SD_MANAGER = 254,
}; ID_PLAY_BYE = 255
};
void codecsInit();
void audioEvent(unsigned int index, unsigned int freq=BEEP_DEFAULT_FREQ); void codecsInit();
void audioPlay(unsigned int index, uint8_t id=0); void audioEvent(unsigned int index, unsigned int freq=BEEP_DEFAULT_FREQ);
void audioStart(); void audioPlay(unsigned int index, uint8_t id=0);
void audioStart();
#if defined(AUDIO) && defined(BUZZER)
#define AUDIO_BUZZER(a, b) do { a; b; } while(0) #if defined(AUDIO) && defined(BUZZER)
#elif defined(AUDIO) #define AUDIO_BUZZER(a, b) do { a; b; } while(0)
#define AUDIO_BUZZER(a, b) a #elif defined(AUDIO)
#else #define AUDIO_BUZZER(a, b) a
#define AUDIO_BUZZER(a, b) b #else
#endif #define AUDIO_BUZZER(a, b) b
#endif
#if defined(VOICE)
#define AUDIO_ERROR_MESSAGE(e) audioEvent(e) #if defined(VOICE)
#define AUDIO_TIMER_MINUTE(t) playDuration(t, 0, 0) #define AUDIO_ERROR_MESSAGE(e) audioEvent(e)
#else #define AUDIO_TIMER_MINUTE(t) playDuration(t, 0, 0)
#define AUDIO_ERROR_MESSAGE(e) audioEvent(AU_ERROR) #else
#define AUDIO_TIMER_MINUTE(t) audioDefevent(AU_WARNING1) #define AUDIO_ERROR_MESSAGE(e) audioEvent(AU_ERROR)
#endif #define AUDIO_TIMER_MINUTE(t) audioDefevent(AU_WARNING1)
#endif
#define AUDIO_TADA() audioPlay(AU_TADA)
#define AUDIO_BYE() audioPlay(AU_BYE, ID_PLAY_BYE) #define AUDIO_TADA() audioPlay(AU_TADA)
#define AUDIO_KEYPAD_UP() AUDIO_BUZZER(audioEvent(AU_KEYPAD_UP), beep(0)) #define AUDIO_BYE() audioPlay(AU_BYE, ID_PLAY_BYE)
#define AUDIO_KEYPAD_DOWN() AUDIO_BUZZER(audioEvent(AU_KEYPAD_DOWN), beep(0)) #define AUDIO_KEYPAD_UP() AUDIO_BUZZER(audioEvent(AU_KEYPAD_UP), beep(0))
#define AUDIO_MENUS() AUDIO_BUZZER(audioEvent(AU_MENUS), beep(0)) #define AUDIO_KEYPAD_DOWN() AUDIO_BUZZER(audioEvent(AU_KEYPAD_DOWN), beep(0))
#define AUDIO_WARNING1() AUDIO_BUZZER(audioEvent(AU_WARNING1), beep(3)) #define AUDIO_MENUS() AUDIO_BUZZER(audioEvent(AU_MENUS), beep(0))
#define AUDIO_WARNING2() AUDIO_BUZZER(audioEvent(AU_WARNING2), beep(2)) #define AUDIO_WARNING1() AUDIO_BUZZER(audioEvent(AU_WARNING1), beep(3))
#define AUDIO_TX_BATTERY_LOW() AUDIO_BUZZER(audioEvent(AU_TX_BATTERY_LOW), beep(4)) #define AUDIO_WARNING2() AUDIO_BUZZER(audioEvent(AU_WARNING2), beep(2))
#if defined(PCBSKY9X) #define AUDIO_TX_BATTERY_LOW() AUDIO_BUZZER(audioEvent(AU_TX_BATTERY_LOW), beep(4))
#define AUDIO_TX_MAH_HIGH() audioEvent(AU_TX_MAH_HIGH) #if defined(PCBSKY9X)
#define AUDIO_TX_TEMP_HIGH() audioEvent(AU_TX_TEMP_HIGH) #define AUDIO_TX_MAH_HIGH() audioEvent(AU_TX_MAH_HIGH)
#endif #define AUDIO_TX_TEMP_HIGH() audioEvent(AU_TX_TEMP_HIGH)
#define AUDIO_ERROR() AUDIO_BUZZER(audioEvent(AU_ERROR), beep(4)) #endif
#define AUDIO_TIMER_30() AUDIO_BUZZER(audioEvent(AU_TIMER_30), { beepAgain=2; beep(2); }) #define AUDIO_ERROR() AUDIO_BUZZER(audioEvent(AU_ERROR), beep(4))
#define AUDIO_TIMER_20() AUDIO_BUZZER(audioEvent(AU_TIMER_20), { beepAgain=1; beep(2); }) #define AUDIO_TIMER_30() AUDIO_BUZZER(audioEvent(AU_TIMER_30), { beepAgain=2; beep(2); })
#define AUDIO_TIMER_20() AUDIO_BUZZER(audioEvent(AU_TIMER_20), { beepAgain=1; beep(2); })
#if defined(HAPTIC)
#define AUDIO_TIMER_LT10(m, x) do { if (m==COUNTDOWN_VOICE) playNumber(x, 0, 0, 0); else if (m==COUNTDOWN_HAPTIC) haptic.event(AU_TIMER_LT10); else AUDIO_BUZZER(audioEvent(AU_TIMER_LT10), beep(2)); } while(0) #if defined(HAPTIC)
#define AUDIO_TIMER_00(m) do { if (m==COUNTDOWN_VOICE) playNumber(0, 0, 0, 0); else if (m==COUNTDOWN_HAPTIC) haptic.event(AU_TIMER_00); else AUDIO_BUZZER(audioEvent(AU_TIMER_00), beep(3)); } while(0) #define AUDIO_TIMER_LT10(m, x) do { if (m==COUNTDOWN_VOICE) playNumber(x, 0, 0, 0); else if (m==COUNTDOWN_HAPTIC) haptic.event(AU_TIMER_LT10); else AUDIO_BUZZER(audioEvent(AU_TIMER_LT10), beep(2)); } while(0)
#else #define AUDIO_TIMER_00(m) do { if (m==COUNTDOWN_VOICE) playNumber(0, 0, 0, 0); else if (m==COUNTDOWN_HAPTIC) haptic.event(AU_TIMER_00); else AUDIO_BUZZER(audioEvent(AU_TIMER_00), beep(3)); } while(0)
#define AUDIO_TIMER_LT10(m, x) do { if (m==COUNTDOWN_VOICE) playNumber(x, 0, 0, 0); else AUDIO_BUZZER(audioEvent(AU_TIMER_LT10), beep(2)); } while(0) #else
#define AUDIO_TIMER_00(m) do { if (m==COUNTDOWN_VOICE) playNumber(0, 0, 0, 0); else AUDIO_BUZZER(audioEvent(AU_TIMER_00), beep(3)); } while(0) #define AUDIO_TIMER_LT10(m, x) do { if (m==COUNTDOWN_VOICE) playNumber(x, 0, 0, 0); else AUDIO_BUZZER(audioEvent(AU_TIMER_LT10), beep(2)); } while(0)
#endif #define AUDIO_TIMER_00(m) do { if (m==COUNTDOWN_VOICE) playNumber(0, 0, 0, 0); else AUDIO_BUZZER(audioEvent(AU_TIMER_00), beep(3)); } while(0)
#endif
#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_INACTIVITY() AUDIO_BUZZER(audioEvent(AU_INACTIVITY), beep(3))
#define AUDIO_POT_MIDDLE(x) AUDIO_BUZZER(audioEvent(AU_STICK1_MIDDLE+x), beep(2)) #define AUDIO_MIX_WARNING(x) AUDIO_BUZZER(audioEvent(AU_MIX_WARNING_1+x-1), beep(1))
#define AUDIO_TRIM_MIDDLE(f) AUDIO_BUZZER(audioEvent(AU_TRIM_MIDDLE, f), beep(2)) #define AUDIO_POT_MIDDLE(x) AUDIO_BUZZER(audioEvent(AU_STICK1_MIDDLE+x), beep(2))
#define AUDIO_TRIM_END(f) AUDIO_BUZZER(audioEvent(AU_TRIM_END, f), beep(2)) #define AUDIO_TRIM_MIDDLE(f) AUDIO_BUZZER(audioEvent(AU_TRIM_MIDDLE, 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_TRIM_END(f) AUDIO_BUZZER(audioEvent(AU_TRIM_END, f), beep(2))
#define AUDIO_PLAY(p) audioEvent(p) #define AUDIO_TRIM(event, f) AUDIO_BUZZER(audioEvent(AU_TRIM_MOVE, f), { if (!IS_KEY_FIRST(event)) warble = true; beep(1); })
#define AUDIO_VARIO(fq, t, p, f) audioQueue.playTone(fq, t, p, f) #define AUDIO_PLAY(p) audioEvent(p)
#define AUDIO_A1_ORANGE() audioEvent(AU_A1_ORANGE) #define AUDIO_VARIO(fq, t, p, f) audioQueue.playTone(fq, t, p, f)
#define AUDIO_A1_RED() audioEvent(AU_A1_RED) #define AUDIO_A1_ORANGE() audioEvent(AU_A1_ORANGE)
#define AUDIO_A2_ORANGE() audioEvent(AU_A2_ORANGE) #define AUDIO_A1_RED() audioEvent(AU_A1_RED)
#define AUDIO_A2_RED() audioEvent(AU_A2_RED) #define AUDIO_A2_ORANGE() audioEvent(AU_A2_ORANGE)
#define AUDIO_A3_ORANGE() audioEvent(AU_A3_ORANGE) #define AUDIO_A2_RED() audioEvent(AU_A2_RED)
#define AUDIO_A3_RED() audioEvent(AU_A3_RED) #define AUDIO_A3_ORANGE() audioEvent(AU_A3_ORANGE)
#define AUDIO_A4_ORANGE() audioEvent(AU_A4_ORANGE) #define AUDIO_A3_RED() audioEvent(AU_A3_RED)
#define AUDIO_A4_RED() audioEvent(AU_A4_RED) #define AUDIO_A4_ORANGE() audioEvent(AU_A4_ORANGE)
#define AUDIO_RSSI_ORANGE() audioEvent(AU_RSSI_ORANGE) #define AUDIO_A4_RED() audioEvent(AU_A4_RED)
#define AUDIO_RSSI_RED() audioEvent(AU_RSSI_RED) #define AUDIO_RSSI_ORANGE() audioEvent(AU_RSSI_ORANGE)
#define AUDIO_SWR_RED() audioEvent(AU_SWR_RED) #define AUDIO_RSSI_RED() audioEvent(AU_RSSI_RED)
#define AUDIO_TELEMETRY_LOST() audioEvent(AU_TELEMETRY_LOST) #define AUDIO_SWR_RED() audioEvent(AU_SWR_RED)
#define AUDIO_TELEMETRY_BACK() audioEvent(AU_TELEMETRY_BACK) #define AUDIO_TELEMETRY_LOST() audioEvent(AU_TELEMETRY_LOST)
#define AUDIO_TRAINER_LOST() audioEvent(AU_TRAINER_LOST) #define AUDIO_TELEMETRY_BACK() audioEvent(AU_TELEMETRY_BACK)
#define AUDIO_TRAINER_BACK() audioEvent(AU_TRAINER_BACK) #define AUDIO_TRAINER_LOST() audioEvent(AU_TRAINER_LOST)
#define AUDIO_TRAINER_BACK() audioEvent(AU_TRAINER_BACK)
#define AUDIO_HEARTBEAT()
#define AUDIO_HEARTBEAT()
enum AutomaticPromptsCategories {
SYSTEM_AUDIO_CATEGORY, enum AutomaticPromptsCategories {
MODEL_AUDIO_CATEGORY, SYSTEM_AUDIO_CATEGORY,
PHASE_AUDIO_CATEGORY, MODEL_AUDIO_CATEGORY,
SWITCH_AUDIO_CATEGORY, PHASE_AUDIO_CATEGORY,
LOGICAL_SWITCH_AUDIO_CATEGORY, SWITCH_AUDIO_CATEGORY,
}; LOGICAL_SWITCH_AUDIO_CATEGORY,
};
enum AutomaticPromptsEvents {
AUDIO_EVENT_OFF, enum AutomaticPromptsEvents {
AUDIO_EVENT_ON, AUDIO_EVENT_OFF,
AUDIO_EVENT_MID, AUDIO_EVENT_ON,
}; AUDIO_EVENT_MID,
};
void pushPrompt(uint16_t prompt, uint8_t id=0);
void playModelName(); void pushPrompt(uint16_t prompt, uint8_t id=0);
void playModelName();
#define I18N_PLAY_FUNCTION(lng, x, ...) void lng ## _ ## x(__VA_ARGS__, uint8_t id)
#define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__, uint8_t id) #define I18N_PLAY_FUNCTION(lng, x, ...) void lng ## _ ## x(__VA_ARGS__, uint8_t id)
#define PUSH_NUMBER_PROMPT(p) pushPrompt((p), id) #define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__, uint8_t id)
#define PLAY_NUMBER(n, u, a) playNumber((n), (u), (a), id) #define PUSH_NUMBER_PROMPT(p) pushPrompt((p), id)
#define PLAY_DURATION(d, att) playDuration((d), (att), id) #define PLAY_NUMBER(n, u, a) playNumber((n), (u), (a), id)
#define PLAY_DURATION_ATT , uint8_t flags #define PLAY_DURATION(d, att) playDuration((d), (att), id)
#define PLAY_TIME 1 #define PLAY_DURATION_ATT , uint8_t flags
#define IS_PLAY_TIME() (flags&PLAY_TIME) #define PLAY_TIME 1
#define IS_PLAYING(id) audioQueue.isPlaying((id)) #define IS_PLAY_TIME() (flags&PLAY_TIME)
#define PLAY_VALUE(v, id) playValue((v), (id)) #define IS_PLAYING(id) audioQueue.isPlaying((id))
#define PLAY_FILE(f, flags, id) audioQueue.playFile((f), (flags), (id)) #define PLAY_VALUE(v, id) playValue((v), (id))
#define STOP_PLAY(id) audioQueue.stopPlay((id)) #define PLAY_FILE(f, flags, id) audioQueue.playFile((f), (flags), (id))
#define AUDIO_RESET() audioQueue.stopAll() #define STOP_PLAY(id) audioQueue.stopPlay((id))
#define AUDIO_FLUSH() audioQueue.flush() #define AUDIO_RESET() audioQueue.stopAll()
#define AUDIO_FLUSH() audioQueue.flush()
#if defined(SDCARD)
extern tmr10ms_t timeAutomaticPromptsSilence; #if defined(SDCARD)
void playModelEvent(uint8_t category, uint8_t index, uint8_t event=0); extern tmr10ms_t timeAutomaticPromptsSilence;
#define PLAY_PHASE_OFF(phase) playModelEvent(PHASE_AUDIO_CATEGORY, phase, AUDIO_EVENT_OFF) void playModelEvent(uint8_t category, uint8_t index, uint8_t event=0);
#define PLAY_PHASE_ON(phase) playModelEvent(PHASE_AUDIO_CATEGORY, phase, AUDIO_EVENT_ON) #define PLAY_PHASE_OFF(phase) playModelEvent(PHASE_AUDIO_CATEGORY, phase, AUDIO_EVENT_OFF)
#define PLAY_SWITCH_MOVED(sw) playModelEvent(SWITCH_AUDIO_CATEGORY, sw) #define PLAY_PHASE_ON(phase) playModelEvent(PHASE_AUDIO_CATEGORY, phase, AUDIO_EVENT_ON)
#define PLAY_LOGICAL_SWITCH_OFF(sw) playModelEvent(LOGICAL_SWITCH_AUDIO_CATEGORY, sw, AUDIO_EVENT_OFF) #define PLAY_SWITCH_MOVED(sw) playModelEvent(SWITCH_AUDIO_CATEGORY, sw)
#define PLAY_LOGICAL_SWITCH_ON(sw) playModelEvent(LOGICAL_SWITCH_AUDIO_CATEGORY, sw, AUDIO_EVENT_ON) #define PLAY_LOGICAL_SWITCH_OFF(sw) playModelEvent(LOGICAL_SWITCH_AUDIO_CATEGORY, sw, AUDIO_EVENT_OFF)
#define PLAY_MODEL_NAME() playModelName() #define PLAY_LOGICAL_SWITCH_ON(sw) playModelEvent(LOGICAL_SWITCH_AUDIO_CATEGORY, sw, AUDIO_EVENT_ON)
#define START_SILENCE_PERIOD() timeAutomaticPromptsSilence = get_tmr10ms() #define PLAY_MODEL_NAME() playModelName()
#define IS_SILENCE_PERIOD_ELAPSED() (get_tmr10ms()-timeAutomaticPromptsSilence > 50) #define START_SILENCE_PERIOD() timeAutomaticPromptsSilence = get_tmr10ms()
#else #define IS_SILENCE_PERIOD_ELAPSED() (get_tmr10ms()-timeAutomaticPromptsSilence > 50)
#define PLAY_PHASE_OFF(phase) #else
#define PLAY_PHASE_ON(phase) #define PLAY_PHASE_OFF(phase)
#define PLAY_SWITCH_MOVED(sw) #define PLAY_PHASE_ON(phase)
#define PLAY_LOGICAL_SWITCH_OFF(sw) #define PLAY_SWITCH_MOVED(sw)
#define PLAY_LOGICAL_SWITCH_ON(sw) #define PLAY_LOGICAL_SWITCH_OFF(sw)
#define PLAY_MODEL_NAME() #define PLAY_LOGICAL_SWITCH_ON(sw)
#define START_SILENCE_PERIOD() #define PLAY_MODEL_NAME()
#endif #define START_SILENCE_PERIOD()
#endif
char * getAudioPath(char * path);
char * getAudioPath(char * path);
void referenceSystemAudioFiles();
void referenceModelAudioFiles(); void referenceSystemAudioFiles();
void referenceModelAudioFiles();
bool isAudioFileReferenced(uint32_t i, char * filename/*at least AUDIO_FILENAME_MAXLEN+1 long*/);
bool isAudioFileReferenced(uint32_t i, char * filename/*at least AUDIO_FILENAME_MAXLEN+1 long*/);
#endif // _AUDIO_ARM_H_
#endif // _AUDIO_ARM_H_

View file

@ -604,22 +604,20 @@ static int luaPlayDuration(lua_State *L)
Play a tone Play a tone
@param frequency (number) tone frequency in Hz @param frequency (number) tone frequency in Hz (from 150 to 15000)
@param duration (number) length of the tone in (TODO units) @param duration (number) length of the tone in milliseconds
@param pause (number) length of the pause in (TODO units) @param pause (number) length of the silence after the tone in milliseconds
@param flags (number): @param flags (number):
* `0 or not present` play with normal priority. * `0 or not present` play with normal priority.
* `PLAY_BACKGROUND` play in background (built in vario function used this context) * `PLAY_BACKGROUND` play in background (built in vario function uses this context)
* `PLAY_NOW` play immediately * `PLAY_NOW` play immediately
@param freqIncr (number) positive number increases the tone pitch (frequency with time), @param freqIncr (number) positive number increases the tone pitch (frequency with time),
negative number decreases it. Bigger number has more effect negative number decreases it. Bigger number has more effect
@notice Minimum played frequency is 150Hz even if a lower value is specified.
@status current Introduced in 2.1.0 @status current Introduced in 2.1.0
*/ */
static int luaPlayTone(lua_State *L) static int luaPlayTone(lua_State *L)