Mercurial > mplayer.hg
annotate libmpcodecs/ad_msadpcm.c @ 34697:ac6b38cd0d45
Rename sub window video window.
It was a bad idea to name the video window "sub window" at the time
the GUI was written. The term "sub window" does make sense from the
programmer's point of view, but it doesn't make any sense at all from
the user's point of view, because the sub window simply is the window
where the video will be displayed.
Moreover, since the term "sub" is generally short for "subtitles",
the renaming makes the code much easier to understand.
author | ib |
---|---|
date | Sat, 03 Mar 2012 16:45:15 +0000 |
parents | a93891202051 |
children |
rev | line source |
---|---|
5408 | 1 /* |
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
2 * MS ADPCM decoder |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
3 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
4 * This file is responsible for decoding Microsoft ADPCM data. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
5 * Details about the data format can be found here: |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
6 * http://www.pcisys.net/~melanson/codecs/ |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
7 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
8 * Copyright (c) 2002 Mike Melanson |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
9 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
10 * This file is part of MPlayer. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
11 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
12 * MPlayer is free software; you can redistribute it and/or modify |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
13 * it under the terms of the GNU General Public License as published by |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
14 * the Free Software Foundation; either version 2 of the License, or |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
15 * (at your option) any later version. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
16 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
17 * MPlayer is distributed in the hope that it will be useful, |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
20 * GNU General Public License for more details. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
21 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
22 * You should have received a copy of the GNU General Public License along |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
23 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
29263
diff
changeset
|
25 */ |
5408 | 26 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
27 #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
|
28 #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
|
29 #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
|
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 #include "config.h" |
34174
a93891202051
Add missing mp_msg.h #includes, remove some unnecessary ones.
diego
parents:
30504
diff
changeset
|
32 #include "mp_msg.h" |
27224
f9b5d028f097
Copy macro simplification from imaadpcm to msadpcm
reimar
parents:
27223
diff
changeset
|
33 #include "libavutil/common.h" |
27225
46bcd3f1b123
Simplify ad_msadpmc.c: Use AV_RL16, merge sign extension into LE_16 read and
reimar
parents:
27224
diff
changeset
|
34 #include "libavutil/intreadwrite.h" |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
35 #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
|
36 #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
|
37 |
30504
cc27da5d7286
Mark all ad_info_t/vd_info_t structure declarations as const.
diego
parents:
30421
diff
changeset
|
38 static const ad_info_t info = |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
39 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
40 "MS ADPCM audio decoder", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
41 "msadpcm", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
42 "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
|
43 "Mike Melanson", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
44 "" |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
45 }; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
46 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
47 LIBAD_EXTERN(msadpcm) |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
48 |
27222 | 49 static const int ms_adapt_table[] = |
5408 | 50 { |
51 230, 230, 230, 230, 307, 409, 512, 614, | |
52 768, 614, 512, 409, 307, 230, 230, 230 | |
53 }; | |
54 | |
27237
6a283385441b
100l, fix MS ADPCM decoding for e.g. http://samples.mplayerhq.hu/mov/qtaudio/surge-2-16-L-ms02.mov
reimar
parents:
27228
diff
changeset
|
55 static const uint8_t ms_adapt_coeff1[] = |
5408 | 56 { |
27226 | 57 64, 128, 0, 48, 60, 115, 98 |
5408 | 58 }; |
59 | |
27226 | 60 static const int8_t ms_adapt_coeff2[] = |
5408 | 61 { |
27226 | 62 0, -64, 0, 16, 0, -52, -58 |
5408 | 63 }; |
64 | |
6609 | 65 #define MS_ADPCM_PREAMBLE_SIZE 6 |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
66 |
27225
46bcd3f1b123
Simplify ad_msadpmc.c: Use AV_RL16, merge sign extension into LE_16 read and
reimar
parents:
27224
diff
changeset
|
67 #define LE_16(x) ((int16_t)AV_RL16(x)) |
5408 | 68 |
69 // clamp a number between 0 and 88 | |
27224
f9b5d028f097
Copy macro simplification from imaadpcm to msadpcm
reimar
parents:
27223
diff
changeset
|
70 #define CLAMP_0_TO_88(x) x = av_clip(x, 0, 88); |
5408 | 71 // clamp a number within a signed 16-bit range |
27224
f9b5d028f097
Copy macro simplification from imaadpcm to msadpcm
reimar
parents:
27223
diff
changeset
|
72 #define CLAMP_S16(x) x = av_clip_int16(x); |
5408 | 73 // clamp a number above 16 |
74 #define CLAMP_ABOVE_16(x) if (x < 16) x = 16; | |
75 // sign extend a 4-bit value | |
76 #define SE_4BIT(x) if (x & 0x8) x -= 0x10; | |
77 | |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
78 static int preinit(sh_audio_t *sh_audio) |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
79 { |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
80 sh_audio->audio_out_minsize = sh_audio->wf->nBlockAlign * 4; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
27238
diff
changeset
|
81 sh_audio->ds->ss_div = |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
82 (sh_audio->wf->nBlockAlign - MS_ADPCM_PREAMBLE_SIZE) * 2; |
5458 | 83 sh_audio->audio_in_minsize = |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
84 sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign; |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
85 return 1; |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
86 } |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
87 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
88 static int init(sh_audio_t *sh_audio) |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
89 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
90 sh_audio->channels=sh_audio->wf->nChannels; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
91 sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
92 sh_audio->i_bps = sh_audio->wf->nBlockAlign * |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
93 (sh_audio->channels*sh_audio->samplerate) / sh_audio->ds->ss_div; |
13427
9d0b052c4f74
setting samplesize to 2 in decoders where neccessary.
reimar
parents:
7893
diff
changeset
|
94 sh_audio->samplesize=2; |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
95 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
96 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
|
97 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
98 |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
99 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
|
100 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
101 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
102 |
5481 | 103 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
|
104 { |
5481 | 105 if(cmd==ADCTRL_SKIP_FRAME){ |
106 demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul); | |
107 return CONTROL_TRUE; | |
108 } | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
109 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
|
110 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
111 |
27238 | 112 static inline int check_coeff(uint8_t c) { |
113 if (c > 6) { | |
114 mp_msg(MSGT_DECAUDIO, MSGL_WARN, | |
115 "MS ADPCM: coefficient (%d) out of range (should be [0..6])\n", | |
116 c); | |
117 c = 6; | |
118 } | |
119 return c; | |
120 } | |
121 | |
5408 | 122 static int ms_adpcm_decode_block(unsigned short *output, unsigned char *input, |
123 int channels, int block_size) | |
124 { | |
125 int current_channel = 0; | |
27238 | 126 int coeff_idx; |
5408 | 127 int idelta[2]; |
128 int sample1[2]; | |
129 int sample2[2]; | |
130 int coeff1[2]; | |
131 int coeff2[2]; | |
132 int stream_ptr = 0; | |
133 int out_ptr = 0; | |
134 int upper_nibble = 1; | |
135 int nibble; | |
136 int snibble; // signed nibble | |
137 int predictor; | |
138 | |
27228 | 139 if (channels != 1) channels = 2; |
140 if (block_size < 7 * channels) | |
141 return -1; | |
142 | |
5408 | 143 // fetch the header information, in stereo if both channels are present |
27238 | 144 coeff_idx = check_coeff(input[stream_ptr]); |
145 coeff1[0] = ms_adapt_coeff1[coeff_idx]; | |
146 coeff2[0] = ms_adapt_coeff2[coeff_idx]; | |
5408 | 147 stream_ptr++; |
148 if (channels == 2) | |
149 { | |
27238 | 150 coeff_idx = check_coeff(input[stream_ptr]); |
151 coeff1[1] = ms_adapt_coeff1[coeff_idx]; | |
152 coeff2[1] = ms_adapt_coeff2[coeff_idx]; | |
5408 | 153 stream_ptr++; |
154 } | |
155 | |
156 idelta[0] = LE_16(&input[stream_ptr]); | |
157 stream_ptr += 2; | |
158 if (channels == 2) | |
159 { | |
160 idelta[1] = LE_16(&input[stream_ptr]); | |
161 stream_ptr += 2; | |
162 } | |
163 | |
164 sample1[0] = LE_16(&input[stream_ptr]); | |
165 stream_ptr += 2; | |
166 if (channels == 2) | |
167 { | |
168 sample1[1] = LE_16(&input[stream_ptr]); | |
169 stream_ptr += 2; | |
170 } | |
171 | |
172 sample2[0] = LE_16(&input[stream_ptr]); | |
173 stream_ptr += 2; | |
174 if (channels == 2) | |
175 { | |
176 sample2[1] = LE_16(&input[stream_ptr]); | |
177 stream_ptr += 2; | |
178 } | |
179 | |
6609 | 180 if (channels == 1) |
181 { | |
182 output[out_ptr++] = sample2[0]; | |
183 output[out_ptr++] = sample1[0]; | |
184 } else { | |
185 output[out_ptr++] = sample2[0]; | |
186 output[out_ptr++] = sample2[1]; | |
187 output[out_ptr++] = sample1[0]; | |
188 output[out_ptr++] = sample1[1]; | |
189 } | |
190 | |
5408 | 191 while (stream_ptr < block_size) |
192 { | |
193 // get the next nibble | |
194 if (upper_nibble) | |
195 nibble = snibble = input[stream_ptr] >> 4; | |
196 else | |
197 nibble = snibble = input[stream_ptr++] & 0x0F; | |
198 upper_nibble ^= 1; | |
199 SE_4BIT(snibble); | |
200 | |
27227 | 201 // should this really be a division and not a shift? |
202 // coefficients were originally scaled by for, which might have | |
203 // been an optimization for 8-bit CPUs _if_ a shift is correct | |
5408 | 204 predictor = ( |
205 ((sample1[current_channel] * coeff1[current_channel]) + | |
27226 | 206 (sample2[current_channel] * coeff2[current_channel])) / 64) + |
5408 | 207 (snibble * idelta[current_channel]); |
208 CLAMP_S16(predictor); | |
209 sample2[current_channel] = sample1[current_channel]; | |
210 sample1[current_channel] = predictor; | |
211 output[out_ptr++] = predictor; | |
212 | |
213 // compute the next adaptive scale factor (a.k.a. the variable idelta) | |
214 idelta[current_channel] = | |
215 (ms_adapt_table[nibble] * idelta[current_channel]) / 256; | |
216 CLAMP_ABOVE_16(idelta[current_channel]); | |
217 | |
218 // toggle the channel | |
219 current_channel ^= channels - 1; | |
220 } | |
221 | |
222 return (block_size - (MS_ADPCM_PREAMBLE_SIZE * channels)) * 2; | |
223 } | |
224 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
225 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
|
226 { |
27228 | 227 int res; |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
228 if (demux_read_data(sh_audio->ds, sh_audio->a_in_buffer, |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
27238
diff
changeset
|
229 sh_audio->ds->ss_mul) != |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
27238
diff
changeset
|
230 sh_audio->ds->ss_mul) |
5408 | 231 return -1; /* EOF */ |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
232 |
27228 | 233 res = ms_adpcm_decode_block( |
5408 | 234 (unsigned short*)buf, sh_audio->a_in_buffer, |
235 sh_audio->wf->nChannels, sh_audio->wf->nBlockAlign); | |
27228 | 236 return res < 0 ? res : 2 * res; |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
237 } |