]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/ext/vorbis/floor0.c
wwww
[16.git] / src / lib / doslib / ext / vorbis / floor0.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
9  * by the Xiph.Org Foundation http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12
13  function: floor backend 0 implementation
14  last mod: $Id: floor0.c 17558 2010-10-22 00:24:41Z tterribe $
15
16  ********************************************************************/
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21 #include <ext/libogg/ogg.h>
22 #include "codec.h"
23 #include "codec_internal.h"
24 #include "registry.h"
25 #include "lpc.h"
26 #include "lsp.h"
27 #include "codebook.h"
28 #include "scales.h"
29 #include "misc.h"
30 #include "os.h"
31
32 #include "misc.h"
33 #include <stdio.h>
34
35 typedef struct {
36   int ln;
37   int  m;
38   int **linearmap;
39   int  n[2];
40
41   vorbis_info_floor0 *vi;
42
43   long bits;
44   long frames;
45 } vorbis_look_floor0;
46
47
48 /***********************************************/
49
50 static void floor0_free_info(vorbis_info_floor *i){
51   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
52   if(info){
53     memset(info,0,sizeof(*info));
54     _ogg_free(info);
55   }
56 }
57
58 static void floor0_free_look(vorbis_look_floor *i){
59   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
60   if(look){
61
62     if(look->linearmap){
63
64       if(look->linearmap[0])_ogg_free(look->linearmap[0]);
65       if(look->linearmap[1])_ogg_free(look->linearmap[1]);
66
67       _ogg_free(look->linearmap);
68     }
69     memset(look,0,sizeof(*look));
70     _ogg_free(look);
71   }
72 }
73
74 static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
75   codec_setup_info     *ci=vi->codec_setup;
76   int j;
77
78   vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info));
79   info->order=oggpack_read(opb,8);
80   info->rate=oggpack_read(opb,16);
81   info->barkmap=oggpack_read(opb,16);
82   info->ampbits=oggpack_read(opb,6);
83   info->ampdB=oggpack_read(opb,8);
84   info->numbooks=oggpack_read(opb,4)+1;
85
86   if(info->order<1)goto err_out;
87   if(info->rate<1)goto err_out;
88   if(info->barkmap<1)goto err_out;
89   if(info->numbooks<1)goto err_out;
90
91   for(j=0;j<info->numbooks;j++){
92     info->books[j]=oggpack_read(opb,8);
93     if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
94     if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
95     if(ci->book_param[info->books[j]]->dim<1)goto err_out;
96   }
97   return(info);
98
99  err_out:
100   floor0_free_info(info);
101   return(NULL);
102 }
103
104 /* initialize Bark scale and normalization lookups.  We could do this
105    with static tables, but Vorbis allows a number of possible
106    combinations, so it's best to do it computationally.
107
108    The below is authoritative in terms of defining scale mapping.
109    Note that the scale depends on the sampling rate as well as the
110    linear block and mapping sizes */
111
112 static void floor0_map_lazy_init(vorbis_block      *vb,
113                                  vorbis_info_floor *infoX,
114                                  vorbis_look_floor0 *look){
115   if(!look->linearmap[vb->W]){
116     vorbis_dsp_state   *vd=vb->vd;
117     vorbis_info        *vi=vd->vi;
118     codec_setup_info   *ci=vi->codec_setup;
119     vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
120     int W=vb->W;
121     int n=ci->blocksizes[W]/2,j;
122
123     /* we choose a scaling constant so that:
124        floor(bark(rate/2-1)*C)=mapped-1
125      floor(bark(rate/2)*C)=mapped */
126     float scale=look->ln/toBARK(info->rate/2.f);
127
128     /* the mapping from a linear scale to a smaller bark scale is
129        straightforward.  We do *not* make sure that the linear mapping
130        does not skip bark-scale bins; the decoder simply skips them and
131        the encoder may do what it wishes in filling them.  They're
132        necessary in some mapping combinations to keep the scale spacing
133        accurate */
134     look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
135     for(j=0;j<n;j++){
136       int val=floor( toBARK((info->rate/2.f)/n*j)
137                      *scale); /* bark numbers represent band edges */
138       if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
139       look->linearmap[W][j]=val;
140     }
141     look->linearmap[W][j]=-1;
142     look->n[W]=n;
143   }
144 }
145
146 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
147                                       vorbis_info_floor *i){
148   vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
149   vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
150   look->m=info->order;
151   look->ln=info->barkmap;
152   look->vi=info;
153
154   look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
155
156   return look;
157 }
158
159 static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
160   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
161   vorbis_info_floor0 *info=look->vi;
162   int j,k;
163
164   int ampraw=oggpack_read(&vb->opb,info->ampbits);
165   if(ampraw>0){ /* also handles the -1 out of data case */
166     long maxval=(1<<info->ampbits)-1;
167     float amp=(float)ampraw/maxval*info->ampdB;
168     int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
169
170     if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
171       codec_setup_info  *ci=vb->vd->vi->codec_setup;
172       codebook *b=ci->fullbooks+info->books[booknum];
173       float last=0.f;
174
175       /* the additional b->dim is a guard against any possible stack
176          smash; b->dim is provably more than we can overflow the
177          vector */
178       float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
179
180       for(j=0;j<look->m;j+=b->dim)
181         if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
182       for(j=0;j<look->m;){
183         for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
184         last=lsp[j-1];
185       }
186
187       lsp[look->m]=amp;
188       return(lsp);
189     }
190   }
191  eop:
192   return(NULL);
193 }
194
195 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
196                            void *memo,float *out){
197   vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
198   vorbis_info_floor0 *info=look->vi;
199
200   floor0_map_lazy_init(vb,info,look);
201
202   if(memo){
203     float *lsp=(float *)memo;
204     float amp=lsp[look->m];
205
206     /* take the coefficients back to a spectral envelope curve */
207     vorbis_lsp_to_curve(out,
208                         look->linearmap[vb->W],
209                         look->n[vb->W],
210                         look->ln,
211                         lsp,look->m,amp,(float)info->ampdB);
212     return(1);
213   }
214   memset(out,0,sizeof(*out)*look->n[vb->W]);
215   return(0);
216 }
217
218 /* export hooks */
219 const vorbis_func_floor floor0_exportbundle={
220   NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
221   &floor0_free_look,&floor0_inverse1,&floor0_inverse2
222 };