diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c old mode 100644 new mode 100755 index a75932b..6987514 --- 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; diff --git a/apps/codecs/libpcms/SOURCES b/apps/codecs/libpcms/SOURCES index 449bdbb..c2e5871 100644 --- a/apps/codecs/libpcms/SOURCES +++ b/apps/codecs/libpcms/SOURCES @@ -5,3 +5,6 @@ ieee_float.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/libpcms/dvi_adpcm.c b/apps/codecs/libpcms/dvi_adpcm.c index 3c5014f..9008fb6 100644 --- a/apps/codecs/libpcms/dvi_adpcm.c +++ b/apps/codecs/libpcms/dvi_adpcm.c @@ -21,30 +21,19 @@ ****************************************************************************/ #include "codeclib.h" #include "pcm_common.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, const unsigned char *fmtpos) @@ -53,14 +42,9 @@ static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) (void)fmtpos; - 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; } @@ -69,231 +53,214 @@ static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) * It also has to be a multiple of blockalign */ fmt->chunksize = (1 + fmt->avgbytespersec / (50*fmt->blockalign))*fmt->blockalign; - /* check that the output buffer is big enough (convert to samplespersec, - then round to the blockalign multiple below) */ - if ((((uint64_t)fmt->chunksize * ci->id3->frequency * fmt->channels * fmt->bitspersample)>>3) - /(uint64_t)fmt->avgbytespersec >= PCM_CHUNK_SIZE) - fmt->chunksize = ((uint64_t)PCM_CHUNK_SIZE * fmt->avgbytespersec - /((uint64_t)ci->id3->frequency * fmt->channels * 2 - * fmt->blockalign)) * fmt->blockalign; - + init_ima_adpcm_decoder(fmt->bitspersample, NULL); return true; } static uint32_t get_seek_pos(long seek_time) { - uint32_t newpos; - /* use avgbytespersec to round to the closest blockalign multiple, add firstblockposn. 64-bit casts to avoid overflows. */ - newpos = (((uint64_t)fmt->avgbytespersec*(seek_time - 1)) - / (1000LL*fmt->blockalign))*fmt->blockalign; - return newpos; + return (((uint64_t)fmt->avgbytespersec*(seek_time - 1)) + / (1000LL*fmt->blockalign))*fmt->blockalign; } -static int decode_dvi_adpcm(const uint8_t *inbuf, size_t inbufsize, - int32_t *outbuf, size_t *outbufcount) +static int decode(const uint8_t *inbuf, size_t inbufsize, + int32_t *outbuf, int *outbufsize) { - size_t nsamples = 0; - int sample[2]; - int samplecode[32][2]; - int i; - int stepindex[2]; - int c; - int diff; - int step; - int codem; - int code; + int ch; + unsigned int i, j; + int samples; + unsigned int nblocks = fmt->chunksize / fmt->blockalign; + int32_t init_pcmdata[2]; + int8_t init_index[2]; + int32_t *pcmbuf; + const uint8_t *adpcmbuf; - if (fmt->bitspersample != 4 && fmt->bitspersample != 3) { - DEBUGF("decode_dvi_adpcm: wrong bitspersample\n"); - return CODEC_ERROR; - } + (void)inbufsize; - /* 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; + *outbufsize = 0; + for (i = 0; i < nblocks; i++) + { + 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; } - inbuf += 4; - inbufsize -= 4; - } - if (fmt->bitspersample == 4) { - while (inbufsize >= (size_t)(fmt->channels*4) && - (nsamples + (fmt->channels*8) <= *outbufcount)) + *outbufsize += 1; + set_decode_parameters(fmt->channels, init_pcmdata, init_index); + + if (fmt->bitspersample == 4) { - for (c = 0; c < fmt->channels; c++) + samples = fmt->blockalign / (4 * fmt->channels) - 1; + *outbufsize += (samples << 3); + while (samples-- > 0) { - 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; + for (ch = 0; ch < fmt->channels; ch++) + { + pcmbuf = outbuf + ch; + for (j = 0; j < 4; j++) + { + *pcmbuf = create_pcmdata_adpcm_data_size4(ch, *inbuf ) << 13; + pcmbuf += fmt->channels; + *pcmbuf = create_pcmdata_adpcm_data_size4(ch, *inbuf >> 4) << 13; + pcmbuf += fmt->channels; + inbuf++; + } + } + outbuf += 8 * fmt->channels; } - for (i = 0; i < 8; i++) + } + else if (fmt->bitspersample == 3) + { + uint32_t adpcms; + + samples = (fmt->blockalign - 4 * fmt->channels) / (12 * fmt->channels); + *outbufsize += (samples << 5); + while (samples--) { - for (c = 0; c < fmt->channels; c++) + for (ch = 0; ch < fmt->channels; ch++) { - 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) + adpcmbuf = inbuf + ch * 4; + pcmbuf = outbuf + ch; + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + for (j = 0; j < 8; j++) { - sample[c] -= diff; - if (sample[c] < -32768) - sample[c] = -32768; + *pcmbuf = create_pcmdata(ch, adpcms >> (3 * j)) << 13; + pcmbuf += fmt->channels; } - else + adpcms = *adpcmbuf++; + adpcmbuf += (fmt->channels - 1) * 4; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + for (j = 0; j < 8; j++) { - sample[c] += diff; - if (sample[c] > 32767) - sample[c] = 32767; + *pcmbuf = create_pcmdata(ch, adpcms >> (3 * j)) << 13; + pcmbuf += fmt->channels; } - /* output the new sample */ - outbuf[nsamples] = sample[c] << 13; - nsamples++; - } - } - } - } 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]<channels - 1) * 4; + adpcms |= (*adpcmbuf++) << 16; + for (j = 0; j < 8; j++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (3 * j)) << 13; + pcmbuf += fmt->channels; + } + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + for (j = 0; j < 8; j++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (3 * j)) << 13; + pcmbuf += fmt->channels; } - samplecode[i][c] = bitstream & 7; - bitstream = bitstream>>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; } + outbuf += 32 * fmt->channels; + inbuf += 12 * 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; + } + else if (fmt->bitspersample == 5) + { + uint64_t adpcms; - /* 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; + samples = (fmt->blockalign - 4 * fmt->channels) / (20 * fmt->channels); + *outbufsize += (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 (j = 0; j < 8; j++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (5 * j)) << 13; + pcmbuf += fmt->channels; } - else { - sample[c] += diff; - if (sample[c] > 32767) - sample[c] = 32767; + adpcms = *adpcmbuf++; + adpcms |= (*adpcmbuf++) << 8; + adpcms |= (*adpcmbuf++) << 16; + adpcmbuf += (fmt->channels - 1) * 4; + adpcms |= (uint64_t)(*adpcmbuf++) << 24; + adpcms |= (uint64_t)(*adpcmbuf++) << 32; + for (j = 0; j < 8; j++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (5 * j)) << 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 (j = 0; j < 8; j++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (5 * j)) << 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 (j = 0; j < 8; j++) + { + *pcmbuf = create_pcmdata(ch, adpcms >> (5 * j)) << 13; + pcmbuf += fmt->channels; } - /* output the new sample */ - outbuf[nsamples] = sample[c] << 13; - nsamples++; } + outbuf += 32 * fmt->channels; + inbuf += 20 * fmt->channels; } } - } - - if (nsamples > *outbufcount) { - DEBUGF("decode_dvi_adpcm: output buffer overflow!\n"); - return CODEC_ERROR; - } - *outbufcount = nsamples; - if (inbufsize != 0) { - DEBUGF("decode_dvi_adpcm: n=%d unprocessed bytes\n", inbufsize); - } - return CODEC_OK; -} - -static int decode(const uint8_t *inbuf, size_t inbufsize, - int32_t *outbuf, int *outbufsize) -{ - unsigned int i; - unsigned int nblocks = fmt->chunksize / fmt->blockalign; - - (void)inbufsize; - - 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; + else /* fmt->bitspersample == 2 */ + { + samples = fmt->blockalign / (4 * fmt->channels) - 1; + *outbufsize += (samples << 4); + while (samples-- > 0) + { + for (ch = 0; ch < fmt->channels; ch++) + { + pcmbuf = outbuf + ch; + for (j = 0; j < 4; j++) + { + *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; + } } } - *outbufsize = nblocks * fmt->samplesperblock; return CODEC_OK; } diff --git a/apps/codecs/libpcms/support_formats.h b/apps/codecs/libpcms/support_formats.h old mode 100644 new mode 100755 index b6d3d64..d0faf27 --- a/apps/codecs/libpcms/support_formats.h +++ b/apps/codecs/libpcms/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 old mode 100644 new mode 100755 index 9acf00f..509c699 --- 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 old mode 100644 new mode 100755 index 67fb43b..aba327f --- 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 old mode 100644 new mode 100755 index 8ca68c1..311555c --- a/apps/metadata/wave.c +++ b/apps/metadata/wave.c @@ -39,8 +39,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 */ }; struct wave_fmt { @@ -69,6 +71,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: @@ -84,6 +87,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/libpcms/ima_adpcm_common.c b/apps/codecs/libpcms/ima_adpcm_common.c new file mode 100755 index 0000000..62fec26 --- /dev/null +++ b/apps/codecs/libpcms/ima_adpcm_common.c @@ -0,0 +1,169 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 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_adpcm_data4() + * 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_adpcm_data_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/libpcms/ima_adpcm_common.h b/apps/codecs/libpcms/ima_adpcm_common.h new file mode 100644 index 0000000..f6f4361 --- /dev/null +++ b/apps/codecs/libpcms/ima_adpcm_common.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 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_LIBPCMS_IMA_ADPCM_COMMON_H +#define CODEC_LIBPCMS_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_adpcm_data_size4(int ch, uint8_t nibble); +#endif diff --git a/apps/codecs/libpcms/qt_ima_adpcm.c b/apps/codecs/libpcms/qt_ima_adpcm.c new file mode 100755 index 0000000..21dcba4 --- /dev/null +++ b/apps/codecs/libpcms/qt_ima_adpcm.c @@ -0,0 +1,118 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 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, const unsigned char *fmtpos) +{ + fmt = format; + + (void)fmtpos; + + /* 1 chunksize = about 1/50[s] data */ + fmt->blockalign = 34 * fmt->channels; + fmt->chunksize = (ci->id3->frequency/3200) * fmt->blockalign; + + init_ima_adpcm_decoder(4, NULL); + return true; +} + +static uint32_t get_seek_pos(long seek_time) +{ + return (((uint64_t)(seek_time * ci->id3->frequency)) / 64000LL) * fmt->blockalign; +} + +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) + { + /* read block header */ + for (ch = 0; ch < fmt->channels; ch++) + { + 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); + + pcmbuf = outbuf + ch; + for (block_size = 32; block_size > 0 && inbufsize > 0; block_size--, inbufsize--) + { + *pcmbuf = create_pcmdata_adpcm_data_size4(ch, *inbuf ) << 13; + pcmbuf += fmt->channels; + *pcmbuf = create_pcmdata_adpcm_data_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/libpcms/swf_adpcm.c b/apps/codecs/libpcms/swf_adpcm.c new file mode 100755 index 0000000..cfbc63b --- /dev/null +++ b/apps/codecs/libpcms/swf_adpcm.c @@ -0,0 +1,198 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 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 struct pcm_format *fmt; + +static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) +{ + fmt = format; + + (void)fmtpos; + + 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; + + if (fmt->samplesperblock > 4096) + { + DEBUGF("CODEC_ERROR: swf adpcm samplesperblock is too large: %d\n", fmt->samplesperblock); + return false; + } + + blockbits = ((fmt->samplesperblock - 1) * fmt->bitspersample + 22) * fmt->channels; + + /* 1 chunksize = about 93 [ms] data (frequency:44.1kHz, 4096 [sample/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 uint32_t get_seek_pos(long seek_time) +{ + return ((((uint64_t)(seek_time * ci->id3->frequency * fmt->blockalign)) / + (1000LL * fmt->samplesperblock)) * blockbits + 9) >> 3; +} + +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; + static int lastbytebits = 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 (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); + } + + 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); + + 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; + + return &codec; +}