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 16227 2009-07-08 06:58:46Z xiphmont $
15
16 ********************************************************************/
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21 #include <ogg/ogg.h>
22 #include "vorbis/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
floor0_free_info(vorbis_info_floor * i)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
floor0_free_look(vorbis_look_floor * i)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
floor0_unpack(vorbis_info * vi,oggpack_buffer * opb)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 }
95 return(info);
96
97 err_out:
98 floor0_free_info(info);
99 return(NULL);
100 }
101
102 /* initialize Bark scale and normalization lookups. We could do this
103 with static tables, but Vorbis allows a number of possible
104 combinations, so it's best to do it computationally.
105
106 The below is authoritative in terms of defining scale mapping.
107 Note that the scale depends on the sampling rate as well as the
108 linear block and mapping sizes */
109
floor0_map_lazy_init(vorbis_block * vb,vorbis_info_floor * infoX,vorbis_look_floor0 * look)110 static void floor0_map_lazy_init(vorbis_block *vb,
111 vorbis_info_floor *infoX,
112 vorbis_look_floor0 *look){
113 if(!look->linearmap[vb->W]){
114 vorbis_dsp_state *vd=vb->vd;
115 vorbis_info *vi=vd->vi;
116 codec_setup_info *ci=vi->codec_setup;
117 vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
118 int W=vb->W;
119 int n=ci->blocksizes[W]/2,j;
120
121 /* we choose a scaling constant so that:
122 floor(bark(rate/2-1)*C)=mapped-1
123 floor(bark(rate/2)*C)=mapped */
124 float scale=look->ln/toBARK(info->rate/2.f);
125
126 /* the mapping from a linear scale to a smaller bark scale is
127 straightforward. We do *not* make sure that the linear mapping
128 does not skip bark-scale bins; the decoder simply skips them and
129 the encoder may do what it wishes in filling them. They're
130 necessary in some mapping combinations to keep the scale spacing
131 accurate */
132 look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
133 for(j=0;j<n;j++){
134 int val=floor( toBARK((info->rate/2.f)/n*j)
135 *scale); /* bark numbers represent band edges */
136 if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
137 look->linearmap[W][j]=val;
138 }
139 look->linearmap[W][j]=-1;
140 look->n[W]=n;
141 }
142 }
143
floor0_look(vorbis_dsp_state * vd,vorbis_info_floor * i)144 static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
145 vorbis_info_floor *i){
146 vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
147 vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
148 look->m=info->order;
149 look->ln=info->barkmap;
150 look->vi=info;
151
152 look->linearmap=_ogg_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,_ilog(info->numbooks));
167
168 if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
169 codec_setup_info *ci=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=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
177
178 for(j=0;j<look->m;j+=b->dim)
179 if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
180 for(j=0;j<look->m;){
181 for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
182 last=lsp[j-1];
183 }
184
185 lsp[look->m]=amp;
186 return(lsp);
187 }
188 }
189 eop:
190 return(NULL);
191 }
192
floor0_inverse2(vorbis_block * vb,vorbis_look_floor * i,void * memo,float * out)193 static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
194 void *memo,float *out){
195 vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
196 vorbis_info_floor0 *info=look->vi;
197
198 floor0_map_lazy_init(vb,info,look);
199
200 if(memo){
201 float *lsp=(float *)memo;
202 float amp=lsp[look->m];
203
204 /* take the coefficients back to a spectral envelope curve */
205 vorbis_lsp_to_curve(out,
206 look->linearmap[vb->W],
207 look->n[vb->W],
208 look->ln,
209 lsp,look->m,amp,(float)info->ampdB);
210 return(1);
211 }
212 memset(out,0,sizeof(*out)*look->n[vb->W]);
213 return(0);
214 }
215
216 /* export hooks */
217 const vorbis_func_floor floor0_exportbundle={
218 NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
219 &floor0_free_look,&floor0_inverse1,&floor0_inverse2
220 };
221