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