Mercurial > mplayer.hg
annotate libmpcodecs/ad_msadpcm.c @ 5699:1dde9686d33b
Good evening ladies and gentleman and welcome to the latest
installment of the ongoing show "Reworking the docs for fun and
profit". Your host Diego will be assisted by Nilmoni in presenting
you:
- spellchecking in all its glory
- a grammar to the envy of all native speakers
- answers now hopefully so clear that their respective questions shall
never be asked again
Somebody from the public raises his voice: "What about HTML errors?"
The host is quick to answer: "Yes, there have been corrections." From
the back of the auditory comes a subdued question: "And the FONT
tags..?" The room falls silent. There is no answer and the host
twitches. Finally the words "They have not been touched." escape from
his mouth, barely audible. A murmur erupts but the jury nods and
calms the crowd "Time to get back to serious hacking.". The host
leaves the stage under polite applause and everybody scuttles off for
their notebooks...
author | arpi |
---|---|
date | Fri, 19 Apr 2002 07:30:49 +0000 |
parents | 8ae2bf330ad5 |
children | 7745d73a5f20 |
rev | line source |
---|---|
5408 | 1 /* |
2 MS ADPCM Decoder for MPlayer | |
3 by Mike Melanson | |
4 | |
5 This file is responsible for decoding Microsoft ADPCM data. | |
6 Details about the data format can be found here: | |
7 http://www.pcisys.net/~melanson/codecs/ | |
8 */ | |
9 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
10 #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
|
11 #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
|
12 #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
|
13 |
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 "config.h" |
5408 | 15 #include "bswap.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
|
16 #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
|
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 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
|
19 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
20 "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
|
21 "msadpcm", |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
22 AFM_MSADPCM, |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
23 "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
|
24 "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
|
25 "" |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
26 }; |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
27 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
28 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
|
29 |
5408 | 30 static int ms_adapt_table[] = |
31 { | |
32 230, 230, 230, 230, 307, 409, 512, 614, | |
33 768, 614, 512, 409, 307, 230, 230, 230 | |
34 }; | |
35 | |
36 static int ms_adapt_coeff1[] = | |
37 { | |
38 256, 512, 0, 192, 240, 460, 392 | |
39 }; | |
40 | |
41 static int ms_adapt_coeff2[] = | |
42 { | |
43 0, -256, 0, 64, 0, -208, -232 | |
44 }; | |
45 | |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
46 #define MS_ADPCM_PREAMBLE_SIZE 7 |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
47 |
5408 | 48 #define LE_16(x) (le2me_16(*(unsigned short *)(x))) |
49 #define LE_32(x) (le2me_32(*(unsigned int *)(x))) | |
50 | |
51 // useful macros | |
52 // clamp a number between 0 and 88 | |
53 #define CLAMP_0_TO_88(x) if (x < 0) x = 0; else if (x > 88) x = 88; | |
54 // clamp a number within a signed 16-bit range | |
55 #define CLAMP_S16(x) if (x < -32768) x = -32768; \ | |
56 else if (x > 32767) x = 32767; | |
57 // clamp a number above 16 | |
58 #define CLAMP_ABOVE_16(x) if (x < 16) x = 16; | |
59 // sign extend a 16-bit value | |
60 #define SE_16BIT(x) if (x & 0x8000) x -= 0x10000; | |
61 // sign extend a 4-bit value | |
62 #define SE_4BIT(x) if (x & 0x8) x -= 0x10; | |
63 | |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
64 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
|
65 { |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
66 sh_audio->audio_out_minsize = sh_audio->wf->nBlockAlign * 4; |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
67 sh_audio->ds->ss_div = |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
68 (sh_audio->wf->nBlockAlign - MS_ADPCM_PREAMBLE_SIZE) * 2; |
5458 | 69 sh_audio->audio_in_minsize = |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
70 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
|
71 return 1; |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
72 } |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
73 |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
74 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
|
75 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
76 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
|
77 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
|
78 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
|
79 (sh_audio->channels*sh_audio->samplerate) / sh_audio->ds->ss_div; |
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
80 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
81 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
|
82 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
83 |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
84 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
|
85 { |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
86 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
87 |
5481 | 88 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
|
89 { |
5481 | 90 if(cmd==ADCTRL_SKIP_FRAME){ |
91 demux_read_data(sh_audio->ds, sh_audio->a_in_buffer,sh_audio->ds->ss_mul); | |
92 return CONTROL_TRUE; | |
93 } | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
94 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
|
95 } |
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
96 |
5408 | 97 static int ms_adpcm_decode_block(unsigned short *output, unsigned char *input, |
98 int channels, int block_size) | |
99 { | |
100 int current_channel = 0; | |
101 int idelta[2]; | |
102 int sample1[2]; | |
103 int sample2[2]; | |
104 int coeff1[2]; | |
105 int coeff2[2]; | |
106 int stream_ptr = 0; | |
107 int out_ptr = 0; | |
108 int upper_nibble = 1; | |
109 int nibble; | |
110 int snibble; // signed nibble | |
111 int predictor; | |
112 | |
113 // fetch the header information, in stereo if both channels are present | |
114 if (input[stream_ptr] > 6) | |
115 mp_msg(MSGT_DECAUDIO, MSGL_WARN, | |
116 "MS ADPCM: coefficient (%d) out of range (should be [0..6])\n", | |
117 input[stream_ptr]); | |
118 coeff1[0] = ms_adapt_coeff1[input[stream_ptr]]; | |
119 coeff2[0] = ms_adapt_coeff2[input[stream_ptr]]; | |
120 stream_ptr++; | |
121 if (channels == 2) | |
122 { | |
123 if (input[stream_ptr] > 6) | |
124 mp_msg(MSGT_DECAUDIO, MSGL_WARN, | |
125 "MS ADPCM: coefficient (%d) out of range (should be [0..6])\n", | |
126 input[stream_ptr]); | |
127 coeff1[1] = ms_adapt_coeff1[input[stream_ptr]]; | |
128 coeff2[1] = ms_adapt_coeff2[input[stream_ptr]]; | |
129 stream_ptr++; | |
130 } | |
131 | |
132 idelta[0] = LE_16(&input[stream_ptr]); | |
133 stream_ptr += 2; | |
134 SE_16BIT(idelta[0]); | |
135 if (channels == 2) | |
136 { | |
137 idelta[1] = LE_16(&input[stream_ptr]); | |
138 stream_ptr += 2; | |
139 SE_16BIT(idelta[1]); | |
140 } | |
141 | |
142 sample1[0] = LE_16(&input[stream_ptr]); | |
143 stream_ptr += 2; | |
144 SE_16BIT(sample1[0]); | |
145 if (channels == 2) | |
146 { | |
147 sample1[1] = LE_16(&input[stream_ptr]); | |
148 stream_ptr += 2; | |
149 SE_16BIT(sample1[1]); | |
150 } | |
151 | |
152 sample2[0] = LE_16(&input[stream_ptr]); | |
153 stream_ptr += 2; | |
154 SE_16BIT(sample2[0]); | |
155 if (channels == 2) | |
156 { | |
157 sample2[1] = LE_16(&input[stream_ptr]); | |
158 stream_ptr += 2; | |
159 SE_16BIT(sample2[1]); | |
160 } | |
161 | |
162 while (stream_ptr < block_size) | |
163 { | |
164 // get the next nibble | |
165 if (upper_nibble) | |
166 nibble = snibble = input[stream_ptr] >> 4; | |
167 else | |
168 nibble = snibble = input[stream_ptr++] & 0x0F; | |
169 upper_nibble ^= 1; | |
170 SE_4BIT(snibble); | |
171 | |
172 predictor = ( | |
173 ((sample1[current_channel] * coeff1[current_channel]) + | |
174 (sample2[current_channel] * coeff2[current_channel])) / 256) + | |
175 (snibble * idelta[current_channel]); | |
176 CLAMP_S16(predictor); | |
177 sample2[current_channel] = sample1[current_channel]; | |
178 sample1[current_channel] = predictor; | |
179 output[out_ptr++] = predictor; | |
180 | |
181 // compute the next adaptive scale factor (a.k.a. the variable idelta) | |
182 idelta[current_channel] = | |
183 (ms_adapt_table[nibble] * idelta[current_channel]) / 256; | |
184 CLAMP_ABOVE_16(idelta[current_channel]); | |
185 | |
186 // toggle the channel | |
187 current_channel ^= channels - 1; | |
188 } | |
189 | |
190 return (block_size - (MS_ADPCM_PREAMBLE_SIZE * channels)) * 2; | |
191 } | |
192 | |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
193 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
|
194 { |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
195 if (demux_read_data(sh_audio->ds, sh_audio->a_in_buffer, |
5408 | 196 sh_audio->ds->ss_mul) != |
197 sh_audio->ds->ss_mul) | |
198 return -1; /* EOF */ | |
5350
d59e27f2f5be
fixed so the decoder cooperates better with the rest of the system
melanson
parents:
5340
diff
changeset
|
199 |
5340
0f12fb7c1c5d
imported from MPlayerXP, dlopen() hack removed, some bugs fixed, interface functions changed to static, info->author field added
arpi
parents:
diff
changeset
|
200 return 2 * ms_adpcm_decode_block( |
5408 | 201 (unsigned short*)buf, sh_audio->a_in_buffer, |
202 sh_audio->wf->nChannels, 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
|
203 } |