Mercurial > libavcodec.hg
comparison ws-snd1.c @ 2585:1ef8fab234c8 libavcodec
Westwood SND1 decoder, courtesy of Kostya
author | melanson |
---|---|
date | Mon, 28 Mar 2005 18:05:25 +0000 |
parents | |
children | ef2149182f1c |
comparison
equal
deleted
inserted
replaced
2584:c07be5590462 | 2585:1ef8fab234c8 |
---|---|
1 /* | |
2 * Westwood SNDx codecs | |
3 * Copyright (c) 2005 Konstantin Shishkov | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avcodec.h" | |
20 | |
21 /** | |
22 * @file ws-snd.c | |
23 * Westwood SNDx codecs. | |
24 * | |
25 * Reference documents about VQA format and its audio codecs | |
26 * can be found here: | |
27 * http://www.multimedia.cx | |
28 */ | |
29 | |
30 typedef struct { | |
31 } WSSNDContext; | |
32 | |
33 static const char ws_adpcm_2bit[] = { -2, -1, 0, 1}; | |
34 static const char ws_adpcm_4bit[] = { | |
35 -9, -8, -6, -5, -4, -3, -2, -1, | |
36 0, 1, 2, 3, 4, 5, 6, 8 }; | |
37 | |
38 #define CLIP8(a) if(a>127)a=127;if(a<-128)a=-128; | |
39 | |
40 static int ws_snd_decode_init(AVCodecContext * avctx) | |
41 { | |
42 // WSSNDContext *c = avctx->priv_data; | |
43 | |
44 return 0; | |
45 } | |
46 | |
47 static int ws_snd_decode_frame(AVCodecContext *avctx, | |
48 void *data, int *data_size, | |
49 uint8_t *buf, int buf_size) | |
50 { | |
51 // WSSNDContext *c = avctx->priv_data; | |
52 | |
53 int in_size, out_size; | |
54 int sample = 0; | |
55 int i; | |
56 short *samples = data; | |
57 | |
58 if (!buf_size) | |
59 return 0; | |
60 | |
61 out_size = LE_16(&buf[0]); | |
62 *data_size = out_size * 2; | |
63 in_size = LE_16(&buf[2]); | |
64 buf += 4; | |
65 | |
66 if (in_size == out_size) { | |
67 for (i = 0; i < out_size; i++) | |
68 *samples++ = (*buf++ - 0x80) << 8; | |
69 return buf_size; | |
70 } | |
71 | |
72 while (out_size > 0) { | |
73 int code; | |
74 uint8_t count; | |
75 code = (*buf) >> 6; | |
76 count = (*buf) & 0x3F; | |
77 buf++; | |
78 switch(code) { | |
79 case 0: /* ADPCM 2-bit */ | |
80 for (count++; count > 0; count--) { | |
81 code = *buf++; | |
82 sample += ws_adpcm_2bit[code & 0x3]; | |
83 CLIP8(sample); | |
84 *samples++ = sample << 8; | |
85 sample += ws_adpcm_2bit[(code >> 2) & 0x3]; | |
86 CLIP8(sample); | |
87 *samples++ = sample << 8; | |
88 sample += ws_adpcm_2bit[(code >> 4) & 0x3]; | |
89 CLIP8(sample); | |
90 *samples++ = sample << 8; | |
91 sample += ws_adpcm_2bit[(code >> 6) & 0x3]; | |
92 CLIP8(sample); | |
93 *samples++ = sample << 8; | |
94 out_size -= 4; | |
95 } | |
96 break; | |
97 case 1: /* ADPCM 4-bit */ | |
98 for (count++; count > 0; count--) { | |
99 code = *buf++; | |
100 sample += ws_adpcm_4bit[code & 0xF]; | |
101 CLIP8(sample); | |
102 *samples++ = sample << 8; | |
103 sample += ws_adpcm_4bit[code >> 4]; | |
104 CLIP8(sample); | |
105 *samples++ = sample << 8; | |
106 out_size -= 2; | |
107 } | |
108 break; | |
109 case 2: /* no compression */ | |
110 if (count & 0x20) { /* big delta */ | |
111 char t; | |
112 t = count; | |
113 t <<= 3; | |
114 sample += t >> 3; | |
115 *samples++ = sample << 8; | |
116 out_size--; | |
117 } else { /* copy */ | |
118 for (count++; count > 0; count--) { | |
119 *samples++ = (*buf++ - 0x80) << 8; | |
120 out_size--; | |
121 } | |
122 sample = buf[-1] - 0x80; | |
123 } | |
124 break; | |
125 default: /* run */ | |
126 for(count++; count > 0; count--) { | |
127 *samples++ = sample << 8; | |
128 out_size--; | |
129 } | |
130 } | |
131 } | |
132 | |
133 return buf_size; | |
134 } | |
135 | |
136 AVCodec ws_snd1_decoder = { | |
137 "ws_snd1", | |
138 CODEC_TYPE_AUDIO, | |
139 CODEC_ID_WESTWOOD_SND1, | |
140 sizeof(WSSNDContext), | |
141 ws_snd_decode_init, | |
142 NULL, | |
143 NULL, | |
144 ws_snd_decode_frame, | |
145 }; |