14280
|
1 /********************************************************************
|
|
2 * *
|
|
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
|
|
4 * *
|
|
5 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
|
6 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
|
|
7 * ALL REDISTRIBUTION RIGHTS RESERVED. *
|
|
8 * *
|
|
9 ********************************************************************
|
|
10
|
|
11 function: residue backend 0, 1 and 2 implementation
|
|
12
|
|
13 ********************************************************************/
|
|
14
|
|
15 #include <stdlib.h>
|
|
16 #include <string.h>
|
|
17 #include <math.h>
|
|
18 #include "ogg.h"
|
|
19 #include "ivorbiscodec.h"
|
|
20 #include "codec_internal.h"
|
|
21 #include "registry.h"
|
|
22 #include "codebook.h"
|
|
23 #include "misc.h"
|
|
24 #include "os.h"
|
|
25
|
|
26 typedef struct {
|
|
27 vorbis_info_residue0 *info;
|
|
28 int map;
|
|
29
|
|
30 int parts;
|
|
31 int stages;
|
|
32 codebook *fullbooks;
|
|
33 codebook *phrasebook;
|
|
34 codebook ***partbooks;
|
|
35
|
|
36 int partvals;
|
|
37 int **decodemap;
|
|
38
|
|
39 } vorbis_look_residue0;
|
|
40
|
|
41 void res0_free_info(vorbis_info_residue *i){
|
|
42 vorbis_info_residue0 *info=(vorbis_info_residue0 *)i;
|
|
43 if(info){
|
|
44 memset(info,0,sizeof(*info));
|
|
45 _ogg_free(info);
|
|
46 }
|
|
47 }
|
|
48
|
|
49 void res0_free_look(vorbis_look_residue *i){
|
|
50 int j;
|
|
51 if(i){
|
|
52
|
|
53 vorbis_look_residue0 *look=(vorbis_look_residue0 *)i;
|
|
54
|
|
55 for(j=0;j<look->parts;j++)
|
|
56 if(look->partbooks[j])_ogg_free(look->partbooks[j]);
|
|
57 _ogg_free(look->partbooks);
|
|
58 for(j=0;j<look->partvals;j++)
|
|
59 _ogg_free(look->decodemap[j]);
|
|
60 _ogg_free(look->decodemap);
|
|
61
|
|
62 memset(look,0,sizeof(*look));
|
|
63 _ogg_free(look);
|
|
64 }
|
|
65 }
|
|
66
|
|
67 static int ilog(unsigned int v){
|
|
68 int ret=0;
|
|
69 while(v){
|
|
70 ret++;
|
|
71 v>>=1;
|
|
72 }
|
|
73 return(ret);
|
|
74 }
|
|
75
|
|
76 static int icount(unsigned int v){
|
|
77 int ret=0;
|
|
78 while(v){
|
|
79 ret+=v&1;
|
|
80 v>>=1;
|
|
81 }
|
|
82 return(ret);
|
|
83 }
|
|
84
|
|
85 /* vorbis_info is for range checking */
|
|
86 vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){
|
|
87 int j,acc=0;
|
|
88 vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info));
|
|
89 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
|
|
90
|
|
91 info->begin=oggpack_read(opb,24);
|
|
92 info->end=oggpack_read(opb,24);
|
|
93 info->grouping=oggpack_read(opb,24)+1;
|
|
94 info->partitions=oggpack_read(opb,6)+1;
|
|
95 info->groupbook=oggpack_read(opb,8);
|
|
96
|
|
97 for(j=0;j<info->partitions;j++){
|
|
98 int cascade=oggpack_read(opb,3);
|
|
99 if(oggpack_read(opb,1))
|
|
100 cascade|=(oggpack_read(opb,5)<<3);
|
|
101 info->secondstages[j]=cascade;
|
|
102
|
|
103 acc+=icount(cascade);
|
|
104 }
|
|
105 for(j=0;j<acc;j++)
|
|
106 info->booklist[j]=oggpack_read(opb,8);
|
|
107
|
|
108 if(info->groupbook>=ci->books)goto errout;
|
|
109 for(j=0;j<acc;j++)
|
|
110 if(info->booklist[j]>=ci->books)goto errout;
|
|
111
|
|
112 return(info);
|
|
113 errout:
|
|
114 res0_free_info(info);
|
|
115 return(NULL);
|
|
116 }
|
|
117
|
|
118 vorbis_look_residue *res0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm,
|
|
119 vorbis_info_residue *vr){
|
|
120 vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr;
|
|
121 vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look));
|
|
122 codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup;
|
|
123
|
|
124 int j,k,acc=0;
|
|
125 int dim;
|
|
126 int maxstage=0;
|
|
127 look->info=info;
|
|
128 look->map=vm->mapping;
|
|
129
|
|
130 look->parts=info->partitions;
|
|
131 look->fullbooks=ci->fullbooks;
|
|
132 look->phrasebook=ci->fullbooks+info->groupbook;
|
|
133 dim=look->phrasebook->dim;
|
|
134
|
|
135 look->partbooks=(codebook ***)_ogg_calloc(look->parts,sizeof(*look->partbooks));
|
|
136
|
|
137 for(j=0;j<look->parts;j++){
|
|
138 int stages=ilog(info->secondstages[j]);
|
|
139 if(stages){
|
|
140 if(stages>maxstage)maxstage=stages;
|
|
141 look->partbooks[j]=(codebook **)_ogg_calloc(stages,sizeof(*look->partbooks[j]));
|
|
142 for(k=0;k<stages;k++)
|
|
143 if(info->secondstages[j]&(1<<k)){
|
|
144 look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++];
|
|
145 #ifdef TRAIN_RES
|
|
146 look->training_data[k][j]=calloc(look->partbooks[j][k]->entries,
|
|
147 sizeof(***look->training_data));
|
|
148 #endif
|
|
149 }
|
|
150 }
|
|
151 }
|
|
152
|
|
153 look->partvals=look->parts;
|
|
154 for(j=1;j<dim;j++)look->partvals*=look->parts;
|
|
155 look->stages=maxstage;
|
|
156 look->decodemap=(int **)_ogg_malloc(look->partvals*sizeof(*look->decodemap));
|
|
157 for(j=0;j<look->partvals;j++){
|
|
158 long val=j;
|
|
159 long mult=look->partvals/look->parts;
|
|
160 look->decodemap[j]=(int *)_ogg_malloc(dim*sizeof(*look->decodemap[j]));
|
|
161 for(k=0;k<dim;k++){
|
|
162 long deco=val/mult;
|
|
163 val-=deco*mult;
|
|
164 mult/=look->parts;
|
|
165 look->decodemap[j][k]=deco;
|
|
166 }
|
|
167 }
|
|
168
|
|
169 return(look);
|
|
170 }
|
|
171
|
|
172
|
|
173 /* a truncated packet here just means 'stop working'; it's not an error */
|
|
174 static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl,
|
|
175 ogg_int32_t **in,int ch,
|
|
176 long (*decodepart)(codebook *, ogg_int32_t *,
|
|
177 oggpack_buffer *,int,int)){
|
|
178
|
|
179 long i,j,k,l,s;
|
|
180 vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
|
|
181 vorbis_info_residue0 *info=look->info;
|
|
182
|
|
183 /* move all this setup out later */
|
|
184 int samples_per_partition=info->grouping;
|
|
185 int partitions_per_word=look->phrasebook->dim;
|
|
186 int n=info->end-info->begin;
|
|
187
|
|
188 int partvals=n/samples_per_partition;
|
|
189 int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
|
|
190 int ***partword=(int ***)alloca(ch*sizeof(*partword));
|
|
191
|
|
192 for(j=0;j<ch;j++)
|
|
193 partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j]));
|
|
194
|
|
195 for(s=0;s<look->stages;s++){
|
|
196
|
|
197 /* each loop decodes on partition codeword containing
|
|
198 partitions_pre_word partitions */
|
|
199 for(i=0,l=0;i<partvals;l++){
|
|
200 if(s==0){
|
|
201 /* fetch the partition word for each channel */
|
|
202 for(j=0;j<ch;j++){
|
|
203 int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
|
|
204 if(temp==-1)goto eopbreak;
|
|
205 partword[j][l]=look->decodemap[temp];
|
|
206 if(partword[j][l]==NULL)goto errout;
|
|
207 }
|
|
208 }
|
|
209
|
|
210 /* now we decode residual values for the partitions */
|
|
211 for(k=0;k<partitions_per_word && i<partvals;k++,i++)
|
|
212 for(j=0;j<ch;j++){
|
|
213 long offset=info->begin+i*samples_per_partition;
|
|
214 if(info->secondstages[partword[j][l][k]]&(1<<s)){
|
|
215 codebook *stagebook=look->partbooks[partword[j][l][k]][s];
|
|
216 if(stagebook){
|
|
217 if(decodepart(stagebook,in[j]+offset,&vb->opb,
|
|
218 samples_per_partition,-8)==-1)goto eopbreak;
|
|
219 }
|
|
220 }
|
|
221 }
|
|
222 }
|
|
223 }
|
|
224
|
|
225 errout:
|
|
226 eopbreak:
|
|
227 return(0);
|
|
228 }
|
|
229
|
|
230 int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl,
|
|
231 ogg_int32_t **in,int *nonzero,int ch){
|
|
232 int i,used=0;
|
|
233 for(i=0;i<ch;i++)
|
|
234 if(nonzero[i])
|
|
235 in[used++]=in[i];
|
|
236 if(used)
|
|
237 return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add));
|
|
238 else
|
|
239 return(0);
|
|
240 }
|
|
241
|
|
242 int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl,
|
|
243 ogg_int32_t **in,int *nonzero,int ch){
|
|
244 int i,used=0;
|
|
245 for(i=0;i<ch;i++)
|
|
246 if(nonzero[i])
|
|
247 in[used++]=in[i];
|
|
248 if(used)
|
|
249 return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add));
|
|
250 else
|
|
251 return(0);
|
|
252 }
|
|
253
|
|
254 /* duplicate code here as speed is somewhat more important */
|
|
255 int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl,
|
|
256 ogg_int32_t **in,int *nonzero,int ch){
|
|
257 long i,k,l,s;
|
|
258 vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
|
|
259 vorbis_info_residue0 *info=look->info;
|
|
260
|
|
261 /* move all this setup out later */
|
|
262 int samples_per_partition=info->grouping;
|
|
263 int partitions_per_word=look->phrasebook->dim;
|
|
264 int n=info->end-info->begin;
|
|
265
|
|
266 int partvals=n/samples_per_partition;
|
|
267 int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
|
|
268 int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword));
|
|
269 int beginoff=info->begin/ch;
|
|
270
|
|
271 for(i=0;i<ch;i++)if(nonzero[i])break;
|
|
272 if(i==ch)return(0); /* no nonzero vectors */
|
|
273
|
|
274 samples_per_partition/=ch;
|
|
275
|
|
276 for(s=0;s<look->stages;s++){
|
|
277 for(i=0,l=0;i<partvals;l++){
|
|
278
|
|
279 if(s==0){
|
|
280 /* fetch the partition word */
|
|
281 int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
|
|
282 if(temp==-1)goto eopbreak;
|
|
283 partword[l]=look->decodemap[temp];
|
|
284 if(partword[l]==NULL)goto errout;
|
|
285 }
|
|
286
|
|
287 /* now we decode residual values for the partitions */
|
|
288 for(k=0;k<partitions_per_word && i<partvals;k++,i++)
|
|
289 if(info->secondstages[partword[l][k]]&(1<<s)){
|
|
290 codebook *stagebook=look->partbooks[partword[l][k]][s];
|
|
291
|
|
292 if(stagebook){
|
|
293 if(vorbis_book_decodevv_add(stagebook,in,
|
|
294 i*samples_per_partition+beginoff,ch,
|
|
295 &vb->opb,
|
|
296 samples_per_partition,-8)==-1)
|
|
297 goto eopbreak;
|
|
298 }
|
|
299 }
|
|
300 }
|
|
301 }
|
|
302
|
|
303 errout:
|
|
304 eopbreak:
|
|
305 return(0);
|
|
306 }
|
|
307
|
|
308
|
|
309 vorbis_func_residue residue0_exportbundle={
|
|
310 &res0_unpack,
|
|
311 &res0_look,
|
|
312 &res0_free_info,
|
|
313 &res0_free_look,
|
|
314 &res0_inverse
|
|
315 };
|
|
316
|
|
317 vorbis_func_residue residue1_exportbundle={
|
|
318 &res0_unpack,
|
|
319 &res0_look,
|
|
320 &res0_free_info,
|
|
321 &res0_free_look,
|
|
322 &res1_inverse
|
|
323 };
|
|
324
|
|
325 vorbis_func_residue residue2_exportbundle={
|
|
326 &res0_unpack,
|
|
327 &res0_look,
|
|
328 &res0_free_info,
|
|
329 &res0_free_look,
|
|
330 &res2_inverse
|
|
331 };
|