PCM alaw codec support
This commit is contained in:
@@ -729,9 +729,12 @@ void board_init()
|
||||
|
||||
startSound() ;
|
||||
|
||||
alawInit();
|
||||
|
||||
eeprom_init();
|
||||
|
||||
init_SDcard();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+60
-32
@@ -108,6 +108,33 @@ inline bool isAudioFileAvailable(uint8_t i, char * filename)
|
||||
#define isAudioFileAvailable(i, f) false
|
||||
#endif
|
||||
|
||||
uint16_t alawTable[256];
|
||||
|
||||
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
|
||||
#define QUANT_MASK (0xf) /* Quantization field mask. */
|
||||
#define SEG_SHIFT (4) /* Left shift for segment number. */
|
||||
#define SEG_MASK (0x70) /* Segment field mask. */
|
||||
|
||||
static short alaw2linear(unsigned char a_val)
|
||||
{
|
||||
int t;
|
||||
int seg;
|
||||
|
||||
a_val ^= 0x55;
|
||||
|
||||
t = a_val & QUANT_MASK;
|
||||
seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
|
||||
if(seg) t= (t + t + 1 + 32) << (seg + 2);
|
||||
else t= (t + t + 1 ) << 3;
|
||||
|
||||
return (a_val & SIGN_BIT) ? t : -t;
|
||||
}
|
||||
|
||||
void alawInit()
|
||||
{
|
||||
for (uint32_t i=0; i<256; i++)
|
||||
alawTable[i] = (0x8000 + alaw2linear(i)) >> 4;
|
||||
}
|
||||
|
||||
uint8_t audioState = 0;
|
||||
|
||||
@@ -151,6 +178,10 @@ extern uint16_t Sine_values[];
|
||||
|
||||
#define WAV_HEADER_SIZE 44
|
||||
|
||||
#define CODEC_ID_PCM_S16LE 1
|
||||
#define CODEC_ID_PCM_ALAW 6
|
||||
uint8_t pcmCodec;
|
||||
|
||||
void audioTask(void* pdata)
|
||||
{
|
||||
#if defined(SDCARD) && !defined(SIMU)
|
||||
@@ -175,7 +206,11 @@ void audioTask(void* pdata)
|
||||
CoSetFlag(audioFlag);
|
||||
bufdata = wavSamplesArray;
|
||||
wavSamplesBuffer = wavSamplesArray + WAV_BUFFER_SIZE;
|
||||
pcmCodec = wavSamplesArray[10];
|
||||
setFrequency(wavSamplesArray[12]);
|
||||
if (pcmCodec != CODEC_ID_PCM_S16LE) {
|
||||
result = f_read(&wavFile, (uint8_t *)wavSamplesArray, 12, &read);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = FR_DENIED;
|
||||
@@ -184,34 +219,41 @@ void audioTask(void* pdata)
|
||||
}
|
||||
|
||||
read = 0;
|
||||
if (result != FR_OK || f_read(&wavFile, (uint8_t *)bufdata, 2*WAV_BUFFER_SIZE, &read) != FR_OK || read != 2*WAV_BUFFER_SIZE) {
|
||||
for (uint32_t i=read/2; i<WAV_BUFFER_SIZE; i++)
|
||||
bufdata[i] = 0x8000;
|
||||
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();
|
||||
volumeInit(0);
|
||||
toneWavFile[0] = '\0';
|
||||
toneWavFile[1] = 0;
|
||||
f_close(&wavFile);
|
||||
audioState = 0;
|
||||
}
|
||||
#if 1
|
||||
{
|
||||
|
||||
if (pcmCodec == CODEC_ID_PCM_S16LE) {
|
||||
read /= 2;
|
||||
for (uint32_t i=0; i<read; i++)
|
||||
uint32_t i = 0;
|
||||
for (; i<read; i++)
|
||||
bufdata[i] = ((uint16_t)0x8000 + ((int16_t)(bufdata[i]))) >> 4;
|
||||
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;
|
||||
volumeInit(1);
|
||||
toneStart();
|
||||
}
|
||||
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();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -227,7 +269,6 @@ void audioTask(void* pdata)
|
||||
CoSetTmrCnt(audioTimer, toneTimeLeft*5, 0);
|
||||
toneTimeLeft = 0;
|
||||
}
|
||||
volumeInit(0);
|
||||
toneStart();
|
||||
CoStartTmr(audioTimer);
|
||||
}
|
||||
@@ -251,7 +292,6 @@ void audioTask(void* pdata)
|
||||
CoSetTmrCnt(audioTimer, tone2TimeLeft*5, 0);
|
||||
tone2TimeLeft = 0;
|
||||
setFrequency(tone2Freq * 6100 / 2);
|
||||
volumeInit(0);
|
||||
toneStart();
|
||||
CoStartTmr(audioTimer);
|
||||
}
|
||||
@@ -325,18 +365,6 @@ void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void volumeInit(uint8_t boost){
|
||||
if(boost == 0){
|
||||
setVolume(g_eeGeneral.speakerVolume); //then raise it
|
||||
} else {
|
||||
setVolume(g_eeGeneral.speakerVolume + 10);
|
||||
/* raise it by factor of 5 higher so wav and beep similar volume!
|
||||
this value of 10 could potentially be a secondary menu config option in
|
||||
system setup as may be different per user? */
|
||||
}
|
||||
}
|
||||
|
||||
void playFile(const char *filename)
|
||||
{
|
||||
strcpy(toneWavFile, filename);
|
||||
|
||||
+1
-2
@@ -64,13 +64,12 @@ extern uint8_t queueToneLength[AUDIO_QUEUE_LENGTH];
|
||||
extern uint8_t queueTonePause[AUDIO_QUEUE_LENGTH];
|
||||
extern uint8_t queueToneRepeat[AUDIO_QUEUE_LENGTH];
|
||||
|
||||
void initAudio();
|
||||
void alawInit();
|
||||
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);
|
||||
void volumeInit(uint8_t boost);
|
||||
|
||||
inline bool audioBusy()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user