00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <math.h>
00021 #include "ogg.h"
00022 #include "ivorbiscodec.h"
00023 #include "codec_internal.h"
00024 #include "registry.h"
00025 #include "codebook.h"
00026 #include "misc.h"
00027
00028 #define floor1_rangedB 140
00029
00030 typedef struct {
00031 int forward_index[VIF_POSIT+2];
00032
00033 int hineighbor[VIF_POSIT];
00034 int loneighbor[VIF_POSIT];
00035 int posts;
00036
00037 int n;
00038 int quant_q;
00039 vorbis_info_floor1 *vi;
00040
00041 } vorbis_look_floor1;
00042
00043
00044
00045 static void floor1_free_info(vorbis_info_floor *i){
00046 vorbis_info_floor1 *info=(vorbis_info_floor1 *)i;
00047 if(info){
00048 memset(info,0,sizeof(*info));
00049 _ogg_free(info);
00050 }
00051 }
00052
00053 static void floor1_free_look(vorbis_look_floor *i){
00054 vorbis_look_floor1 *look=(vorbis_look_floor1 *)i;
00055 if(look){
00056 memset(look,0,sizeof(*look));
00057 _ogg_free(look);
00058 }
00059 }
00060
00061 static int ilog(unsigned int v){
00062 int ret=0;
00063 while(v){
00064 ret++;
00065 v>>=1;
00066 }
00067 return(ret);
00068 }
00069
00070 static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){
00071 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
00072 int j,k,count=0,maxclass=-1,rangebits;
00073
00074 vorbis_info_floor1 *info=(vorbis_info_floor1 *)_ogg_calloc(1,sizeof(*info));
00075
00076 info->partitions=oggpack_read(opb,5);
00077 for(j=0;j<info->partitions;j++){
00078 info->partitionclass[j]=oggpack_read(opb,4);
00079 if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
00080 }
00081
00082
00083 for(j=0;j<maxclass+1;j++){
00084 info->class_dim[j]=oggpack_read(opb,3)+1;
00085 info->class_subs[j]=oggpack_read(opb,2);
00086 if(info->class_subs[j]<0)
00087 goto err_out;
00088 if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8);
00089 if(info->class_book[j]<0 || info->class_book[j]>=ci->books)
00090 goto err_out;
00091 for(k=0;k<(1<<info->class_subs[j]);k++){
00092 info->class_subbook[j][k]=oggpack_read(opb,8)-1;
00093 if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books)
00094 goto err_out;
00095 }
00096 }
00097
00098
00099 info->mult=oggpack_read(opb,2)+1;
00100 rangebits=oggpack_read(opb,4);
00101
00102 for(j=0,k=0;j<info->partitions;j++){
00103 count+=info->class_dim[info->partitionclass[j]];
00104 for(;k<count;k++){
00105 int t=info->postlist[k+2]=oggpack_read(opb,rangebits);
00106 if(t<0 || t>=(1<<rangebits))
00107 goto err_out;
00108 }
00109 }
00110 info->postlist[0]=0;
00111 info->postlist[1]=1<<rangebits;
00112
00113 return(info);
00114
00115 err_out:
00116 floor1_free_info(info);
00117 return(NULL);
00118 }
00119
00120 static int icomp(const void *a,const void *b){
00121 return(**(int **)a-**(int **)b);
00122 }
00123
00124 static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,vorbis_info_mode *mi,
00125 vorbis_info_floor *in){
00126
00127 int *sortpointer[VIF_POSIT+2];
00128 vorbis_info_floor1 *info=(vorbis_info_floor1 *)in;
00129 vorbis_look_floor1 *look=(vorbis_look_floor1 *)_ogg_calloc(1,sizeof(*look));
00130 int i,j,n=0;
00131 mi = mi;
00132 vd = vd;
00133
00134 look->vi=info;
00135 look->n=info->postlist[1];
00136
00137
00138
00139
00140
00141
00142
00143
00144 for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]];
00145 n+=2;
00146 look->posts=n;
00147
00148
00149 for(i=0;i<n;i++)sortpointer[i]=info->postlist+i;
00150 qsort(sortpointer,n,sizeof(*sortpointer),icomp);
00151
00152
00153 for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist;
00154
00155
00156 switch(info->mult){
00157 case 1:
00158 look->quant_q=256;
00159 break;
00160 case 2:
00161 look->quant_q=128;
00162 break;
00163 case 3:
00164 look->quant_q=86;
00165 break;
00166 case 4:
00167 look->quant_q=64;
00168 break;
00169 }
00170
00171
00172
00173 for(i=0;i<n-2;i++){
00174 int lo=0;
00175 int hi=1;
00176 int lx=0;
00177 int hx=look->n;
00178 int currentx=info->postlist[i+2];
00179 for(j=0;j<i+2;j++){
00180 int x=info->postlist[j];
00181 if(x>lx && x<currentx){
00182 lo=j;
00183 lx=x;
00184 }
00185 if(x<hx && x>currentx){
00186 hi=j;
00187 hx=x;
00188 }
00189 }
00190 look->loneighbor[i]=lo;
00191 look->hineighbor[i]=hi;
00192 }
00193
00194 return(look);
00195 }
00196
00197 static int render_point(int x0,int x1,int y0,int y1,int x){
00198 y0&=0x7fff;
00199 y1&=0x7fff;
00200
00201 {
00202 int dy=y1-y0;
00203 int adx=x1-x0;
00204 int ady=abs(dy);
00205 int err=ady*(x-x0);
00206
00207 int off=err/adx;
00208 if(dy<0)return(y0-off);
00209 return(y0+off);
00210 }
00211 }
00212
00213 #ifdef _LOW_ACCURACY_
00214 # define XdB(n) ((((n)>>8)+1)>>1)
00215 #else
00216 # define XdB(n) (n)
00217 #endif
00218
00219 static const ogg_int32_t FLOOR_fromdB_LOOKUP[256]={
00220 XdB(0x000000e5), XdB(0x000000f4), XdB(0x00000103), XdB(0x00000114),
00221 XdB(0x00000126), XdB(0x00000139), XdB(0x0000014e), XdB(0x00000163),
00222 XdB(0x0000017a), XdB(0x00000193), XdB(0x000001ad), XdB(0x000001c9),
00223 XdB(0x000001e7), XdB(0x00000206), XdB(0x00000228), XdB(0x0000024c),
00224 XdB(0x00000272), XdB(0x0000029b), XdB(0x000002c6), XdB(0x000002f4),
00225 XdB(0x00000326), XdB(0x0000035a), XdB(0x00000392), XdB(0x000003cd),
00226 XdB(0x0000040c), XdB(0x00000450), XdB(0x00000497), XdB(0x000004e4),
00227 XdB(0x00000535), XdB(0x0000058c), XdB(0x000005e8), XdB(0x0000064a),
00228 XdB(0x000006b3), XdB(0x00000722), XdB(0x00000799), XdB(0x00000818),
00229 XdB(0x0000089e), XdB(0x0000092e), XdB(0x000009c6), XdB(0x00000a69),
00230 XdB(0x00000b16), XdB(0x00000bcf), XdB(0x00000c93), XdB(0x00000d64),
00231 XdB(0x00000e43), XdB(0x00000f30), XdB(0x0000102d), XdB(0x0000113a),
00232 XdB(0x00001258), XdB(0x0000138a), XdB(0x000014cf), XdB(0x00001629),
00233 XdB(0x0000179a), XdB(0x00001922), XdB(0x00001ac4), XdB(0x00001c82),
00234 XdB(0x00001e5c), XdB(0x00002055), XdB(0x0000226f), XdB(0x000024ac),
00235 XdB(0x0000270e), XdB(0x00002997), XdB(0x00002c4b), XdB(0x00002f2c),
00236 XdB(0x0000323d), XdB(0x00003581), XdB(0x000038fb), XdB(0x00003caf),
00237 XdB(0x000040a0), XdB(0x000044d3), XdB(0x0000494c), XdB(0x00004e10),
00238 XdB(0x00005323), XdB(0x0000588a), XdB(0x00005e4b), XdB(0x0000646b),
00239 XdB(0x00006af2), XdB(0x000071e5), XdB(0x0000794c), XdB(0x0000812e),
00240 XdB(0x00008993), XdB(0x00009283), XdB(0x00009c09), XdB(0x0000a62d),
00241 XdB(0x0000b0f9), XdB(0x0000bc79), XdB(0x0000c8b9), XdB(0x0000d5c4),
00242 XdB(0x0000e3a9), XdB(0x0000f274), XdB(0x00010235), XdB(0x000112fd),
00243 XdB(0x000124dc), XdB(0x000137e4), XdB(0x00014c29), XdB(0x000161bf),
00244 XdB(0x000178bc), XdB(0x00019137), XdB(0x0001ab4a), XdB(0x0001c70e),
00245 XdB(0x0001e4a1), XdB(0x0002041f), XdB(0x000225aa), XdB(0x00024962),
00246 XdB(0x00026f6d), XdB(0x000297f0), XdB(0x0002c316), XdB(0x0002f109),
00247 XdB(0x000321f9), XdB(0x00035616), XdB(0x00038d97), XdB(0x0003c8b4),
00248 XdB(0x000407a7), XdB(0x00044ab2), XdB(0x00049218), XdB(0x0004de23),
00249 XdB(0x00052f1e), XdB(0x0005855c), XdB(0x0005e135), XdB(0x00064306),
00250 XdB(0x0006ab33), XdB(0x00071a24), XdB(0x0007904b), XdB(0x00080e20),
00251 XdB(0x00089422), XdB(0x000922da), XdB(0x0009bad8), XdB(0x000a5cb6),
00252 XdB(0x000b091a), XdB(0x000bc0b1), XdB(0x000c8436), XdB(0x000d5471),
00253 XdB(0x000e3233), XdB(0x000f1e5f), XdB(0x001019e4), XdB(0x001125c1),
00254 XdB(0x00124306), XdB(0x001372d5), XdB(0x0014b663), XdB(0x00160ef7),
00255 XdB(0x00177df0), XdB(0x001904c1), XdB(0x001aa4f9), XdB(0x001c603d),
00256 XdB(0x001e384f), XdB(0x00202f0f), XdB(0x0022467a), XdB(0x002480b1),
00257 XdB(0x0026dff7), XdB(0x002966b3), XdB(0x002c1776), XdB(0x002ef4fc),
00258 XdB(0x0032022d), XdB(0x00354222), XdB(0x0038b828), XdB(0x003c67c2),
00259 XdB(0x004054ae), XdB(0x004482e8), XdB(0x0048f6af), XdB(0x004db488),
00260 XdB(0x0052c142), XdB(0x005821ff), XdB(0x005ddc33), XdB(0x0063f5b0),
00261 XdB(0x006a74a7), XdB(0x00715faf), XdB(0x0078bdce), XdB(0x0080967f),
00262 XdB(0x0088f1ba), XdB(0x0091d7f9), XdB(0x009b5247), XdB(0x00a56a41),
00263 XdB(0x00b02a27), XdB(0x00bb9ce2), XdB(0x00c7ce12), XdB(0x00d4ca17),
00264 XdB(0x00e29e20), XdB(0x00f15835), XdB(0x0101074b), XdB(0x0111bb4e),
00265 XdB(0x01238531), XdB(0x01367704), XdB(0x014aa402), XdB(0x016020a7),
00266 XdB(0x017702c3), XdB(0x018f6190), XdB(0x01a955cb), XdB(0x01c4f9cf),
00267 XdB(0x01e269a8), XdB(0x0201c33b), XdB(0x0223265a), XdB(0x0246b4ea),
00268 XdB(0x026c9302), XdB(0x0294e716), XdB(0x02bfda13), XdB(0x02ed9793),
00269 XdB(0x031e4e09), XdB(0x03522ee4), XdB(0x03896ed0), XdB(0x03c445e2),
00270 XdB(0x0402efd6), XdB(0x0445ac4b), XdB(0x048cbefc), XdB(0x04d87013),
00271 XdB(0x05290c67), XdB(0x057ee5ca), XdB(0x05da5364), XdB(0x063bb204),
00272 XdB(0x06a36485), XdB(0x0711d42b), XdB(0x0787710e), XdB(0x0804b299),
00273 XdB(0x088a17ef), XdB(0x0918287e), XdB(0x09af747c), XdB(0x0a50957e),
00274 XdB(0x0afc2f19), XdB(0x0bb2ef7f), XdB(0x0c759034), XdB(0x0d44d6ca),
00275 XdB(0x0e2195bc), XdB(0x0f0cad0d), XdB(0x10070b62), XdB(0x1111aeea),
00276 XdB(0x122da66c), XdB(0x135c120f), XdB(0x149e24d9), XdB(0x15f525b1),
00277 XdB(0x176270e3), XdB(0x18e7794b), XdB(0x1a85c9ae), XdB(0x1c3f06d1),
00278 XdB(0x1e14f07d), XdB(0x200963d7), XdB(0x221e5ccd), XdB(0x2455f870),
00279 XdB(0x26b2770b), XdB(0x29363e2b), XdB(0x2be3db5c), XdB(0x2ebe06b6),
00280 XdB(0x31c7a55b), XdB(0x3503ccd4), XdB(0x3875c5aa), XdB(0x3c210f44),
00281 XdB(0x4009632b), XdB(0x4432b8cf), XdB(0x48a149bc), XdB(0x4d59959e),
00282 XdB(0x52606733), XdB(0x57bad899), XdB(0x5d6e593a), XdB(0x6380b298),
00283 XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff),
00284 };
00285
00286 static void render_line(int x0,int x1,int y0,int y1,ogg_int32_t *d){
00287 int dy=y1-y0;
00288 int adx=x1-x0;
00289 int ady=abs(dy);
00290 int base=dy/adx;
00291 int sy=(dy<0?base-1:base+1);
00292 int x=x0;
00293 int y=y0;
00294 int err=0;
00295
00296 ady-=abs(base*adx);
00297
00298 d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]);
00299
00300 while(++x<x1){
00301 err=err+ady;
00302 if(err>=adx){
00303 err-=adx;
00304 y+=sy;
00305 }else{
00306 y+=base;
00307 }
00308 d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]);
00309 }
00310 }
00311
00312 void *_vorbis_block_alloc(vorbis_block *vb,long bytes);
00313 static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
00314 vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
00315 vorbis_info_floor1 *info=look->vi;
00316 codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
00317
00318 int i,j,k;
00319 codebook *books=ci->fullbooks;
00320
00321
00322 if(oggpack_read(&vb->opb,1)==1){
00323 int *fit_value=(int *)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value));
00324
00325 fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1));
00326 fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1));
00327
00328
00329
00330 for(i=0,j=2;i<info->partitions;i++){
00331 int classv=info->partitionclass[i];
00332 int cdim=info->class_dim[classv];
00333 int csubbits=info->class_subs[classv];
00334 int csub=1<<csubbits;
00335 int cval=0;
00336
00337
00338 if(csubbits){
00339 cval=vorbis_book_decode(books+info->class_book[classv],&vb->opb);
00340
00341 if(cval==-1)goto eop;
00342 }
00343
00344 for(k=0;k<cdim;k++){
00345 int book=info->class_subbook[classv][cval&(csub-1)];
00346 cval>>=csubbits;
00347 if(book>=0){
00348 if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1)
00349 goto eop;
00350 }else{
00351 fit_value[j+k]=0;
00352 }
00353 }
00354 j+=cdim;
00355 }
00356
00357
00358 for(i=2;i<look->posts;i++){
00359 int predicted=render_point(info->postlist[look->loneighbor[i-2]],
00360 info->postlist[look->hineighbor[i-2]],
00361 fit_value[look->loneighbor[i-2]],
00362 fit_value[look->hineighbor[i-2]],
00363 info->postlist[i]);
00364 int hiroom=look->quant_q-predicted;
00365 int loroom=predicted;
00366 int room=(hiroom<loroom?hiroom:loroom)<<1;
00367 int val=fit_value[i];
00368
00369 if(val){
00370 if(val>=room){
00371 if(hiroom>loroom){
00372 val = val-loroom;
00373 }else{
00374 val = -1-(val-hiroom);
00375 }
00376 }else{
00377 if(val&1){
00378 val= -((val+1)>>1);
00379 }else{
00380 val>>=1;
00381 }
00382 }
00383
00384 fit_value[i]=val+predicted;
00385 fit_value[look->loneighbor[i-2]]&=0x7fff;
00386 fit_value[look->hineighbor[i-2]]&=0x7fff;
00387
00388 }else{
00389 fit_value[i]=predicted|0x8000;
00390 }
00391
00392 }
00393
00394 return(fit_value);
00395 }
00396 eop:
00397 return(NULL);
00398 }
00399
00400 static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
00401 ogg_int32_t *out){
00402 vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
00403 vorbis_info_floor1 *info=look->vi;
00404
00405 codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
00406 int n=ci->blocksizes[vb->W]/2;
00407 int j;
00408
00409 if(memo){
00410
00411 int *fit_value=(int *)memo;
00412 int hx=0;
00413 int lx=0;
00414 int ly=fit_value[0]*info->mult;
00415 for(j=1;j<look->posts;j++){
00416 int current=look->forward_index[j];
00417 int hy=fit_value[current]&0x7fff;
00418 if(hy==fit_value[current]){
00419
00420 hy*=info->mult;
00421 hx=info->postlist[current];
00422
00423 render_line(lx,hx,ly,hy,out);
00424
00425 lx=hx;
00426 ly=hy;
00427 }
00428 }
00429 for(j=hx;j<n;j++)out[j]*=ly;
00430 return(1);
00431 }
00432 memset(out,0,sizeof(*out)*n);
00433 return(0);
00434 }
00435
00436
00437 const vorbis_func_floor floor1_exportbundle={
00438 &floor1_unpack,&floor1_look,&floor1_free_info,
00439 &floor1_free_look,&floor1_inverse1,&floor1_inverse2
00440 };
00441