00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/intreadwrite.h"
00023 #include "avcodec.h"
00024 #include "adx.h"
00025 #include "put_bits.h"
00026
00036
00037
00038 static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav,
00039 ADXChannelState *prev)
00040 {
00041 PutBitContext pb;
00042 int scale;
00043 int i;
00044 int s0,s1,s2,d;
00045 int max=0;
00046 int min=0;
00047 int data[32];
00048
00049 s1 = prev->s1;
00050 s2 = prev->s2;
00051 for(i=0;i<32;i++) {
00052 s0 = wav[i];
00053 d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS;
00054 data[i]=d;
00055 if (max<d) max=d;
00056 if (min>d) min=d;
00057 s2 = s1;
00058 s1 = s0;
00059 }
00060 prev->s1 = s1;
00061 prev->s2 = s2;
00062
00063
00064
00065 if (max==0 && min==0) {
00066 memset(adx,0,18);
00067 return;
00068 }
00069
00070 if (max/7>-min/8) scale = max/7;
00071 else scale = -min/8;
00072
00073 if (scale==0) scale=1;
00074
00075 AV_WB16(adx, scale);
00076
00077 init_put_bits(&pb, adx + 2, 16);
00078 for (i = 0; i < 32; i++)
00079 put_sbits(&pb, 4, av_clip(data[i]/scale, -8, 7));
00080 flush_put_bits(&pb);
00081 }
00082
00083 static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t bufsize)
00084 {
00085 #if 0
00086 struct {
00087 uint32_t offset;
00088 unsigned char unknown1[3];
00089 unsigned char channel;
00090 uint32_t freq;
00091 uint32_t size;
00092 uint32_t unknown2;
00093 uint32_t unknown3;
00094 uint32_t unknown4;
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 } adxhdr;
00106
00107 #endif
00108 ADXContext *c = avctx->priv_data;
00109
00110 AV_WB32(buf+0x00,0x80000000|0x20);
00111 AV_WB32(buf+0x04,0x03120400|avctx->channels);
00112 AV_WB32(buf+0x08,avctx->sample_rate);
00113 AV_WB32(buf+0x0c,0);
00114 AV_WB16(buf + 0x10, c->cutoff);
00115 AV_WB32(buf + 0x12, 0x03000000);
00116 AV_WB32(buf + 0x16, 0x00000000);
00117 AV_WB32(buf + 0x1a, 0x00000000);
00118 memcpy (buf + 0x1e, "(c)CRI", 6);
00119 return 0x20+4;
00120 }
00121
00122 static av_cold int adx_encode_init(AVCodecContext *avctx)
00123 {
00124 ADXContext *c = avctx->priv_data;
00125
00126 if (avctx->channels > 2)
00127 return -1;
00128 avctx->frame_size = 32;
00129
00130 avctx->coded_frame= avcodec_alloc_frame();
00131 avctx->coded_frame->key_frame= 1;
00132
00133
00134
00135
00136 c->cutoff = 500;
00137 ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff);
00138
00139 av_log(avctx, AV_LOG_DEBUG, "adx encode init\n");
00140
00141 return 0;
00142 }
00143
00144 static av_cold int adx_encode_close(AVCodecContext *avctx)
00145 {
00146 av_freep(&avctx->coded_frame);
00147
00148 return 0;
00149 }
00150
00151 static int adx_encode_frame(AVCodecContext *avctx,
00152 uint8_t *frame, int buf_size, void *data)
00153 {
00154 ADXContext *c = avctx->priv_data;
00155 const short *samples = data;
00156 unsigned char *dst = frame;
00157 int rest = avctx->frame_size;
00158
00159
00160
00161
00162
00163
00164
00165
00166 if (!c->header_parsed) {
00167 int hdrsize = adx_encode_header(avctx,dst,buf_size);
00168 dst+=hdrsize;
00169 c->header_parsed = 1;
00170 }
00171
00172 if (avctx->channels==1) {
00173 while(rest>=32) {
00174 adx_encode(c, dst, samples, c->prev);
00175 dst+=18;
00176 samples+=32;
00177 rest-=32;
00178 }
00179 } else {
00180 while(rest>=32*2) {
00181 short tmpbuf[32*2];
00182 int i;
00183
00184 for(i=0;i<32;i++) {
00185 tmpbuf[i] = samples[i*2];
00186 tmpbuf[i+32] = samples[i*2+1];
00187 }
00188
00189 adx_encode(c, dst, tmpbuf, c->prev);
00190 adx_encode(c, dst + 18, tmpbuf + 32, c->prev + 1);
00191 dst+=18*2;
00192 samples+=32*2;
00193 rest-=32*2;
00194 }
00195 }
00196 return dst-frame;
00197 }
00198
00199 AVCodec ff_adpcm_adx_encoder = {
00200 .name = "adpcm_adx",
00201 .type = AVMEDIA_TYPE_AUDIO,
00202 .id = CODEC_ID_ADPCM_ADX,
00203 .priv_data_size = sizeof(ADXContext),
00204 .init = adx_encode_init,
00205 .encode = adx_encode_frame,
00206 .close = adx_encode_close,
00207 .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
00208 .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"),
00209 };