ima adpcm/swf adpcm: corrects the problem the noise occurs after the play ends.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25052 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Yoshihisa Uchida 2010-03-07 07:27:45 +00:00
parent f640b89a12
commit 1e9789879f
2 changed files with 38 additions and 44 deletions

View file

@ -67,7 +67,7 @@ static struct pcm_pos *get_seek_pos(long seek_time,
return &newpos; return &newpos;
} }
static inline void decode_2bit(const uint8_t **inbuf, static inline void decode_2bit(const uint8_t **inbuf, size_t inbufsize,
int32_t **outbuf, int *outbufcount) int32_t **outbuf, int *outbufcount)
{ {
int ch; int ch;
@ -75,7 +75,7 @@ static inline void decode_2bit(const uint8_t **inbuf,
int32_t *pcmbuf; int32_t *pcmbuf;
int samples; int samples;
samples = fmt->blockalign / (4 * fmt->channels) - 1; samples = inbufsize / (4 * fmt->channels) - 1;
*outbufcount += (samples << 4); *outbufcount += (samples << 4);
while (samples-- > 0) while (samples-- > 0)
{ {
@ -99,7 +99,7 @@ static inline void decode_2bit(const uint8_t **inbuf,
} }
} }
static inline void decode_3bit(const uint8_t **inbuf, static inline void decode_3bit(const uint8_t **inbuf, size_t inbufsize,
int32_t **outbuf, int *outbufcount) int32_t **outbuf, int *outbufcount)
{ {
const uint8_t *adpcmbuf; const uint8_t *adpcmbuf;
@ -109,7 +109,7 @@ static inline void decode_3bit(const uint8_t **inbuf,
int32_t *pcmbuf; int32_t *pcmbuf;
int samples; int samples;
samples = (fmt->blockalign - 4 * fmt->channels) / (12 * fmt->channels); samples = (inbufsize - 4 * fmt->channels) / (12 * fmt->channels);
*outbufcount += (samples << 5); *outbufcount += (samples << 5);
while (samples--) while (samples--)
{ {
@ -157,7 +157,7 @@ static inline void decode_3bit(const uint8_t **inbuf,
} }
} }
static inline void decode_4bit(const uint8_t **inbuf, static inline void decode_4bit(const uint8_t **inbuf, size_t inbufsize,
int32_t **outbuf, int *outbufcount) int32_t **outbuf, int *outbufcount)
{ {
int ch; int ch;
@ -165,7 +165,7 @@ static inline void decode_4bit(const uint8_t **inbuf,
int32_t *pcmbuf; int32_t *pcmbuf;
int samples; int samples;
samples = fmt->blockalign / (4 * fmt->channels) - 1; samples = inbufsize / (4 * fmt->channels) - 1;
*outbufcount += (samples << 3); *outbufcount += (samples << 3);
while (samples-- > 0) while (samples-- > 0)
{ {
@ -185,7 +185,7 @@ static inline void decode_4bit(const uint8_t **inbuf,
} }
} }
static inline void decode_5bit(const uint8_t **inbuf, static inline void decode_5bit(const uint8_t **inbuf, size_t inbufsize,
int32_t **outbuf, int *outbufcount) int32_t **outbuf, int *outbufcount)
{ {
const uint8_t *adpcmbuf; const uint8_t *adpcmbuf;
@ -195,7 +195,7 @@ static inline void decode_5bit(const uint8_t **inbuf,
int32_t *pcmbuf; int32_t *pcmbuf;
int samples; int samples;
samples = (fmt->blockalign - 4 * fmt->channels) / (20 * fmt->channels); samples = (inbufsize - 4 * fmt->channels) / (20 * fmt->channels);
*outbufcount += (samples << 5); *outbufcount += (samples << 5);
while (samples--) while (samples--)
{ {
@ -257,46 +257,40 @@ static int decode(const uint8_t *inbuf, size_t inbufsize,
int32_t *outbuf, int *outbufcount) int32_t *outbuf, int *outbufcount)
{ {
int ch; int ch;
unsigned int i;
int32_t init_pcmdata[2]; int32_t init_pcmdata[2];
int8_t init_index[2]; int8_t init_index[2];
unsigned int nblocks = fmt->chunksize / fmt->blockalign;
(void)inbufsize;
*outbufcount = 0; *outbufcount = 0;
for (i = 0; i < nblocks; i++) for (ch = 0; ch < fmt->channels; ch++)
{ {
for (ch = 0; ch < fmt->channels; ch++) init_pcmdata[ch] = inbuf[0] | (inbuf[1] << 8);
if (init_pcmdata[ch] > 32767)
init_pcmdata[ch] -= 65536;
init_index[ch] = inbuf[2];
if (init_index[ch] > 88 || init_index[ch] < 0)
{ {
init_pcmdata[ch] = inbuf[0] | (inbuf[1] << 8); DEBUGF("CODEC_ERROR: dvi adpcm illegal step index=%d > 88\n",
if (init_pcmdata[ch] > 32767) init_index[ch]);
init_pcmdata[ch] -= 65536; return CODEC_ERROR;
init_index[ch] = inbuf[2];
if (init_index[ch] > 88 || init_index[ch] < 0)
{
DEBUGF("CODEC_ERROR: dvi adpcm illegal step index=%d > 88\n",
init_index[ch]);
return CODEC_ERROR;
}
inbuf += 4;
*outbuf++ = init_pcmdata[ch] << IMA_ADPCM_INC_DEPTH;
} }
inbuf += 4;
*outbufcount += 1; *outbuf++ = init_pcmdata[ch] << IMA_ADPCM_INC_DEPTH;
set_decode_parameters(fmt->channels, init_pcmdata, init_index);
if (fmt->bitspersample == 4)
decode_4bit(&inbuf, &outbuf, outbufcount);
else if (fmt->bitspersample == 3)
decode_3bit(&inbuf, &outbuf, outbufcount);
else if (fmt->bitspersample == 5)
decode_5bit(&inbuf, &outbuf, outbufcount);
else /* fmt->bitspersample == 2 */
decode_2bit(&inbuf, &outbuf, outbufcount);
} }
*outbufcount += 1;
set_decode_parameters(fmt->channels, init_pcmdata, init_index);
if (fmt->bitspersample == 4)
decode_4bit(&inbuf, inbufsize, &outbuf, outbufcount);
else if (fmt->bitspersample == 3)
decode_3bit(&inbuf, inbufsize, &outbuf, outbufcount);
else if (fmt->bitspersample == 5)
decode_5bit(&inbuf, inbufsize, &outbuf, outbufcount);
else /* fmt->bitspersample == 2 */
decode_2bit(&inbuf, inbufsize, &outbuf, outbufcount);
return CODEC_OK; return CODEC_OK;
} }

View file

@ -47,6 +47,8 @@ static bool after_seek = false;
static struct pcm_format *fmt; static struct pcm_format *fmt;
#define GET_SAMPLE_COUNT(s) ((((s) << 3) / fmt->channels - 22) / fmt->bitspersample + 1)
static bool set_format(struct pcm_format *format) static bool set_format(struct pcm_format *format)
{ {
fmt = format; fmt = format;
@ -139,14 +141,14 @@ static int decode(const uint8_t *inbuf, size_t inbufsize,
{ {
int ch; int ch;
int adpcm_code_size; int adpcm_code_size;
int count = fmt->samplesperblock; int count = ((size_t)fmt->chunksize == inbufsize) ? fmt->samplesperblock :
GET_SAMPLE_COUNT(inbufsize);
int32_t init_pcmdata[2]; int32_t init_pcmdata[2];
int8_t init_index[2]; int8_t init_index[2];
static uint8_t lastbyte = 0; static uint8_t lastbyte = 0;
(void)inbufsize;
validity_bits = 8; validity_bits = 8;
*outbufcount = count;
/* read block header */ /* read block header */
ch = fmt->channels - 1; ch = fmt->channels - 1;
@ -208,8 +210,6 @@ static int decode(const uint8_t *inbuf, size_t inbufsize,
<< IMA_ADPCM_INC_DEPTH; << IMA_ADPCM_INC_DEPTH;
} }
*outbufcount = fmt->samplesperblock;
lastbyte = *inbuf; lastbyte = *inbuf;
lastbytebits = (8 - validity_bits) & 0x07; lastbytebits = (8 - validity_bits) & 0x07;