summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--adpcm.c62
-rw-r--r--adpcm.h7
-rw-r--r--codec-cfg.c1
-rw-r--r--codec-cfg.h3
-rw-r--r--dec_audio.c22
-rw-r--r--etc/codecs.conf6
6 files changed, 98 insertions, 3 deletions
diff --git a/adpcm.c b/adpcm.c
index 37bbd64461..8239dfd9c5 100644
--- a/adpcm.c
+++ b/adpcm.c
@@ -298,6 +298,68 @@ int ms_adpcm_decode_block(unsigned short *output, unsigned char *input,
return (block_size - (MS_ADPCM_PREAMBLE_SIZE * channels)) * 2;
}
+// note: This decoder assumes the format 0x61 data always comes in
+// mono flavor
+int fox61_adpcm_decode_block(unsigned short *output, unsigned char *input)
+{
+ int i;
+ int out_ptr = 0;
+
+ int predictor;
+ int index;
+ int nibble;
+ int sign;
+ int delta;
+ int diff;
+ int step;
+
+ predictor = output[out_ptr++] = LE_16(&input[0]);
+ index = input[2];
+
+ // iterate through and decode the rest of the bytes
+ for (i = 4; i < FOX61_ADPCM_BLOCK_SIZE; i++)
+ {
+ nibble = (input[i] >> 4) & 0x0F;
+
+ step = adpcm_step[index];
+ sign = nibble & 8;
+ delta = nibble & 7;
+ diff = step >> 3;
+ if (delta & 4) diff += step;
+ if (delta & 2) diff += step >> 1;
+ if (delta & 1) diff += step >> 2;
+ if (sign)
+ predictor -= diff;
+ else
+ predictor += diff;
+ CLAMP_S16(predictor);
+ output[out_ptr++] = predictor;
+ index += adpcm_index[nibble];
+ CLAMP_0_TO_88(index);
+
+ nibble = input[i] & 0x0F;
+
+ step = adpcm_step[index];
+ sign = nibble & 8;
+ delta = nibble & 7;
+ diff = step >> 3;
+ if (delta & 4) diff += step;
+ if (delta & 2) diff += step >> 1;
+ if (delta & 1) diff += step >> 2;
+ if (sign)
+ predictor -= diff;
+ else
+ predictor += diff;
+ CLAMP_S16(predictor);
+ output[out_ptr++] = predictor;
+ index += adpcm_index[nibble];
+ CLAMP_0_TO_88(index);
+ }
+
+ return FOX61_ADPCM_SAMPLES_PER_BLOCK;
+}
+
+
// note: This decoder assumes the format 0x62 data always comes in
// stereo flavor
int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input,
diff --git a/adpcm.h b/adpcm.h
index d20dbc5717..939f7656b6 100644
--- a/adpcm.h
+++ b/adpcm.h
@@ -10,6 +10,11 @@
#define MS_ADPCM_SAMPLES_PER_BLOCK \
((sh_audio->wf->nBlockAlign - MS_ADPCM_PREAMBLE_SIZE) * 2)
+#define FOX61_ADPCM_PREAMBLE_SIZE 4
+#define FOX61_ADPCM_BLOCK_SIZE 0x200
+#define FOX61_ADPCM_SAMPLES_PER_BLOCK \
+ (((FOX61_ADPCM_BLOCK_SIZE - FOX61_ADPCM_PREAMBLE_SIZE) * 2) + 1)
+
// pretend there's such a thing as mono for this format
#define FOX62_ADPCM_PREAMBLE_SIZE 8
#define FOX62_ADPCM_BLOCK_SIZE 0x400
@@ -20,7 +25,7 @@ int ima_adpcm_decode_block(unsigned short *output, unsigned char *input,
int channels);
int ms_adpcm_decode_block(unsigned short *output, unsigned char *input,
int channels, int block_size);
+int fox61_adpcm_decode_block(unsigned short *output, unsigned char *input);
int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input,
int channels);
-
#endif
diff --git a/codec-cfg.c b/codec-cfg.c
index 0af0c91abe..909607ff3f 100644
--- a/codec-cfg.c
+++ b/codec-cfg.c
@@ -219,6 +219,7 @@ static short get_driver(char *s,int audioflag)
"liba52",
"g72x",
"imaadpcm",
+ "fox61adpcm",
"fox62adpcm",
NULL
};
diff --git a/codec-cfg.h b/codec-cfg.h
index f09a205826..b28f748c38 100644
--- a/codec-cfg.h
+++ b/codec-cfg.h
@@ -34,7 +34,8 @@
#define AFM_A52 14
#define AFM_G72X 15
#define AFM_IMAADPCM 16
-#define AFM_FOX62ADPCM 17
+#define AFM_FOX61ADPCM 17
+#define AFM_FOX62ADPCM 18
#define VFM_MPEG 1
#define VFM_VFW 2
diff --git a/dec_audio.c b/dec_audio.c
index bcc6c3577e..c16b07c252 100644
--- a/dec_audio.c
+++ b/dec_audio.c
@@ -412,6 +412,11 @@ case AFM_MSADPCM:
sh_audio->ds->ss_div = MS_ADPCM_SAMPLES_PER_BLOCK;
sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign;
break;
+case AFM_FOX61ADPCM:
+ sh_audio->audio_out_minsize=FOX61_ADPCM_SAMPLES_PER_BLOCK * 4;
+ sh_audio->ds->ss_div=FOX61_ADPCM_SAMPLES_PER_BLOCK;
+ sh_audio->ds->ss_mul=FOX61_ADPCM_BLOCK_SIZE;
+ break;
case AFM_FOX62ADPCM:
sh_audio->audio_out_minsize=FOX62_ADPCM_SAMPLES_PER_BLOCK * 4;
sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK;
@@ -693,6 +698,12 @@ case AFM_MSADPCM:
sh_audio->i_bps = sh_audio->wf->nBlockAlign *
(sh_audio->channels*sh_audio->samplerate) / MS_ADPCM_SAMPLES_PER_BLOCK;
break;
+case AFM_FOX61ADPCM:
+ sh_audio->channels=sh_audio->wf->nChannels;
+ sh_audio->samplerate=sh_audio->wf->nSamplesPerSec;
+ sh_audio->i_bps=FOX61_ADPCM_BLOCK_SIZE*
+ (sh_audio->channels*sh_audio->samplerate) / FOX61_ADPCM_SAMPLES_PER_BLOCK;
+ break;
case AFM_FOX62ADPCM:
sh_audio->channels=sh_audio->wf->nChannels;
sh_audio->samplerate=sh_audio->wf->nSamplesPerSec;
@@ -1122,13 +1133,22 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){
sh_audio->wf->nBlockAlign);
break;
}
+ case AFM_FOX61ADPCM:
+ { unsigned char ibuf[FOX61_ADPCM_BLOCK_SIZE]; // bytes / stereo frame
+ if (demux_read_data(sh_audio->ds, ibuf, FOX61_ADPCM_BLOCK_SIZE) !=
+ FOX61_ADPCM_BLOCK_SIZE)
+ break; // EOF
+ len=2*fox61_adpcm_decode_block((unsigned short*)buf,ibuf);
+ break;
+ }
case AFM_FOX62ADPCM:
{ unsigned char ibuf[FOX62_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame
if (demux_read_data(sh_audio->ds, ibuf,
FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) !=
FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels)
break; // EOF
- len=2*fox62_adpcm_decode_block((unsigned short*)buf,ibuf, sh_audio->wf->nChannels);
+ len = 2 * fox62_adpcm_decode_block(
+ (unsigned short*)buf,ibuf, sh_audio->wf->nChannels);
break;
}
#ifdef USE_LIBAC3
diff --git a/etc/codecs.conf b/etc/codecs.conf
index 86a5d5869a..49b9fb59c7 100644
--- a/etc/codecs.conf
+++ b/etc/codecs.conf
@@ -331,6 +331,12 @@ audiocodec msadpcm
format 0x2
driver msadpcm
+audiocodec fox61adpcm
+ info "Format 0x61 ADPCM"
+ status working
+ format 0x61
+ driver fox61adpcm
+
audiocodec fox62adpcm
info "Format 0x62 ADPCM"
status buggy