00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avcodec.h"
00022
00032 static const char ws_adpcm_2bit[] = { -2, -1, 0, 1};
00033 static const char ws_adpcm_4bit[] = {
00034 -9, -8, -6, -5, -4, -3, -2, -1,
00035 0, 1, 2, 3, 4, 5, 6, 8 };
00036
00037 #define CLIP8(a) if(a>127)a=127;if(a<-128)a=-128;
00038
00039 static int ws_snd_decode_init(AVCodecContext * avctx)
00040 {
00041
00042
00043 return 0;
00044 }
00045
00046 static int ws_snd_decode_frame(AVCodecContext *avctx,
00047 void *data, int *data_size,
00048 const uint8_t *buf, int buf_size)
00049 {
00050
00051
00052 int in_size, out_size;
00053 int sample = 0;
00054 int i;
00055 short *samples = data;
00056
00057 if (!buf_size)
00058 return 0;
00059
00060 out_size = AV_RL16(&buf[0]);
00061 *data_size = out_size * 2;
00062 in_size = AV_RL16(&buf[2]);
00063 buf += 4;
00064
00065 if (out_size > *data_size) {
00066 av_log(avctx, AV_LOG_ERROR, "Frame is too large to fit in buffer\n");
00067 return -1;
00068 }
00069 if (in_size > buf_size) {
00070 av_log(avctx, AV_LOG_ERROR, "Frame data is larger than input buffer\n");
00071 return -1;
00072 }
00073 if (in_size == out_size) {
00074 for (i = 0; i < out_size; i++)
00075 *samples++ = (*buf++ - 0x80) << 8;
00076 return buf_size;
00077 }
00078
00079 while (out_size > 0) {
00080 int code;
00081 uint8_t count;
00082 code = (*buf) >> 6;
00083 count = (*buf) & 0x3F;
00084 buf++;
00085 switch(code) {
00086 case 0:
00087 for (count++; count > 0; count--) {
00088 code = *buf++;
00089 sample += ws_adpcm_2bit[code & 0x3];
00090 CLIP8(sample);
00091 *samples++ = sample << 8;
00092 sample += ws_adpcm_2bit[(code >> 2) & 0x3];
00093 CLIP8(sample);
00094 *samples++ = sample << 8;
00095 sample += ws_adpcm_2bit[(code >> 4) & 0x3];
00096 CLIP8(sample);
00097 *samples++ = sample << 8;
00098 sample += ws_adpcm_2bit[(code >> 6) & 0x3];
00099 CLIP8(sample);
00100 *samples++ = sample << 8;
00101 out_size -= 4;
00102 }
00103 break;
00104 case 1:
00105 for (count++; count > 0; count--) {
00106 code = *buf++;
00107 sample += ws_adpcm_4bit[code & 0xF];
00108 CLIP8(sample);
00109 *samples++ = sample << 8;
00110 sample += ws_adpcm_4bit[code >> 4];
00111 CLIP8(sample);
00112 *samples++ = sample << 8;
00113 out_size -= 2;
00114 }
00115 break;
00116 case 2:
00117 if (count & 0x20) {
00118 char t;
00119 t = count;
00120 t <<= 3;
00121 sample += t >> 3;
00122 *samples++ = sample << 8;
00123 out_size--;
00124 } else {
00125 for (count++; count > 0; count--) {
00126 *samples++ = (*buf++ - 0x80) << 8;
00127 out_size--;
00128 }
00129 sample = buf[-1] - 0x80;
00130 }
00131 break;
00132 default:
00133 for(count++; count > 0; count--) {
00134 *samples++ = sample << 8;
00135 out_size--;
00136 }
00137 }
00138 }
00139
00140 return buf_size;
00141 }
00142
00143 AVCodec ws_snd1_decoder = {
00144 "ws_snd1",
00145 CODEC_TYPE_AUDIO,
00146 CODEC_ID_WESTWOOD_SND1,
00147 0,
00148 ws_snd_decode_init,
00149 NULL,
00150 NULL,
00151 ws_snd_decode_frame,
00152 };