[sky9x/Taranis] Audio mixer!
This commit is contained in:
+114
-49
@@ -41,53 +41,87 @@
|
||||
|
||||
#define AUDIO_FILENAME_MAXLEN (40)
|
||||
#define AUDIO_QUEUE_LENGTH (20)
|
||||
#define BEEP_DEFAULT_FREQ (140)
|
||||
#define BEEP_OFFSET (10)
|
||||
#define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+10)
|
||||
#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-10)
|
||||
|
||||
extern uint16_t Sine_values[];
|
||||
#define AUDIO_SAMPLE_RATE (32000)
|
||||
#define AUDIO_BUFFER_DURATION (10)
|
||||
#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE*AUDIO_BUFFER_DURATION/1000)
|
||||
#define AUDIO_BUFFER_COUNT (3)
|
||||
|
||||
class ToneFragment {
|
||||
public:
|
||||
uint16_t freq;
|
||||
uint8_t duration;
|
||||
uint8_t pause;
|
||||
uint8_t repeat;
|
||||
int8_t freqIncr;
|
||||
uint8_t id;
|
||||
#define BEEP_MIN_FREQ (440)
|
||||
#define BEEP_DEFAULT_FREQ (2250)
|
||||
#define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+150)
|
||||
#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-150)
|
||||
|
||||
#define AUDIO_BUFFER_FREE (0)
|
||||
#define AUDIO_BUFFER_FILLED (1)
|
||||
#define AUDIO_BUFFER_PLAYING (2)
|
||||
|
||||
struct AudioBuffer {
|
||||
uint16_t data[AUDIO_BUFFER_SIZE];
|
||||
uint16_t size;
|
||||
uint8_t state;
|
||||
};
|
||||
|
||||
class AudioFragment : public ToneFragment {
|
||||
public:
|
||||
#define FRAGMENT_EMPTY 0
|
||||
#define FRAGMENT_TONE 1
|
||||
#define FRAGMENT_FILE 2
|
||||
|
||||
struct AudioFragment {
|
||||
uint8_t type;
|
||||
uint8_t id;
|
||||
uint8_t repeat;
|
||||
union {
|
||||
struct {
|
||||
uint16_t freq;
|
||||
uint16_t duration;
|
||||
uint16_t pause;
|
||||
int8_t freqIncr;
|
||||
} tone;
|
||||
|
||||
char file[AUDIO_FILENAME_MAXLEN+1];
|
||||
};
|
||||
|
||||
void clear()
|
||||
{
|
||||
memset(this, 0, sizeof(AudioFragment));
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" void DAC_IRQHandler();
|
||||
|
||||
#define AUDIO_NOT_STARTED 0
|
||||
#define AUDIO_SLEEPING 1
|
||||
#define AUDIO_RESUMING 2
|
||||
#define AUDIO_PLAYING_TONE 3
|
||||
#define AUDIO_PLAYING_WAV 4
|
||||
|
||||
extern bool playingBackground;
|
||||
|
||||
class AudioContext {
|
||||
public:
|
||||
AudioFragment fragment;
|
||||
|
||||
union {
|
||||
#if defined(SDCARD)
|
||||
FIL wavFile;
|
||||
struct {
|
||||
FIL file;
|
||||
uint8_t codec;
|
||||
uint32_t freq;
|
||||
uint32_t size;
|
||||
uint8_t resampleRatio;
|
||||
uint16_t readSize;
|
||||
} wav;
|
||||
#endif
|
||||
uint8_t pcmCodec;
|
||||
uint32_t pcmFreq;
|
||||
uint32_t wavSize;
|
||||
|
||||
struct {
|
||||
uint16_t points[100];
|
||||
uint8_t count;
|
||||
uint8_t idx;
|
||||
uint16_t freq;
|
||||
} tone;
|
||||
} state;
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
fragment.clear();
|
||||
}
|
||||
};
|
||||
|
||||
bool dacQueue(AudioBuffer *buffer);
|
||||
|
||||
class AudioQueue {
|
||||
|
||||
friend void audioTask(void* pdata);
|
||||
friend void DAC_IRQHandler();
|
||||
|
||||
public:
|
||||
|
||||
@@ -95,13 +129,13 @@ class AudioQueue {
|
||||
|
||||
void start();
|
||||
|
||||
void play(uint16_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlags=0, int8_t tFreqIncr=0);
|
||||
void play(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 stopPlay(uint8_t id);
|
||||
|
||||
void pause(uint8_t tLen);
|
||||
void pause(uint16_t tLen);
|
||||
|
||||
void stopSD();
|
||||
|
||||
@@ -109,16 +143,7 @@ class AudioQueue {
|
||||
|
||||
bool started()
|
||||
{
|
||||
return (state != AUDIO_NOT_STARTED);
|
||||
}
|
||||
|
||||
bool busy()
|
||||
{
|
||||
#ifdef SIMU
|
||||
return false;
|
||||
#else
|
||||
return (state != AUDIO_SLEEPING);
|
||||
#endif
|
||||
return state;
|
||||
}
|
||||
|
||||
bool empty()
|
||||
@@ -128,27 +153,69 @@ class AudioQueue {
|
||||
|
||||
void reset();
|
||||
|
||||
inline AudioBuffer * getNextFilledBuffer()
|
||||
{
|
||||
if (buffers[bufferRIdx].state == AUDIO_BUFFER_PLAYING) {
|
||||
buffers[bufferRIdx].state = AUDIO_BUFFER_FREE;
|
||||
bufferRIdx = nextBufferIdx(bufferRIdx);
|
||||
}
|
||||
|
||||
uint8_t idx = bufferRIdx;
|
||||
while (idx != bufferWIdx) {
|
||||
AudioBuffer * buffer = &buffers[idx];
|
||||
if (buffer->state == AUDIO_BUFFER_FILLED) {
|
||||
buffer->state = AUDIO_BUFFER_PLAYING;
|
||||
return buffer;
|
||||
}
|
||||
idx = nextBufferIdx(idx);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void wakeup();
|
||||
|
||||
void sdWakeup(AudioContext & context);
|
||||
int mixAudioContext(AudioContext &context, AudioBuffer *buffer, unsigned int weight);
|
||||
int mixTone(AudioContext &context, AudioBuffer *buffer, unsigned int weight);
|
||||
int mixWav(AudioContext &context, AudioBuffer *buffer, unsigned int weight);
|
||||
|
||||
volatile uint8_t state;
|
||||
volatile bool state;
|
||||
uint8_t ridx;
|
||||
uint8_t widx;
|
||||
int8_t prioIdx;
|
||||
|
||||
AudioFragment fragments[AUDIO_QUEUE_LENGTH];
|
||||
|
||||
AudioContext currentContext;
|
||||
AudioContext backgroundContext; // for background music / vario
|
||||
AudioContext currentContext;
|
||||
AudioContext foregroundContext; // for important beeps
|
||||
|
||||
AudioBuffer buffers[AUDIO_BUFFER_COUNT];
|
||||
uint8_t bufferRIdx;
|
||||
uint8_t bufferWIdx;
|
||||
|
||||
inline uint8_t nextBufferIdx(uint8_t idx)
|
||||
{
|
||||
return (idx == AUDIO_BUFFER_COUNT-1 ? 0 : idx+1);
|
||||
}
|
||||
|
||||
inline AudioBuffer * getEmptyBuffer()
|
||||
{
|
||||
AudioBuffer * buffer = &buffers[bufferWIdx];
|
||||
if (buffer->state == AUDIO_BUFFER_FREE)
|
||||
return buffer;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pushBuffer(AudioBuffer *buffer);
|
||||
};
|
||||
|
||||
extern AudioQueue audioQueue;
|
||||
|
||||
void codecsInit();
|
||||
void audioEvent(uint8_t e, uint8_t f=BEEP_DEFAULT_FREQ);
|
||||
void audioEvent(uint8_t e, uint16_t f=BEEP_DEFAULT_FREQ);
|
||||
void audioStart();
|
||||
|
||||
#if defined(AUDIO) && defined(BUZZER)
|
||||
@@ -240,8 +307,6 @@ extern void refreshModelAudioFiles();
|
||||
extern bool isAudioFileAvailable(uint32_t i, char * filename);
|
||||
|
||||
// TODO not public, everything could be inside a function in audio_arm.cpp
|
||||
extern OS_TCID audioTimer;
|
||||
extern OS_FlagID audioFlag;
|
||||
extern OS_MutexID audioMutex;
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user