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