Mercurial > mplayer.hg
comparison adpcm.c @ 3756:734d0c0a8ab0
Initial support for unified ADPCM decoder
author | melanson |
---|---|
date | Wed, 26 Dec 2001 06:13:17 +0000 |
parents | |
children | 81d84039dd17 |
comparison
equal
deleted
inserted
replaced
3755:b805040d6645 | 3756:734d0c0a8ab0 |
---|---|
1 /* | |
2 Unified ADPCM Decoder for MPlayer | |
3 | |
4 (C) 2001 Mike Melanson | |
5 */ | |
6 | |
7 #include "config.h" | |
8 #include "bswap.h" | |
9 #include "adpcm.h" | |
10 | |
11 #define BE_16(x) (be2me_16(*(unsigned short *)(x))) | |
12 #define BE_32(x) (be2me_32(*(unsigned int *)(x))) | |
13 #define LE_16(x) (le2me_16(*(unsigned short *)(x))) | |
14 #define LE_32(x) (le2me_32(*(unsigned int *)(x))) | |
15 | |
16 // clamp a number between 0 and 88 | |
17 #define CLAMP_0_TO_88(x) if (x < 0) x = 0; else if (x > 88) x = 88; | |
18 // clamp a number within a signed 16-bit range | |
19 #define CLAMP_S16(x) if (x < -32768) x = -32768; \ | |
20 else if (x > 32767) x = 32767; | |
21 // sign extend a 16-bit value | |
22 #define SE_16BIT(x) if (x & 0x8000) x -= 0x10000; | |
23 | |
24 void ima_dvi_decode_nibbles(unsigned short *output, int channels, | |
25 int predictor_l, int index_l, | |
26 int predictor_r, int index_r) | |
27 { | |
28 int step[2]; | |
29 int predictor[2]; | |
30 int index[2]; | |
31 int diff; | |
32 int i; | |
33 int sign; | |
34 int delta; | |
35 int channel_number = 0; | |
36 | |
37 step[0] = adpcm_step[index_l]; | |
38 step[1] = adpcm_step[index_r]; | |
39 predictor[0] = predictor_l; | |
40 predictor[1] = predictor_r; | |
41 index[0] = index_l; | |
42 index[1] = index_r; | |
43 | |
44 for (i = 0; i < IMA_ADPCM_SAMPLES_PER_BLOCK * channels; i++) | |
45 { | |
46 delta = output[i]; | |
47 | |
48 index[channel_number] += adpcm_index[delta]; | |
49 CLAMP_0_TO_88(index[channel_number]); | |
50 | |
51 sign = delta & 8; | |
52 delta = delta & 7; | |
53 | |
54 diff = step[channel_number] >> 3; | |
55 if (delta & 4) diff += step[channel_number]; | |
56 if (delta & 2) diff += step[channel_number] >> 1; | |
57 if (delta & 1) diff += step[channel_number] >> 2; | |
58 | |
59 if (sign) | |
60 predictor[channel_number] -= diff; | |
61 else | |
62 predictor[channel_number] += diff; | |
63 | |
64 CLAMP_S16(predictor[channel_number]); | |
65 output[i] = predictor[channel_number]; | |
66 step[channel_number] = adpcm_step[index[channel_number]]; | |
67 | |
68 // toggle channel | |
69 channel_number ^= channels - 1; | |
70 } | |
71 } | |
72 | |
73 int ima_adpcm_decode_block(unsigned short *output, unsigned char *input, | |
74 int channels) | |
75 { | |
76 int initial_predictor_l = 0; | |
77 int initial_predictor_r = 0; | |
78 int initial_index_l = 0; | |
79 int initial_index_r = 0; | |
80 int stream_ptr = 0; | |
81 int i; | |
82 | |
83 initial_predictor_l = BE_16(&input[stream_ptr]); | |
84 stream_ptr += 2; | |
85 initial_index_l = initial_predictor_l; | |
86 | |
87 // mask, sign-extend, and clamp the predictor portion | |
88 initial_predictor_l &= 0xFF80; | |
89 SE_16BIT(initial_predictor_l); | |
90 CLAMP_S16(initial_predictor_l); | |
91 | |
92 // mask and clamp the index portion | |
93 initial_index_l &= 0x7F; | |
94 CLAMP_0_TO_88(initial_index_l); | |
95 | |
96 // handle stereo | |
97 if (channels > 1) | |
98 { | |
99 initial_predictor_r = BE_16(&input[stream_ptr]); | |
100 stream_ptr += 2; | |
101 initial_index_r = initial_predictor_r; | |
102 | |
103 // mask, sign-extend, and clamp the predictor portion | |
104 initial_predictor_r &= 0xFF80; | |
105 SE_16BIT(initial_predictor_r); | |
106 CLAMP_S16(initial_predictor_r); | |
107 | |
108 // mask and clamp the index portion | |
109 initial_index_r &= 0x7F; | |
110 CLAMP_0_TO_88(initial_index_r); | |
111 } | |
112 | |
113 // break apart all of the nibbles in the block | |
114 if (channels == 1) | |
115 for (i = 0; i < IMA_ADPCM_SAMPLES_PER_BLOCK / 2; i++) | |
116 { | |
117 output[i * 2 + 0] = input[stream_ptr] & 0x0F; | |
118 output[i * 2 + 1] = input[stream_ptr] >> 4; | |
119 stream_ptr++; | |
120 } | |
121 else | |
122 for (i = 0; i < IMA_ADPCM_SAMPLES_PER_BLOCK / 2 * 2; i++) | |
123 { | |
124 output[i * 4 + 0] = input[stream_ptr] & 0x0F; | |
125 output[i * 4 + 1] = input[stream_ptr + 1] & 0x0F; | |
126 output[i * 4 + 2] = input[stream_ptr] >> 4; | |
127 output[i * 4 + 3] = input[stream_ptr + 1] >> 4; | |
128 stream_ptr++; | |
129 } | |
130 | |
131 ima_dvi_decode_nibbles(output, channels, | |
132 initial_predictor_l, initial_index_l, | |
133 initial_predictor_r, initial_index_r); | |
134 | |
135 return IMA_ADPCM_SAMPLES_PER_BLOCK * channels; | |
136 } |