[sky9x/Taranis] Audio mixer!

This commit is contained in:
bsongis@gmail.com
2013-06-15 16:18:08 +00:00
parent 46ae2e434a
commit f79e2aba4f
12 changed files with 524 additions and 576 deletions
+114 -49
View File
@@ -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