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