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 | };
|
---|