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