Mercurial > mplayer.hg
annotate libmpcodecs/ad_dk3adpcm.c @ 26110:69790f7caffa
configure: Set CONFIG_ENCODERS=yes in config.mak unconditionally
config.h already had "#define CONFIG_ENCODERS 1" unconditionally, but
the config.mak value depended on whether MEncoder was enabled.
Encoders need to be enabled as some encoder code is used by MPlayer
too. The inconsistent values broke compilation with --disable-mencoder
after libavcodec Makefile made compilation of i386/dsputilenc_mmx.o
depend on the config.mak value.
author | uau |
---|---|
date | Mon, 03 Mar 2008 03:02:36 +0000 |
parents | fa99b3d31d13 |
children | b21e1506e50b |
rev | line source |
---|---|
5408 | 1 /* |
2 DK3 ADPCM Decoder for MPlayer | |
3 by Mike Melanson | |
4 | |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
5 "This format number was used by Duck Corp. but not officially |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
6 registered with Microsoft" |
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
7 |
5408 | 8 This file is responsible for decoding audio data encoded with |
9 Duck Corp's DK3 ADPCM algorithm. Details about the data format | |
10 can be found here: | |
11 http://www.pcisys.net/~melanson/codecs/ | |
12 */ | |
13 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
14 #include <stdio.h> |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
15 #include <stdlib.h> |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
16 #include <unistd.h> |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
17 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
18 #include "config.h" |
21372 | 19 #include "libavutil/common.h" |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
20 #include "mpbswap.h" |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
21 #include "ad_internal.h" |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
22 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
23 static ad_info_t info = |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
24 { |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
25 "Duck Corp. DK3 ADPCM decoder", |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
26 "dk3adpcm", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
27 "Nick Kurshev", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
28 "Mike Melanson", |
7191
1eadce15446c
-afm/-vfm help implemenetd, some cosmetics of ad/vd codec names/comments
arpi
parents:
7180
diff
changeset
|
29 "" |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
30 }; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
31 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
32 LIBAD_EXTERN(dk3adpcm) |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
33 |
5408 | 34 #define DK3_ADPCM_PREAMBLE_SIZE 16 |
35 | |
36 #define LE_16(x) (le2me_16(*(unsigned short *)(x))) | |
37 #define LE_32(x) (le2me_32(*(unsigned int *)(x))) | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
38 |
5408 | 39 // useful macros |
40 // clamp a number between 0 and 88 | |
41 #define CLAMP_0_TO_88(x) if (x < 0) x = 0; else if (x > 88) x = 88; | |
42 // clamp a number within a signed 16-bit range | |
43 #define CLAMP_S16(x) if (x < -32768) x = -32768; \ | |
44 else if (x > 32767) x = 32767; | |
45 // clamp a number above 16 | |
46 #define CLAMP_ABOVE_16(x) if (x < 16) x = 16; | |
47 // sign extend a 16-bit value | |
48 #define SE_16BIT(x) if (x & 0x8000) x -= 0x10000; | |
49 // sign extend a 4-bit value | |
50 #define SE_4BIT(x) if (x & 0x8) x -= 0x10; | |
51 | |
52 // pertinent tables | |
53 static int adpcm_step[89] = | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
54 { |
5408 | 55 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, |
56 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, | |
57 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, | |
58 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, | |
59 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, | |
60 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, | |
61 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, | |
62 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | |
63 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 | |
64 }; | |
65 | |
66 static int adpcm_index[16] = | |
67 { | |
68 -1, -1, -1, -1, 2, 4, 6, 8, | |
69 -1, -1, -1, -1, 2, 4, 6, 8 | |
70 }; | |
71 | |
72 static int preinit(sh_audio_t *sh_audio) | |
73 { | |
74 sh_audio->audio_out_minsize = sh_audio->wf->nBlockAlign * 6; | |
75 sh_audio->ds->ss_div = | |
76 (sh_audio->wf->nBlockAlign - DK3_ADPCM_PREAMBLE_SIZE) * 8 / 3; | |
5458 | 77 sh_audio->audio_in_minsize= |
5408 | 78 sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign; |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
79 return 1; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
80 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
81 |
5408 | 82 static int init(sh_audio_t *sh_audio) |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
83 { |
5408 | 84 sh_audio->channels = sh_audio->wf->nChannels; |
85 sh_audio->samplerate = sh_audio->wf->nSamplesPerSec; | |
86 sh_audio->i_bps = | |
87 (sh_audio->ds->ss_mul * sh_audio->samplerate) / sh_audio->ds->ss_div; | |
13427
9d0b052c4f74
setting samplesize to 2 in decoders where neccessary.
reimar
parents:
7191
diff
changeset
|
88 sh_audio->samplesize=2; |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
89 return 1; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
90 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
91 |
5408 | 92 static void uninit(sh_audio_t *sh_audio) |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
93 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
94 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
95 |
5481 | 96 static int control(sh_audio_t *sh_audio,int cmd,void* arg, ...) |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
97 { |
5481 | 98 if(cmd==ADCTRL_SKIP_FRAME){ |
99 demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul); | |
100 return CONTROL_TRUE; | |
101 } | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
102 return CONTROL_UNKNOWN; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
103 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
104 |
5408 | 105 #define DK3_GET_NEXT_NIBBLE() \ |
106 if (decode_top_nibble_next) \ | |
107 { \ | |
108 nibble = (last_byte >> 4) & 0x0F; \ | |
109 decode_top_nibble_next = 0; \ | |
110 } \ | |
111 else \ | |
112 { \ | |
113 last_byte = input[in_ptr++]; \ | |
114 nibble = last_byte & 0x0F; \ | |
115 decode_top_nibble_next = 1; \ | |
116 } | |
117 | |
118 // note: This decoder assumes the format 0x62 data always comes in | |
119 // stereo flavor | |
120 static int dk3_adpcm_decode_block(unsigned short *output, unsigned char *input, | |
121 int block_size) | |
122 { | |
123 int sum_pred; | |
124 int diff_pred; | |
125 int sum_index; | |
126 int diff_index; | |
127 int diff_channel; | |
128 int in_ptr = 0x10; | |
129 int out_ptr = 0; | |
130 | |
131 unsigned char last_byte = 0; | |
132 unsigned char nibble; | |
133 int decode_top_nibble_next = 0; | |
134 | |
135 // ADPCM work variables | |
136 int sign; | |
137 int delta; | |
138 int step; | |
139 int diff; | |
140 | |
141 sum_pred = LE_16(&input[10]); | |
142 diff_pred = LE_16(&input[12]); | |
143 SE_16BIT(sum_pred); | |
144 SE_16BIT(diff_pred); | |
145 diff_channel = diff_pred; | |
146 sum_index = input[14]; | |
147 diff_index = input[15]; | |
148 | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
149 while (in_ptr < block_size - !decode_top_nibble_next) |
5408 | 150 // while (in_ptr < 2048) |
151 { | |
152 // process the first predictor of the sum channel | |
153 DK3_GET_NEXT_NIBBLE(); | |
154 | |
155 step = adpcm_step[sum_index]; | |
156 | |
157 sign = nibble & 8; | |
158 delta = nibble & 7; | |
159 | |
160 diff = step >> 3; | |
161 if (delta & 4) diff += step; | |
162 if (delta & 2) diff += step >> 1; | |
163 if (delta & 1) diff += step >> 2; | |
164 | |
165 if (sign) | |
166 sum_pred -= diff; | |
167 else | |
168 sum_pred += diff; | |
169 | |
170 CLAMP_S16(sum_pred); | |
171 | |
172 sum_index += adpcm_index[nibble]; | |
173 CLAMP_0_TO_88(sum_index); | |
174 | |
175 // process the diff channel predictor | |
176 DK3_GET_NEXT_NIBBLE(); | |
177 | |
178 step = adpcm_step[diff_index]; | |
179 | |
180 sign = nibble & 8; | |
181 delta = nibble & 7; | |
182 | |
183 diff = step >> 3; | |
184 if (delta & 4) diff += step; | |
185 if (delta & 2) diff += step >> 1; | |
186 if (delta & 1) diff += step >> 2; | |
187 | |
188 if (sign) | |
189 diff_pred -= diff; | |
190 else | |
191 diff_pred += diff; | |
192 | |
193 CLAMP_S16(diff_pred); | |
194 | |
195 diff_index += adpcm_index[nibble]; | |
196 CLAMP_0_TO_88(diff_index); | |
197 | |
198 // output the first pair of stereo PCM samples | |
199 diff_channel = (diff_channel + diff_pred) / 2; | |
200 output[out_ptr++] = sum_pred + diff_channel; | |
201 output[out_ptr++] = sum_pred - diff_channel; | |
202 | |
203 // process the second predictor of the sum channel | |
204 DK3_GET_NEXT_NIBBLE(); | |
205 | |
206 step = adpcm_step[sum_index]; | |
207 | |
208 sign = nibble & 8; | |
209 delta = nibble & 7; | |
210 | |
211 diff = step >> 3; | |
212 if (delta & 4) diff += step; | |
213 if (delta & 2) diff += step >> 1; | |
214 if (delta & 1) diff += step >> 2; | |
215 | |
216 if (sign) | |
217 sum_pred -= diff; | |
218 else | |
219 sum_pred += diff; | |
220 | |
221 CLAMP_S16(sum_pred); | |
222 | |
223 sum_index += adpcm_index[nibble]; | |
224 CLAMP_0_TO_88(sum_index); | |
225 | |
226 // output the second pair of stereo PCM samples | |
227 output[out_ptr++] = sum_pred + diff_channel; | |
228 output[out_ptr++] = sum_pred - diff_channel; | |
229 } | |
230 | |
231 return out_ptr; | |
232 } | |
233 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
234 static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen) |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
235 { |
5408 | 236 if (demux_read_data(sh_audio->ds, sh_audio->a_in_buffer, |
237 sh_audio->ds->ss_mul) != | |
238 sh_audio->ds->ss_mul) | |
239 return -1; /* EOF */ | |
240 | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
241 if (maxlen < 2 * 4 * sh_audio->wf->nBlockAlign * 2 / 3) { |
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
242 mp_msg(MSGT_DECAUDIO, MSGL_V, "dk3adpcm: maxlen too small in decode_audio\n"); |
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
243 return -1; |
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
244 } |
5408 | 245 return 2 * dk3_adpcm_decode_block( |
246 (unsigned short*)buf, sh_audio->a_in_buffer, | |
16965
d8755974657a
attempt to fix missing and/or broken boundary checks
reimar
parents:
13427
diff
changeset
|
247 sh_audio->ds->ss_mul); |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
248 } |