Mercurial > libavcodec.hg
comparison adxenc.c @ 5866:b1b3dd3324ae libavcodec
split adx encoder in its own file
author | aurel |
---|---|
date | Thu, 01 Nov 2007 18:38:15 +0000 |
parents | adx.c@79a8fa9d763d |
children | 48759bfbd073 |
comparison
equal
deleted
inserted
replaced
5865:79a8fa9d763d | 5866:b1b3dd3324ae |
---|---|
1 /* | |
2 * ADX ADPCM codecs | |
3 * Copyright (c) 2001,2003 BERO | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 #include "avcodec.h" | |
22 #include "adx.h" | |
23 | |
24 /** | |
25 * @file adx.c | |
26 * SEGA CRI adx codecs. | |
27 * | |
28 * Reference documents: | |
29 * http://ku-www.ss.titech.ac.jp/~yatsushi/adx.html | |
30 * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ | |
31 */ | |
32 | |
33 /* 18 bytes <-> 32 samples */ | |
34 | |
35 static void adx_encode(unsigned char *adx,const short *wav,PREV *prev) | |
36 { | |
37 int scale; | |
38 int i; | |
39 int s0,s1,s2,d; | |
40 int max=0; | |
41 int min=0; | |
42 int data[32]; | |
43 | |
44 s1 = prev->s1; | |
45 s2 = prev->s2; | |
46 for(i=0;i<32;i++) { | |
47 s0 = wav[i]; | |
48 d = ((s0<<14) - SCALE1*s1 + SCALE2*s2)/BASEVOL; | |
49 data[i]=d; | |
50 if (max<d) max=d; | |
51 if (min>d) min=d; | |
52 s2 = s1; | |
53 s1 = s0; | |
54 } | |
55 prev->s1 = s1; | |
56 prev->s2 = s2; | |
57 | |
58 /* -8..+7 */ | |
59 | |
60 if (max==0 && min==0) { | |
61 memset(adx,0,18); | |
62 return; | |
63 } | |
64 | |
65 if (max/7>-min/8) scale = max/7; | |
66 else scale = -min/8; | |
67 | |
68 if (scale==0) scale=1; | |
69 | |
70 AV_WB16(adx, scale); | |
71 | |
72 for(i=0;i<16;i++) { | |
73 adx[i+2] = ((data[i*2]/scale)<<4) | ((data[i*2+1]/scale)&0xf); | |
74 } | |
75 } | |
76 | |
77 static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t bufsize) | |
78 { | |
79 #if 0 | |
80 struct { | |
81 uint32_t offset; /* 0x80000000 + sample start - 4 */ | |
82 unsigned char unknown1[3]; /* 03 12 04 */ | |
83 unsigned char channel; /* 1 or 2 */ | |
84 uint32_t freq; | |
85 uint32_t size; | |
86 uint32_t unknown2; /* 01 f4 03 00 */ | |
87 uint32_t unknown3; /* 00 00 00 00 */ | |
88 uint32_t unknown4; /* 00 00 00 00 */ | |
89 | |
90 /* if loop | |
91 unknown3 00 15 00 01 | |
92 unknown4 00 00 00 01 | |
93 long loop_start_sample; | |
94 long loop_start_byte; | |
95 long loop_end_sample; | |
96 long loop_end_byte; | |
97 long | |
98 */ | |
99 } adxhdr; /* big endian */ | |
100 /* offset-6 "(c)CRI" */ | |
101 #endif | |
102 AV_WB32(buf+0x00,0x80000000|0x20); | |
103 AV_WB32(buf+0x04,0x03120400|avctx->channels); | |
104 AV_WB32(buf+0x08,avctx->sample_rate); | |
105 AV_WB32(buf+0x0c,0); /* FIXME: set after */ | |
106 AV_WB32(buf+0x10,0x01040300); | |
107 AV_WB32(buf+0x14,0x00000000); | |
108 AV_WB32(buf+0x18,0x00000000); | |
109 memcpy(buf+0x1c,"\0\0(c)CRI",8); | |
110 return 0x20+4; | |
111 } | |
112 | |
113 static int adx_encode_init(AVCodecContext *avctx) | |
114 { | |
115 if (avctx->channels > 2) | |
116 return -1; /* only stereo or mono =) */ | |
117 avctx->frame_size = 32; | |
118 | |
119 avctx->coded_frame= avcodec_alloc_frame(); | |
120 avctx->coded_frame->key_frame= 1; | |
121 | |
122 // avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32; | |
123 | |
124 av_log(avctx, AV_LOG_DEBUG, "adx encode init\n"); | |
125 | |
126 return 0; | |
127 } | |
128 | |
129 static int adx_encode_close(AVCodecContext *avctx) | |
130 { | |
131 av_freep(&avctx->coded_frame); | |
132 | |
133 return 0; | |
134 } | |
135 | |
136 static int adx_encode_frame(AVCodecContext *avctx, | |
137 uint8_t *frame, int buf_size, void *data) | |
138 { | |
139 ADXContext *c = avctx->priv_data; | |
140 const short *samples = data; | |
141 unsigned char *dst = frame; | |
142 int rest = avctx->frame_size; | |
143 | |
144 /* | |
145 input data size = | |
146 ffmpeg.c: do_audio_out() | |
147 frame_bytes = enc->frame_size * 2 * enc->channels; | |
148 */ | |
149 | |
150 // printf("sz=%d ",buf_size); fflush(stdout); | |
151 if (!c->header_parsed) { | |
152 int hdrsize = adx_encode_header(avctx,dst,buf_size); | |
153 dst+=hdrsize; | |
154 c->header_parsed = 1; | |
155 } | |
156 | |
157 if (avctx->channels==1) { | |
158 while(rest>=32) { | |
159 adx_encode(dst,samples,c->prev); | |
160 dst+=18; | |
161 samples+=32; | |
162 rest-=32; | |
163 } | |
164 } else { | |
165 while(rest>=32*2) { | |
166 short tmpbuf[32*2]; | |
167 int i; | |
168 | |
169 for(i=0;i<32;i++) { | |
170 tmpbuf[i] = samples[i*2]; | |
171 tmpbuf[i+32] = samples[i*2+1]; | |
172 } | |
173 | |
174 adx_encode(dst,tmpbuf,c->prev); | |
175 adx_encode(dst+18,tmpbuf+32,c->prev+1); | |
176 dst+=18*2; | |
177 samples+=32*2; | |
178 rest-=32*2; | |
179 } | |
180 } | |
181 return dst-frame; | |
182 } | |
183 | |
184 AVCodec adpcm_adx_encoder = { | |
185 "adpcm_adx", | |
186 CODEC_TYPE_AUDIO, | |
187 CODEC_ID_ADPCM_ADX, | |
188 sizeof(ADXContext), | |
189 adx_encode_init, | |
190 adx_encode_frame, | |
191 adx_encode_close, | |
192 NULL, | |
193 }; |