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