diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c index 66f1770..4b87038 100755 --- a/apps/codecs/aiff.c +++ b/apps/codecs/aiff.c @@ -36,6 +36,7 @@ enum { AIFC_FORMAT_MULAW = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */ AIFC_FORMAT_IEEE_FLOAT32 = FOURCC('f', 'l', '3', '2'), /* AIFC IEEE float 32 bit */ AIFC_FORMAT_IEEE_FLOAT64 = FOURCC('f', 'l', '6', '4'), /* AIFC IEEE float 64 bit */ + AIFC_FORMAT_QT_IMA_ADPCM = FOURCC('i', 'm', 'a', '4'), /* AIFC QuickTime IMA ADPCM */ }; static const struct pcm_entry pcm_codecs[] = { @@ -44,9 +45,10 @@ static const struct pcm_entry pcm_codecs[] = { { AIFC_FORMAT_MULAW, get_itut_g711_mulaw_codec }, { AIFC_FORMAT_IEEE_FLOAT32, get_ieee_float_codec }, { AIFC_FORMAT_IEEE_FLOAT64, get_ieee_float_codec }, + { AIFC_FORMAT_QT_IMA_ADPCM, get_qt_ima_adpcm_codec }, }; -#define NUM_FORMATS 5 +#define NUM_FORMATS 6 static int32_t samples[PCM_CHUNK_SIZE] IBSS_ATTR; @@ -171,6 +173,8 @@ next_track: if (format.formattag == AIFC_FORMAT_ALAW || format.formattag == AIFC_FORMAT_MULAW) format.bitspersample = 8; + else if (format.formattag == AIFC_FORMAT_QT_IMA_ADPCM) + format.bitspersample = 4; } else format.formattag = AIFC_FORMAT_PCM; diff --git a/apps/codecs/libpcm/SOURCES b/apps/codecs/libpcm/SOURCES index 1352ce7..356c9cd 100644 --- a/apps/codecs/libpcm/SOURCES +++ b/apps/codecs/libpcm/SOURCES @@ -6,3 +6,6 @@ adpcm_seek.c dialogic_oki_adpcm.c ms_adpcm.c yamaha_adpcm.c +ima_adpcm_common.c +qt_ima_adpcm.c +swf_adpcm.c diff --git a/apps/codecs/libpcm/dvi_adpcm.c b/apps/codecs/libpcm/dvi_adpcm.c index 00dabb2..97ba017 100644 --- a/apps/codecs/libpcm/dvi_adpcm.c +++ b/apps/codecs/libpcm/dvi_adpcm.c @@ -21,50 +21,36 @@ ****************************************************************************/ #include "codeclib.h" #include "pcm_common.h" -#include "support_formats.h" +#include "ima_adpcm_common.h" /* - * Intel DVI ADPCM + * Intel DVI ADPCM (IMA ADPCM) + * + * References + * [1] The IMA Digital Audio Focus and Technical Working Groups, + * Recommended Practices for Enhancing Digital Audio Compatibility + * in Multimedia Systems Revision 3.00, 1992 + * [2] Microsoft Corporation, New Multimedia Data Types and Data Techniques, + * Revision:3.0, 1994 + * [3] ffmpeg source code, libavcodec/adpcm.c */ -static const uint16_t dvi_adpcm_steptab[89] ICONST_ATTR = { - 7, 8, 9, 10, 11, 12, 13, 14, - 16, 17, 19, 21, 23, 25, 28, 31, - 34, 37, 41, 45, 50, 55, 60, 66, - 73, 80, 88, 97, 107, 118, 130, 143, - 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, - 724, 796, 876, 963, 1060, 1166, 1282, 1411, - 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, - 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, - 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, - 32767 }; - -static const int dvi_adpcm_indextab4[8] ICONST_ATTR = { - -1, -1, -1, -1, 2, 4, 6, 8 }; - -static const int dvi_adpcm_indextab3[4] ICONST_ATTR = { -1, -1, 1, 2 }; - static struct pcm_format *fmt; static bool set_format(struct pcm_format *format) { fmt = format; - if (fmt->bitspersample != 4 && fmt->bitspersample != 3) + if (fmt->bitspersample < 2 || fmt->bitspersample > 5) { - DEBUGF("CODEC_ERROR: dvi_adpcm must have 3 or 4 bitspersample\n"); - return false; - } - - if (fmt->size < 2) { - DEBUGF("CODEC_ERROR: dvi_adpcm is missing SamplesPerBlock value\n"); + DEBUGF("CODEC_ERROR: dvi adpcm must be 2, 3, 4 or 5 bitspersample: %d\n", + fmt->bitspersample); return false; } fmt->chunksize = fmt->blockalign; + init_ima_adpcm_decoder(fmt->bitspersample, NULL); return true; } @@ -73,7 +59,7 @@ static struct pcm_pos *get_seek_pos(long seek_time, { static struct pcm_pos newpos; uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) - / (1000LL * fmt->samplesperblock); + / (1000LL * fmt->samplesperblock); (void)read_buffer; newpos.pos = newblock * fmt->blockalign; @@ -81,209 +67,236 @@ static struct pcm_pos *get_seek_pos(long seek_time, return &newpos; } -static int decode_dvi_adpcm(const uint8_t *inbuf, size_t inbufsize, - int32_t *outbuf, size_t *outbufcount) +static inline void decode_2bit(const uint8_t **inbuf, + int32_t **outbuf, int *outbufcount) { - size_t nsamples = 0; - int sample[2]; - int samplecode[32][2]; + int ch; int i; - int stepindex[2]; - int c; - int diff; - int step; - int codem; - int code; + int32_t *pcmbuf; + int samples; - if (fmt->bitspersample != 4 && fmt->bitspersample != 3) { - DEBUGF("decode_dvi_adpcm: wrong bitspersample\n"); - return CODEC_ERROR; + samples = fmt->blockalign / (4 * fmt->channels) - 1; + *outbufcount += (samples << 4); + while (samples-- > 0) + { + for (ch = 0; ch < fmt->channels; ch++) + { + pcmbuf = *outbuf + ch; + for (i = 0; i < 4; i++) + { + *pcmbuf = create_pcmdata(ch, **inbuf ) << 13; + pcmbuf += fmt->channels; + *pcmbuf = create_pcmdata(ch, **inbuf >> 2) << 13; + pcmbuf += fmt->channels; + *pcmbuf = create_pcmdata(ch, **inbuf >> 4) << 13; + pcmbuf += fmt->channels; + *pcmbuf = create_pcmdata(ch, **inbuf >> 6) << 13; + pcmbuf += fmt->channels; + (*inbuf)++; + } + } + *outbuf += 16 * fmt->channels; } +} - /* decode block header */ - for (c = 0; c < fmt->channels && inbufsize >= 4; c++) { - /* decode + push first sample */ - sample[c] = (short)(inbuf[0]|(inbuf[1]<<8));/* need cast for sign-extend */ - outbuf[c] = sample[c] << 13; - nsamples++; - stepindex[c] = inbuf[2]; - /* check for step table index overflow */ - if (stepindex[c] > 88) { - DEBUGF("decode_dvi_adpcm: stepindex[%d]=%d>88\n",c,stepindex[c]); - return CODEC_ERROR; - } +static inline void decode_3bit(const uint8_t **inbuf, + int32_t **outbuf, int *outbufcount) +{ + const uint8_t *adpcmbuf; + uint32_t adpcms; + int ch; + int i; + int32_t *pcmbuf; + int samples; - inbuf += 4; - inbufsize -= 4; - } - if (fmt->bitspersample == 4) { - while (inbufsize >= (size_t)(fmt->channels*4) && - (nsamples + (fmt->channels*8) <= *outbufcount)) + samples = (fmt->blockalign - 4 * fmt->channels) / (12 * fmt->channels); + *outbufcount += (samples << 5); + while (samples--) + { + for (ch = 0; ch < fmt->channels; ch++) { - for (c = 0; c < fmt->channels; c++) + adpcmbuf = *inbuf + ch * 4; + pcmbuf = *outbuf + ch; + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + for (i = 0; i < 8; i++) { - samplecode[0][c] = inbuf[0]&0xf; - samplecode[1][c] = inbuf[0]>>4; - samplecode[2][c] = inbuf[1]&0xf; - samplecode[3][c] = inbuf[1]>>4; - samplecode[4][c] = inbuf[2]&0xf; - samplecode[5][c] = inbuf[2]>>4; - samplecode[6][c] = inbuf[3]&0xf; - samplecode[7][c] = inbuf[3]>>4; - inbuf += 4; - inbufsize -= 4; + *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << 13; + pcmbuf += fmt->channels; } + adpcms = *adpcmbuf++; + adpcmbuf += (fmt->channels - 1) * 4; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; for (i = 0; i < 8; i++) { - for (c = 0; c < fmt->channels; c++) - { - step = dvi_adpcm_steptab[stepindex[c]]; - codem = samplecode[i][c]; - code = codem & 0x07; - - /* adjust the step table index */ - stepindex[c] += dvi_adpcm_indextab4[code]; - /* check for step table index overflow and underflow */ - if (stepindex[c] > 88) - stepindex[c] = 88; - else if (stepindex[c] < 0) - stepindex[c] = 0; - /* calculate the difference */ -#ifdef STRICT_IMA - diff = 0; - if (code & 4) - diff += step; - step = step >> 1; - if (code & 2) - diff += step; - step = step >> 1; - if (code & 1) - diff += step; - step = step >> 1; - diff += step; -#else - diff = ((code + code + 1) * step) >> 3; /* faster */ -#endif - /* check the sign bit */ - /* check for overflow and underflow errors */ - if (code != codem) - { - sample[c] -= diff; - if (sample[c] < -32768) - sample[c] = -32768; - } - else - { - sample[c] += diff; - if (sample[c] > 32767) - sample[c] = 32767; - } - /* output the new sample */ - outbuf[nsamples] = sample[c] << 13; - nsamples++; - } + *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << 13; + pcmbuf += fmt->channels; } - } - } else { /* bitspersample == 3 */ - while (inbufsize >= (uint32_t)(fmt->channels*12) && - (nsamples + 32*fmt->channels) <= *outbufcount) { - for (c = 0; c < fmt->channels; c++) { - uint16_t bitstream = 0; - int bitsread = 0; - for (i = 0; i < 32 && inbufsize > 0; i++) { - if (bitsread < 3) { - /* read 8 more bits */ - bitstream |= inbuf[0]<>3; - bitsread -= 3; - } - if (bitsread != 0) { - /* 32*3 = 3 words, so we should end with bitsread==0 */ - DEBUGF("decode_dvi_adpcm: error in implementation\n"); - return CODEC_ERROR; - } + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcmbuf += (fmt->channels - 1) * 4; + adpcms |= (*adpcmbuf++) << 16; + for (i = 0; i < 8; i++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << 13; + pcmbuf += fmt->channels; } - - for (i = 0; i < 32; i++) { - for (c = 0; c < fmt->channels; c++) { - step = dvi_adpcm_steptab[stepindex[c]]; - codem = samplecode[i][c]; - code = codem & 0x03; - - /* adjust the step table index */ - stepindex[c] += dvi_adpcm_indextab3[code]; - /* check for step table index overflow and underflow */ - if (stepindex[c] > 88) - stepindex[c] = 88; - else if (stepindex[c] < 0) - stepindex[c] = 0; - /* calculate the difference */ -#ifdef STRICT_IMA - diff = 0; - if (code & 2) - diff += step; - step = step >> 1; - if (code & 1) - diff += step; - step = step >> 1; - diff += step; -#else - diff = ((code + code + 1) * step) >> 3; /* faster */ -#endif - /* check the sign bit */ - /* check for overflow and underflow errors */ - if (code != codem) { - sample[c] -= diff; - if (sample[c] < -32768) - sample[c] = -32768; - } - else { - sample[c] += diff; - if (sample[c] > 32767) - sample[c] = 32767; - } - /* output the new sample */ - outbuf[nsamples] = sample[c] << 13; - nsamples++; - } + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + for (i = 0; i < 8; i++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << 13; + pcmbuf += fmt->channels; } } + *outbuf += 32 * fmt->channels; + *inbuf += 12 * fmt->channels; } +} + +static inline void decode_4bit(const uint8_t **inbuf, + int32_t **outbuf, int *outbufcount) +{ + int ch; + int i; + int32_t *pcmbuf; + int samples; - if (nsamples > *outbufcount) { - DEBUGF("decode_dvi_adpcm: output buffer overflow!\n"); - return CODEC_ERROR; + samples = fmt->blockalign / (4 * fmt->channels) - 1; + *outbufcount += (samples << 3); + while (samples-- > 0) + { + for (ch = 0; ch < fmt->channels; ch++) + { + pcmbuf = *outbuf + ch; + for (i = 0; i < 4; i++) + { + *pcmbuf = create_pcmdata_size4(ch, **inbuf ) << 13; + pcmbuf += fmt->channels; + *pcmbuf = create_pcmdata_size4(ch, **inbuf >> 4) << 13; + pcmbuf += fmt->channels; + (*inbuf)++; + } + } + *outbuf += 8 * fmt->channels; } - *outbufcount = nsamples; - if (inbufsize != 0) { - DEBUGF("decode_dvi_adpcm: n=%d unprocessed bytes\n", (int)inbufsize); +} + +static inline void decode_5bit(const uint8_t **inbuf, + int32_t **outbuf, int *outbufcount) +{ + const uint8_t *adpcmbuf; + uint64_t adpcms; + int ch; + int i; + int32_t *pcmbuf; + int samples; + + samples = (fmt->blockalign - 4 * fmt->channels) / (20 * fmt->channels); + *outbufcount += (samples << 5); + while (samples--) + { + for (ch = 0; ch < fmt->channels; ch++) + { + adpcmbuf = *inbuf + ch * 4; + pcmbuf = *outbuf + ch; + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + adpcms |= (uint64_t)(*adpcmbuf++) << 24; + adpcmbuf += (fmt->channels - 1) * 4; + adpcms |= (uint64_t)(*adpcmbuf++) << 32; + for (i = 0; i < 8; i++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << 13; + pcmbuf += fmt->channels; + } + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + adpcmbuf += (fmt->channels - 1) * 4; + adpcms |= (uint64_t)(*adpcmbuf++) << 24; + adpcms |= (uint64_t)(*adpcmbuf++) << 32; + for (i = 0; i < 8; i++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << 13; + pcmbuf += fmt->channels; + } + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcmbuf += (fmt->channels - 1) * 4; + adpcms |= (*adpcmbuf++) << 16; + adpcms |= (uint64_t)(*adpcmbuf++) << 24; + adpcms |= (uint64_t)(*adpcmbuf++) << 32; + for (i = 0; i < 8; i++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << 13; + pcmbuf += fmt->channels; + } + adpcms = *adpcmbuf++; + adpcmbuf += (fmt->channels - 1) * 4; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + adpcms |= (uint64_t)(*adpcmbuf++) << 24; + adpcms |= (uint64_t)(*adpcmbuf++) << 32; + for (i = 0; i < 8; i++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << 13; + pcmbuf += fmt->channels; + } + } + *outbuf += 32 * fmt->channels; + *inbuf += 20 * fmt->channels; } - return CODEC_OK; } static int decode(const uint8_t *inbuf, size_t inbufsize, - int32_t *outbuf, int *outbufsize) + int32_t *outbuf, int *outbufcount) { + int ch; unsigned int i; + int32_t init_pcmdata[2]; + int8_t init_index[2]; unsigned int nblocks = fmt->chunksize / fmt->blockalign; (void)inbufsize; + *outbufcount = 0; for (i = 0; i < nblocks; i++) { - size_t decodedsize = fmt->samplesperblock * fmt->channels; - if (decode_dvi_adpcm(inbuf + i * fmt->blockalign, fmt->blockalign, - outbuf + i * fmt->samplesperblock * fmt->channels, - &decodedsize) != CODEC_OK) { - return CODEC_ERROR; + 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) + { + DEBUGF("CODEC_ERROR: dvi adpcm illegal step index=%d > 88\n", + init_index[ch]); + return CODEC_ERROR; + } + inbuf += 4; + + *outbuf++ = init_pcmdata[ch] << 13; } + + *outbufcount += 1; + 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); } - *outbufsize = nblocks * fmt->samplesperblock; return CODEC_OK; } diff --git a/apps/codecs/libpcm/support_formats.h b/apps/codecs/libpcm/support_formats.h index fb1617e..b1e089e 100644 --- a/apps/codecs/libpcm/support_formats.h +++ b/apps/codecs/libpcm/support_formats.h @@ -32,7 +32,7 @@ const struct pcm_codec *get_itut_g711_alaw_codec(void); /* ITU-T G.711 mu-law */ const struct pcm_codec *get_itut_g711_mulaw_codec(void); -/* Intel DVI ADPCM */ +/* Intel DVI ADPCM (IMA ADPCM) */ const struct pcm_codec *get_dvi_adpcm_codec(void); /* IEEE float */ @@ -46,4 +46,10 @@ const struct pcm_codec *get_dialogic_oki_adpcm_codec(void); /* YAMAHA ADPCM */ const struct pcm_codec *get_yamaha_adpcm_codec(void); + +/* Apple QuickTime IMA ADPCM */ +const struct pcm_codec *get_qt_ima_adpcm_codec(void); + +/* Adobe SWF ADPCM */ +const struct pcm_codec *get_swf_adpcm_codec(void); #endif diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index 664f993..c24ef81 100755 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c @@ -52,8 +52,10 @@ enum WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */ WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */ WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */ + WAVE_FORMAT_XBOX_ADPCM = 0x0069, /* XBOX ADPCM */ IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */ IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ + WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */ WAVE_FORMAT_EXTENSIBLE = 0xFFFE }; @@ -67,11 +69,13 @@ const struct pcm_entry wave_codecs[] = { { WAVE_FORMAT_DVI_ADPCM, get_dvi_adpcm_codec }, { WAVE_FORMAT_DIALOGIC_OKI_ADPCM, get_dialogic_oki_adpcm_codec }, { WAVE_FORMAT_YAMAHA_ADPCM, get_yamaha_adpcm_codec }, + { WAVE_FORMAT_XBOX_ADPCM, get_dvi_adpcm_codec }, { IBM_FORMAT_MULAW, get_itut_g711_mulaw_codec }, { IBM_FORMAT_ALAW, get_itut_g711_alaw_codec }, + { WAVE_FORMAT_SWF_ADPCM, get_swf_adpcm_codec }, }; -#define NUM_FORMATS 11 +#define NUM_FORMATS 13 static const struct pcm_codec *get_wave_codec(uint32_t formattag) { diff --git a/apps/metadata/aiff.c b/apps/metadata/aiff.c index 67fb43b..aba327f 100644 --- a/apps/metadata/aiff.c +++ b/apps/metadata/aiff.c @@ -29,6 +29,9 @@ #include "metadata_common.h" #include "metadata_parsers.h" +/* compressionType: AIFC QuickTime IMA ADPCM */ +#define AIFC_FORMAT_QT_IMA_ADPCM "ima4" + bool get_aiff_metadata(int fd, struct mp3entry* id3) { /* Use the trackname part of the id3 structure as a temporary buffer */ @@ -40,6 +43,7 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) unsigned long numbytes = 0; int read_bytes; int i; + bool is_aifc = false; if ((lseek(fd, 0, SEEK_SET) < 0) || ((read_bytes = read(fd, buf, sizeof(id3->path))) < 54)) @@ -47,10 +51,15 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) return false; } - if ((memcmp(buf, "FORM",4) != 0) - || ((memcmp(&buf[8], "AIFF", 4) !=0) && (memcmp(&buf[8], "AIFC", 4) !=0))) - { + if (memcmp(buf, "FORM",4) != 0) return false; + + if (memcmp(&buf[8], "AIFF", 4) != 0) + { + if (memcmp(&buf[8], "AIFC", 4) != 0) + return false; + + is_aifc = true; } buf += 12; @@ -75,7 +84,13 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) /* save format infos */ id3->bitrate = (sampleSize * numChannels * sampleRate) / 1000; id3->frequency = sampleRate; - id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency; + if (!is_aifc || memcmp(&buf[26], AIFC_FORMAT_QT_IMA_ADPCM, 4) != 0) + id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency; + else + { + /* QuickTime IMA ADPCM is 1block = 64 data for each channel */ + id3->length = (int64_t)(numSampleFrames * 64000LL) / id3->frequency; + } id3->vbr = false; /* AIFF files are CBR */ id3->filesize = filesize(fd); diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c index c8a0b19..f395e75 100755 --- a/apps/metadata/wave.c +++ b/apps/metadata/wave.c @@ -51,9 +51,11 @@ enum WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */ WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */ WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */ + WAVE_FORMAT_XBOX_ADPCM = 0x0069, /* XBOX ADPCM */ IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */ IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ WAVE_FORMAT_ATRAC3 = 0x0270, /* Atrac3 stream */ + WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */ }; struct wave_fmt { @@ -82,6 +84,7 @@ static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3 break; case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_DVI_ADPCM: + case WAVE_FORMAT_XBOX_ADPCM: totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; break; case WAVE_FORMAT_YAMAHA_ADPCM: @@ -97,6 +100,13 @@ static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3 case WAVE_FORMAT_DIALOGIC_OKI_ADPCM: totalsamples = 2 * fmt->numbytes; break; + case WAVE_FORMAT_SWF_ADPCM: + if (fmt->samplesperblock == 0) + fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22) + / fmt->bitspersample; + + totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; + break; default: totalsamples = 0; break; diff --git a/apps/codecs/libpcm/ima_adpcm_common.c b/apps/codecs/libpcm/ima_adpcm_common.c new file mode 100644 index 0000000..ff5051f --- /dev/null +++ b/apps/codecs/libpcm/ima_adpcm_common.c @@ -0,0 +1,171 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "codeclib.h" +#include "pcm_common.h" +#include "ima_adpcm_common.h" + +/* + * Functions for IMA ADPCM and IMA ADPCM series format + * + * References + * [1] The IMA Digital Audio Focus and Technical Working Groups, + * Recommended Practices for Enhancing Digital Audio Compatibility + * in Multimedia Systems Revision 3.00, 1992 + * [2] Microsoft Corporation, New Multimedia Data Types and Data Techniques, + * Revision:3.0, 1994 + * [3] ffmpeg source code, libavcodec/adpcm.c + */ + +/* step table */ +static const uint16_t step_table[89] ICONST_ATTR = { + 7, 8, 9, 10, 11, 12, 13, 14, + 16, 17, 19, 21, 23, 25, 28, 31, + 34, 37, 41, 45, 50, 55, 60, 66, + 73, 80, 88, 97, 107, 118, 130, 143, + 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, + 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, + 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767 +}; + +/* step index tables */ +static const int index_tables[4][16] ICONST_ATTR = { + /* adpcm data size is 2 */ + { -1, 2 }, + /* adpcm data size is 3 */ + { -1, -1, 1, 2 }, + /* adpcm data size is 4 */ + { -1, -1, -1, -1, 2, 4, 6, 8 }, + /* adpcm data size is 5 */ + { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 }, +}; + +static int32_t pcmdata[2]; +static int8_t index[2]; + +static int adpcm_data_size; +static uint8_t step_mask; +static uint8_t step_sign_mask; +static int8_t step_shift; +static const int *use_index_table; + +/* + * Before first decoding, this function must be executed. + * + * params + * bit: adpcm data size (2 <= bit <= 5). + * index_table: step index table + * if index_table is null, then step index table + * is used index_tables[bit-2]. + */ +void init_ima_adpcm_decoder(int bit, const int *index_table) +{ + adpcm_data_size = bit; + step_sign_mask = 1 << (adpcm_data_size - 1); + step_mask = step_sign_mask - 1; + step_shift = adpcm_data_size - 2; + if (index_table) + use_index_table = index_table; + else + use_index_table = index_tables[adpcm_data_size - 2]; +} + +/* + * When starting decoding for each block, this function must be executed. + * + * params + * channels: channel count + * init_pcmdata: array of init pcmdata + * init_index: array of init step indexes + */ +void set_decode_parameters(int channels, int32_t *init_pcmdata, int8_t *init_index) +{ + int ch; + + for (ch = 0; ch < channels; ch++) + { + pcmdata[ch] = init_pcmdata[ch]; + index[ch] = init_index[ch]; + } +} + +/* + * convert ADPCM to PCM for any adpcm data size. + * + * If adpcm_data_size is 4, then you use create_pcmdata_size4() + * in place of this functon. + */ +int16_t create_pcmdata(int ch, uint8_t nibble) +{ + int check_bit = 1 << step_shift; + int32_t delta = 0; + int16_t step = step_table[index[ch]]; + + do { + if (nibble & check_bit) + delta += step; + step >>= 1; + check_bit >>= 1; + } while (check_bit); + delta += step; + + if (nibble & step_sign_mask) + pcmdata[ch] -= delta; + else + pcmdata[ch] += delta; + + index[ch] += use_index_table[nibble & step_mask]; + CLIP(index[ch], 0, 88); + + CLIP(pcmdata[ch], -32768, 32767); + + return (int16_t)pcmdata[ch]; +} + +/* + * convert ADPCM to PCM when adpcm data size is 4. + */ +int16_t create_pcmdata_size4(int ch, uint8_t nibble) +{ + int32_t delta; + int16_t step = step_table[index[ch]]; + + delta = (step >> 3); + if (nibble & 4) delta += step; + if (nibble & 2) delta += (step >> 1); + if (nibble & 1) delta += (step >> 2); + + if (nibble & 0x08) + pcmdata[ch] -= delta; + else + pcmdata[ch] += delta; + + index[ch] += use_index_table[nibble & 0x07]; + CLIP(index[ch], 0, 88); + + CLIP(pcmdata[ch], -32768, 32767); + + return (int16_t)pcmdata[ch]; +} diff --git a/apps/codecs/libpcm/ima_adpcm_common.h b/apps/codecs/libpcm/ima_adpcm_common.h new file mode 100644 index 0000000..65cfefc --- /dev/null +++ b/apps/codecs/libpcm/ima_adpcm_common.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef CODEC_LIBPCM_IMA_ADPCM_COMMON_H +#define CODEC_LIBPCM_IMA_ADPCM_COMMON_H + +#include +#include +#include + +void init_ima_adpcm_decoder(int bit, const int *index_table); +void set_decode_parameters(int channels, int32_t *init_pcmdata, int8_t *init_index); +int16_t create_pcmdata(int ch, uint8_t nibble); +int16_t create_pcmdata_size4(int ch, uint8_t nibble); +#endif diff --git a/apps/codecs/libpcm/qt_ima_adpcm.c b/apps/codecs/libpcm/qt_ima_adpcm.c new file mode 100644 index 0000000..a34e0e8 --- /dev/null +++ b/apps/codecs/libpcm/qt_ima_adpcm.c @@ -0,0 +1,136 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "codeclib.h" +#include "pcm_common.h" +#include "ima_adpcm_common.h" + +/* + * Apple QuickTime IMA ADPCM + * + * References + * [1] Multimedia Wiki, Apple QuickTime IMA ADPCM + * URL:http://wiki.multimedia.cx/index.php?title=Apple_QuickTime_IMA_ADPCM + * [2] Apple Inc., Technical Note TN1081 Understanding the Differences Between + * Apple and Windows IMA-ADPCM Compressed Sound Files, 1996 + * [3] ffmpeg source code, libavcodec/adpcm.c + */ + +static struct pcm_format *fmt; + +static bool set_format(struct pcm_format *format) +{ + fmt = format; + + if (fmt->bitspersample != 4) + { + DEBUGF("CODEC_ERROR: quicktime ima adpcm must be 4 bitspersample: %d\n", + fmt->bitspersample); + return false; + } + + fmt->blockalign = 34 * fmt->channels; + fmt->samplesperblock = 64; + + /* chunksize = about 1/50[s] data */ + fmt->chunksize = (ci->id3->frequency / (50 * fmt->samplesperblock)) + * fmt->blockalign; + + init_ima_adpcm_decoder(4, NULL); + return true; +} + +static struct pcm_pos *get_seek_pos(long seek_time, + uint8_t *(*read_buffer)(size_t *realsize)) +{ + static struct pcm_pos newpos; + uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) + / (1000LL * fmt->samplesperblock); + + (void)read_buffer; + newpos.pos = newblock * fmt->blockalign; + newpos.samples = newblock * fmt->samplesperblock; + return &newpos; +} + +static int decode(const uint8_t *inbuf, size_t inbufsize, + int32_t *outbuf, int *outbufcount) +{ + int ch; + size_t nsamples = 0; + int block_size; + int32_t *pcmbuf; + int32_t init_pcmdata; + int8_t init_index; + + while (inbufsize > 0) + { + for (ch = 0; ch < fmt->channels; ch++) + { + /* read block header */ + init_pcmdata = (inbuf[0] << 8)|(inbuf[1] & 0x80); + if (init_pcmdata > 32767) + init_pcmdata -= 65536; + + init_index = inbuf[1] & 0x7f; + if (init_index > 88) + { + DEBUGF("CODEC_ERROR: quicktime ima adpcm illegal step index=%d > 88\n", + init_index); + return CODEC_ERROR; + } + + inbuf += 2; + inbufsize -= 2; + + set_decode_parameters(1, &init_pcmdata, &init_index); + + /* read block data */ + pcmbuf = outbuf + ch; + for (block_size = 32; block_size > 0 && inbufsize > 0; block_size--, inbufsize--) + { + *pcmbuf = create_pcmdata_size4(ch, *inbuf ) << 13; + pcmbuf += fmt->channels; + *pcmbuf = create_pcmdata_size4(ch, *inbuf >> 4) << 13; + pcmbuf += fmt->channels; + nsamples += 2; + inbuf++; + } + } + outbuf += 64 * fmt->channels; + } + + if (fmt->channels == 2) + nsamples >>= 1; + *outbufcount = nsamples; + + return CODEC_OK; +} + +static const struct pcm_codec codec = { + set_format, + get_seek_pos, + decode, + }; + +const struct pcm_codec *get_qt_ima_adpcm_codec(void) +{ + return &codec; +} diff --git a/apps/codecs/libpcm/swf_adpcm.c b/apps/codecs/libpcm/swf_adpcm.c new file mode 100644 index 0000000..456e1cd --- /dev/null +++ b/apps/codecs/libpcm/swf_adpcm.c @@ -0,0 +1,233 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "codeclib.h" +#include "pcm_common.h" +#include "ima_adpcm_common.h" + +/* + * Adobe SWF ADPCM + * + * References + * [1] Adobe, SWF File Format Specification Version 10, 2008 + * [2] Jack Jansen, adpcm.c in adpcm.zip + * [3] ffmpeg source code, libavcodec/adpcm.c + */ + +/* step index table when bitspersample is 3. + * (when bitspersample is 2, 4, 5, step index table uses the table + * which is defined ima_adpcm_common.c.) + */ +static const int index_table[4] ICONST_ATTR = { + -1, -1, 2, 4, +}; + +static int validity_bits = 8; +static bool first_block = true; +static int blockbits = 0; +static int lastbytebits = 0; +static bool after_seek = false; + +static struct pcm_format *fmt; + +static bool set_format(struct pcm_format *format) +{ + fmt = format; + + if (fmt->bitspersample < 2 || fmt->bitspersample > 5) + { + DEBUGF("CODEC_ERROR: swf adpcm must be 2, 3, 4 or 5 bitspersample: %d\n", + fmt->bitspersample); + return false; + } + + if (fmt->samplesperblock == 0) + fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22) + / fmt->bitspersample + 1; + + blockbits = ((fmt->samplesperblock - 1) * fmt->bitspersample + 22) * fmt->channels; + + /* + * chunksize = about 93 [ms] data (frequency:44.1kHz, 4096 [sample/block]) + * chunksize changes depending upon the position of block. + */ + fmt->chunksize = (blockbits + 9) >> 3; + + /* initialize for ima adpcm common functions */ + if (fmt->bitspersample == 3) + init_ima_adpcm_decoder(fmt->bitspersample, index_table); + else + init_ima_adpcm_decoder(fmt->bitspersample, NULL); + + return true; +} + +static struct pcm_pos *get_seek_pos(long seek_time, + uint8_t *(*read_buffer)(size_t *realsize)) +{ + static struct pcm_pos newpos; + uint32_t chunkbits = blockbits; + uint32_t seekbits = (((uint64_t)seek_time * ci->id3->frequency) + / (1000LL * fmt->samplesperblock)) * blockbits + 2; + + (void)read_buffer; + + newpos.pos = seekbits >> 3; + newpos.samples = (((uint64_t)seek_time * ci->id3->frequency) + / (1000LL * fmt->samplesperblock)) + * fmt->samplesperblock; + + if (newpos.pos == 0) + { + first_block = true; + lastbytebits = 0; + } + else + { + first_block = false; + lastbytebits = seekbits & 0x07; + if (lastbytebits != 0) + chunkbits -= (8 - lastbytebits); + } + + /* calculates next read bytes */ + fmt->chunksize = (chunkbits >> 3) + (((chunkbits & 0x07) > 0)?1:0) + + ((lastbytebits > 0)?1:0); + + after_seek = true; + return &newpos; +} + +static uint8_t get_data(const uint8_t **buf, int bit) +{ + uint8_t res = 0; + uint8_t mask = (1 << bit) - 1; + + if (validity_bits >= bit) + { + validity_bits -= bit; + return (**buf >> validity_bits) & mask; + } + + if (validity_bits > 0) + res = **buf << (bit - validity_bits); + + validity_bits += 8 - bit; + res = (res | (*(++(*buf)) >> validity_bits)) & mask; + return res; +} + +static int decode(const uint8_t *inbuf, size_t inbufsize, + int32_t *outbuf, int *outbufcount) +{ + int ch; + int adpcm_code_size; + int count = fmt->samplesperblock; + int32_t init_pcmdata[2]; + int8_t init_index[2]; + static uint8_t lastbyte = 0; + + (void)inbufsize; + + validity_bits = 8; + + /* read block header */ + ch = fmt->channels - 1; + if (first_block) + { + adpcm_code_size = get_data(&inbuf, 2) + 2; + if (fmt->bitspersample != adpcm_code_size) + { + DEBUGF("CODEC_ERROR: swf adpcm different adpcm code size=%d != %d\n", + adpcm_code_size, fmt->bitspersample); + return CODEC_ERROR; + } + init_pcmdata[0] = (get_data(&inbuf, 8) << 8) | get_data(&inbuf, 8); + + lastbytebits = 0; + first_block = false; + } + else + { + if (after_seek && lastbytebits > 0) + { + lastbyte = *inbuf++; + after_seek = false; + } + if (lastbytebits > 0) + init_pcmdata[0] = ((lastbyte << (8 + lastbytebits)) | + (get_data(&inbuf, 8) << lastbytebits) | + get_data(&inbuf, lastbytebits)) & 65535; + else + init_pcmdata[0] = (get_data(&inbuf, 8) << 8) | get_data(&inbuf, 8); + } + after_seek = false; + + init_index[0] = get_data(&inbuf, 6); + if (init_pcmdata[0] > 32767) + init_pcmdata[0] -= 65536; + + if (ch > 0) + { + init_pcmdata[1] = (get_data(&inbuf, 8) << 8) | get_data(&inbuf, 8); + init_index[1] = get_data(&inbuf, 6); + if (init_pcmdata[1] > 32767) + init_pcmdata[1] -= 65536; + } + + *outbuf++ = init_pcmdata[0] << 13; + if (ch > 0) + *outbuf++ = init_pcmdata[1] << 13; + + set_decode_parameters(fmt->channels, init_pcmdata, init_index); + + /* read block data */ + while (--count > 0) + { + *outbuf++ = create_pcmdata(0, get_data(&inbuf, fmt->bitspersample)) << 13; + if (ch > 0) + *outbuf++ = create_pcmdata(ch, get_data(&inbuf, fmt->bitspersample)) << 13; + } + + *outbufcount = fmt->samplesperblock; + + lastbyte = *inbuf; + lastbytebits = (8 - validity_bits) & 0x07; + + /* calculates next read bytes */ + fmt->chunksize = (blockbits - validity_bits + 7) >> 3; + + return CODEC_OK; +} + +static const struct pcm_codec codec = { + set_format, + get_seek_pos, + decode, + }; + +const struct pcm_codec *get_swf_adpcm_codec(void) +{ + first_block = true; + lastbytebits = 0; + after_seek = false; + + return &codec; +}