Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /******************************************************************** |
michael@0 | 2 | * * |
michael@0 | 3 | * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * |
michael@0 | 4 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
michael@0 | 5 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
michael@0 | 6 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
michael@0 | 7 | * * |
michael@0 | 8 | * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 * |
michael@0 | 9 | * by the Xiph.Org Foundation http://www.xiph.org/ * |
michael@0 | 10 | * * |
michael@0 | 11 | ******************************************************************** |
michael@0 | 12 | |
michael@0 | 13 | function: simple programmatic interface for encoder mode setup |
michael@0 | 14 | last mod: $Id: vorbisenc.c 17028 2010-03-25 05:22:15Z xiphmont $ |
michael@0 | 15 | |
michael@0 | 16 | ********************************************************************/ |
michael@0 | 17 | |
michael@0 | 18 | #include <stdlib.h> |
michael@0 | 19 | #include <string.h> |
michael@0 | 20 | #include <math.h> |
michael@0 | 21 | |
michael@0 | 22 | #include "vorbis/codec.h" |
michael@0 | 23 | #include "vorbis/vorbisenc.h" |
michael@0 | 24 | |
michael@0 | 25 | #include "codec_internal.h" |
michael@0 | 26 | |
michael@0 | 27 | #include "os.h" |
michael@0 | 28 | #include "misc.h" |
michael@0 | 29 | |
michael@0 | 30 | /* careful with this; it's using static array sizing to make managing |
michael@0 | 31 | all the modes a little less annoying. If we use a residue backend |
michael@0 | 32 | with > 12 partition types, or a different division of iteration, |
michael@0 | 33 | this needs to be updated. */ |
michael@0 | 34 | typedef struct { |
michael@0 | 35 | const static_codebook *books[12][4]; |
michael@0 | 36 | } static_bookblock; |
michael@0 | 37 | |
michael@0 | 38 | typedef struct { |
michael@0 | 39 | int res_type; |
michael@0 | 40 | int limit_type; /* 0 lowpass limited, 1 point stereo limited */ |
michael@0 | 41 | int grouping; |
michael@0 | 42 | const vorbis_info_residue0 *res; |
michael@0 | 43 | const static_codebook *book_aux; |
michael@0 | 44 | const static_codebook *book_aux_managed; |
michael@0 | 45 | const static_bookblock *books_base; |
michael@0 | 46 | const static_bookblock *books_base_managed; |
michael@0 | 47 | } vorbis_residue_template; |
michael@0 | 48 | |
michael@0 | 49 | typedef struct { |
michael@0 | 50 | const vorbis_info_mapping0 *map; |
michael@0 | 51 | const vorbis_residue_template *res; |
michael@0 | 52 | } vorbis_mapping_template; |
michael@0 | 53 | |
michael@0 | 54 | typedef struct vp_adjblock{ |
michael@0 | 55 | int block[P_BANDS]; |
michael@0 | 56 | } vp_adjblock; |
michael@0 | 57 | |
michael@0 | 58 | typedef struct { |
michael@0 | 59 | int data[NOISE_COMPAND_LEVELS]; |
michael@0 | 60 | } compandblock; |
michael@0 | 61 | |
michael@0 | 62 | /* high level configuration information for setting things up |
michael@0 | 63 | step-by-step with the detailed vorbis_encode_ctl interface. |
michael@0 | 64 | There's a fair amount of redundancy such that interactive setup |
michael@0 | 65 | does not directly deal with any vorbis_info or codec_setup_info |
michael@0 | 66 | initialization; it's all stored (until full init) in this highlevel |
michael@0 | 67 | setup, then flushed out to the real codec setup structs later. */ |
michael@0 | 68 | |
michael@0 | 69 | typedef struct { |
michael@0 | 70 | int att[P_NOISECURVES]; |
michael@0 | 71 | float boost; |
michael@0 | 72 | float decay; |
michael@0 | 73 | } att3; |
michael@0 | 74 | typedef struct { int data[P_NOISECURVES]; } adj3; |
michael@0 | 75 | |
michael@0 | 76 | typedef struct { |
michael@0 | 77 | int pre[PACKETBLOBS]; |
michael@0 | 78 | int post[PACKETBLOBS]; |
michael@0 | 79 | float kHz[PACKETBLOBS]; |
michael@0 | 80 | float lowpasskHz[PACKETBLOBS]; |
michael@0 | 81 | } adj_stereo; |
michael@0 | 82 | |
michael@0 | 83 | typedef struct { |
michael@0 | 84 | int lo; |
michael@0 | 85 | int hi; |
michael@0 | 86 | int fixed; |
michael@0 | 87 | } noiseguard; |
michael@0 | 88 | typedef struct { |
michael@0 | 89 | int data[P_NOISECURVES][17]; |
michael@0 | 90 | } noise3; |
michael@0 | 91 | |
michael@0 | 92 | typedef struct { |
michael@0 | 93 | int mappings; |
michael@0 | 94 | const double *rate_mapping; |
michael@0 | 95 | const double *quality_mapping; |
michael@0 | 96 | int coupling_restriction; |
michael@0 | 97 | long samplerate_min_restriction; |
michael@0 | 98 | long samplerate_max_restriction; |
michael@0 | 99 | |
michael@0 | 100 | |
michael@0 | 101 | const int *blocksize_short; |
michael@0 | 102 | const int *blocksize_long; |
michael@0 | 103 | |
michael@0 | 104 | const att3 *psy_tone_masteratt; |
michael@0 | 105 | const int *psy_tone_0dB; |
michael@0 | 106 | const int *psy_tone_dBsuppress; |
michael@0 | 107 | |
michael@0 | 108 | const vp_adjblock *psy_tone_adj_impulse; |
michael@0 | 109 | const vp_adjblock *psy_tone_adj_long; |
michael@0 | 110 | const vp_adjblock *psy_tone_adj_other; |
michael@0 | 111 | |
michael@0 | 112 | const noiseguard *psy_noiseguards; |
michael@0 | 113 | const noise3 *psy_noise_bias_impulse; |
michael@0 | 114 | const noise3 *psy_noise_bias_padding; |
michael@0 | 115 | const noise3 *psy_noise_bias_trans; |
michael@0 | 116 | const noise3 *psy_noise_bias_long; |
michael@0 | 117 | const int *psy_noise_dBsuppress; |
michael@0 | 118 | |
michael@0 | 119 | const compandblock *psy_noise_compand; |
michael@0 | 120 | const double *psy_noise_compand_short_mapping; |
michael@0 | 121 | const double *psy_noise_compand_long_mapping; |
michael@0 | 122 | |
michael@0 | 123 | const int *psy_noise_normal_start[2]; |
michael@0 | 124 | const int *psy_noise_normal_partition[2]; |
michael@0 | 125 | const double *psy_noise_normal_thresh; |
michael@0 | 126 | |
michael@0 | 127 | const int *psy_ath_float; |
michael@0 | 128 | const int *psy_ath_abs; |
michael@0 | 129 | |
michael@0 | 130 | const double *psy_lowpass; |
michael@0 | 131 | |
michael@0 | 132 | const vorbis_info_psy_global *global_params; |
michael@0 | 133 | const double *global_mapping; |
michael@0 | 134 | const adj_stereo *stereo_modes; |
michael@0 | 135 | |
michael@0 | 136 | const static_codebook *const *const *const floor_books; |
michael@0 | 137 | const vorbis_info_floor1 *floor_params; |
michael@0 | 138 | const int floor_mappings; |
michael@0 | 139 | const int **floor_mapping_list; |
michael@0 | 140 | |
michael@0 | 141 | const vorbis_mapping_template *maps; |
michael@0 | 142 | } ve_setup_data_template; |
michael@0 | 143 | |
michael@0 | 144 | /* a few static coder conventions */ |
michael@0 | 145 | static const vorbis_info_mode _mode_template[2]={ |
michael@0 | 146 | {0,0,0,0}, |
michael@0 | 147 | {1,0,0,1} |
michael@0 | 148 | }; |
michael@0 | 149 | |
michael@0 | 150 | static const vorbis_info_mapping0 _map_nominal[2]={ |
michael@0 | 151 | {1, {0,0}, {0}, {0}, 1,{0},{1}}, |
michael@0 | 152 | {1, {0,0}, {1}, {1}, 1,{0},{1}} |
michael@0 | 153 | }; |
michael@0 | 154 | |
michael@0 | 155 | #include "modes/setup_44.h" |
michael@0 | 156 | #include "modes/setup_44u.h" |
michael@0 | 157 | #include "modes/setup_44p51.h" |
michael@0 | 158 | #include "modes/setup_32.h" |
michael@0 | 159 | #include "modes/setup_8.h" |
michael@0 | 160 | #include "modes/setup_11.h" |
michael@0 | 161 | #include "modes/setup_16.h" |
michael@0 | 162 | #include "modes/setup_22.h" |
michael@0 | 163 | #include "modes/setup_X.h" |
michael@0 | 164 | |
michael@0 | 165 | static const ve_setup_data_template *const setup_list[]={ |
michael@0 | 166 | &ve_setup_44_stereo, |
michael@0 | 167 | &ve_setup_44_51, |
michael@0 | 168 | &ve_setup_44_uncoupled, |
michael@0 | 169 | |
michael@0 | 170 | &ve_setup_32_stereo, |
michael@0 | 171 | &ve_setup_32_uncoupled, |
michael@0 | 172 | |
michael@0 | 173 | &ve_setup_22_stereo, |
michael@0 | 174 | &ve_setup_22_uncoupled, |
michael@0 | 175 | &ve_setup_16_stereo, |
michael@0 | 176 | &ve_setup_16_uncoupled, |
michael@0 | 177 | |
michael@0 | 178 | &ve_setup_11_stereo, |
michael@0 | 179 | &ve_setup_11_uncoupled, |
michael@0 | 180 | &ve_setup_8_stereo, |
michael@0 | 181 | &ve_setup_8_uncoupled, |
michael@0 | 182 | |
michael@0 | 183 | &ve_setup_X_stereo, |
michael@0 | 184 | &ve_setup_X_uncoupled, |
michael@0 | 185 | &ve_setup_XX_stereo, |
michael@0 | 186 | &ve_setup_XX_uncoupled, |
michael@0 | 187 | 0 |
michael@0 | 188 | }; |
michael@0 | 189 | |
michael@0 | 190 | static void vorbis_encode_floor_setup(vorbis_info *vi,int s, |
michael@0 | 191 | const static_codebook *const *const *const books, |
michael@0 | 192 | const vorbis_info_floor1 *in, |
michael@0 | 193 | const int *x){ |
michael@0 | 194 | int i,k,is=s; |
michael@0 | 195 | vorbis_info_floor1 *f=_ogg_calloc(1,sizeof(*f)); |
michael@0 | 196 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 197 | |
michael@0 | 198 | memcpy(f,in+x[is],sizeof(*f)); |
michael@0 | 199 | |
michael@0 | 200 | /* books */ |
michael@0 | 201 | { |
michael@0 | 202 | int partitions=f->partitions; |
michael@0 | 203 | int maxclass=-1; |
michael@0 | 204 | int maxbook=-1; |
michael@0 | 205 | for(i=0;i<partitions;i++) |
michael@0 | 206 | if(f->partitionclass[i]>maxclass)maxclass=f->partitionclass[i]; |
michael@0 | 207 | for(i=0;i<=maxclass;i++){ |
michael@0 | 208 | if(f->class_book[i]>maxbook)maxbook=f->class_book[i]; |
michael@0 | 209 | f->class_book[i]+=ci->books; |
michael@0 | 210 | for(k=0;k<(1<<f->class_subs[i]);k++){ |
michael@0 | 211 | if(f->class_subbook[i][k]>maxbook)maxbook=f->class_subbook[i][k]; |
michael@0 | 212 | if(f->class_subbook[i][k]>=0)f->class_subbook[i][k]+=ci->books; |
michael@0 | 213 | } |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | for(i=0;i<=maxbook;i++) |
michael@0 | 217 | ci->book_param[ci->books++]=(static_codebook *)books[x[is]][i]; |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | /* for now, we're only using floor 1 */ |
michael@0 | 221 | ci->floor_type[ci->floors]=1; |
michael@0 | 222 | ci->floor_param[ci->floors]=f; |
michael@0 | 223 | ci->floors++; |
michael@0 | 224 | |
michael@0 | 225 | return; |
michael@0 | 226 | } |
michael@0 | 227 | |
michael@0 | 228 | static void vorbis_encode_global_psych_setup(vorbis_info *vi,double s, |
michael@0 | 229 | const vorbis_info_psy_global *in, |
michael@0 | 230 | const double *x){ |
michael@0 | 231 | int i,is=s; |
michael@0 | 232 | double ds=s-is; |
michael@0 | 233 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 234 | vorbis_info_psy_global *g=&ci->psy_g_param; |
michael@0 | 235 | |
michael@0 | 236 | memcpy(g,in+(int)x[is],sizeof(*g)); |
michael@0 | 237 | |
michael@0 | 238 | ds=x[is]*(1.-ds)+x[is+1]*ds; |
michael@0 | 239 | is=(int)ds; |
michael@0 | 240 | ds-=is; |
michael@0 | 241 | if(ds==0 && is>0){ |
michael@0 | 242 | is--; |
michael@0 | 243 | ds=1.; |
michael@0 | 244 | } |
michael@0 | 245 | |
michael@0 | 246 | /* interpolate the trigger threshholds */ |
michael@0 | 247 | for(i=0;i<4;i++){ |
michael@0 | 248 | g->preecho_thresh[i]=in[is].preecho_thresh[i]*(1.-ds)+in[is+1].preecho_thresh[i]*ds; |
michael@0 | 249 | g->postecho_thresh[i]=in[is].postecho_thresh[i]*(1.-ds)+in[is+1].postecho_thresh[i]*ds; |
michael@0 | 250 | } |
michael@0 | 251 | g->ampmax_att_per_sec=ci->hi.amplitude_track_dBpersec; |
michael@0 | 252 | return; |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | static void vorbis_encode_global_stereo(vorbis_info *vi, |
michael@0 | 256 | const highlevel_encode_setup *const hi, |
michael@0 | 257 | const adj_stereo *p){ |
michael@0 | 258 | float s=hi->stereo_point_setting; |
michael@0 | 259 | int i,is=s; |
michael@0 | 260 | double ds=s-is; |
michael@0 | 261 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 262 | vorbis_info_psy_global *g=&ci->psy_g_param; |
michael@0 | 263 | |
michael@0 | 264 | if(p){ |
michael@0 | 265 | memcpy(g->coupling_prepointamp,p[is].pre,sizeof(*p[is].pre)*PACKETBLOBS); |
michael@0 | 266 | memcpy(g->coupling_postpointamp,p[is].post,sizeof(*p[is].post)*PACKETBLOBS); |
michael@0 | 267 | |
michael@0 | 268 | if(hi->managed){ |
michael@0 | 269 | /* interpolate the kHz threshholds */ |
michael@0 | 270 | for(i=0;i<PACKETBLOBS;i++){ |
michael@0 | 271 | float kHz=p[is].kHz[i]*(1.-ds)+p[is+1].kHz[i]*ds; |
michael@0 | 272 | g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; |
michael@0 | 273 | g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; |
michael@0 | 274 | g->coupling_pkHz[i]=kHz; |
michael@0 | 275 | |
michael@0 | 276 | kHz=p[is].lowpasskHz[i]*(1.-ds)+p[is+1].lowpasskHz[i]*ds; |
michael@0 | 277 | g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; |
michael@0 | 278 | g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; |
michael@0 | 279 | |
michael@0 | 280 | } |
michael@0 | 281 | }else{ |
michael@0 | 282 | float kHz=p[is].kHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].kHz[PACKETBLOBS/2]*ds; |
michael@0 | 283 | for(i=0;i<PACKETBLOBS;i++){ |
michael@0 | 284 | g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; |
michael@0 | 285 | g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; |
michael@0 | 286 | g->coupling_pkHz[i]=kHz; |
michael@0 | 287 | } |
michael@0 | 288 | |
michael@0 | 289 | kHz=p[is].lowpasskHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].lowpasskHz[PACKETBLOBS/2]*ds; |
michael@0 | 290 | for(i=0;i<PACKETBLOBS;i++){ |
michael@0 | 291 | g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; |
michael@0 | 292 | g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; |
michael@0 | 293 | } |
michael@0 | 294 | } |
michael@0 | 295 | }else{ |
michael@0 | 296 | for(i=0;i<PACKETBLOBS;i++){ |
michael@0 | 297 | g->sliding_lowpass[0][i]=ci->blocksizes[0]; |
michael@0 | 298 | g->sliding_lowpass[1][i]=ci->blocksizes[1]; |
michael@0 | 299 | } |
michael@0 | 300 | } |
michael@0 | 301 | return; |
michael@0 | 302 | } |
michael@0 | 303 | |
michael@0 | 304 | static void vorbis_encode_psyset_setup(vorbis_info *vi,double s, |
michael@0 | 305 | const int *nn_start, |
michael@0 | 306 | const int *nn_partition, |
michael@0 | 307 | const double *nn_thresh, |
michael@0 | 308 | int block){ |
michael@0 | 309 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 310 | vorbis_info_psy *p=ci->psy_param[block]; |
michael@0 | 311 | highlevel_encode_setup *hi=&ci->hi; |
michael@0 | 312 | int is=s; |
michael@0 | 313 | |
michael@0 | 314 | if(block>=ci->psys) |
michael@0 | 315 | ci->psys=block+1; |
michael@0 | 316 | if(!p){ |
michael@0 | 317 | p=_ogg_calloc(1,sizeof(*p)); |
michael@0 | 318 | ci->psy_param[block]=p; |
michael@0 | 319 | } |
michael@0 | 320 | |
michael@0 | 321 | memcpy(p,&_psy_info_template,sizeof(*p)); |
michael@0 | 322 | p->blockflag=block>>1; |
michael@0 | 323 | |
michael@0 | 324 | if(hi->noise_normalize_p){ |
michael@0 | 325 | p->normal_p=1; |
michael@0 | 326 | p->normal_start=nn_start[is]; |
michael@0 | 327 | p->normal_partition=nn_partition[is]; |
michael@0 | 328 | p->normal_thresh=nn_thresh[is]; |
michael@0 | 329 | } |
michael@0 | 330 | |
michael@0 | 331 | return; |
michael@0 | 332 | } |
michael@0 | 333 | |
michael@0 | 334 | static void vorbis_encode_tonemask_setup(vorbis_info *vi,double s,int block, |
michael@0 | 335 | const att3 *att, |
michael@0 | 336 | const int *max, |
michael@0 | 337 | const vp_adjblock *in){ |
michael@0 | 338 | int i,is=s; |
michael@0 | 339 | double ds=s-is; |
michael@0 | 340 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 341 | vorbis_info_psy *p=ci->psy_param[block]; |
michael@0 | 342 | |
michael@0 | 343 | /* 0 and 2 are only used by bitmanagement, but there's no harm to always |
michael@0 | 344 | filling the values in here */ |
michael@0 | 345 | p->tone_masteratt[0]=att[is].att[0]*(1.-ds)+att[is+1].att[0]*ds; |
michael@0 | 346 | p->tone_masteratt[1]=att[is].att[1]*(1.-ds)+att[is+1].att[1]*ds; |
michael@0 | 347 | p->tone_masteratt[2]=att[is].att[2]*(1.-ds)+att[is+1].att[2]*ds; |
michael@0 | 348 | p->tone_centerboost=att[is].boost*(1.-ds)+att[is+1].boost*ds; |
michael@0 | 349 | p->tone_decay=att[is].decay*(1.-ds)+att[is+1].decay*ds; |
michael@0 | 350 | |
michael@0 | 351 | p->max_curve_dB=max[is]*(1.-ds)+max[is+1]*ds; |
michael@0 | 352 | |
michael@0 | 353 | for(i=0;i<P_BANDS;i++) |
michael@0 | 354 | p->toneatt[i]=in[is].block[i]*(1.-ds)+in[is+1].block[i]*ds; |
michael@0 | 355 | return; |
michael@0 | 356 | } |
michael@0 | 357 | |
michael@0 | 358 | |
michael@0 | 359 | static void vorbis_encode_compand_setup(vorbis_info *vi,double s,int block, |
michael@0 | 360 | const compandblock *in, |
michael@0 | 361 | const double *x){ |
michael@0 | 362 | int i,is=s; |
michael@0 | 363 | double ds=s-is; |
michael@0 | 364 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 365 | vorbis_info_psy *p=ci->psy_param[block]; |
michael@0 | 366 | |
michael@0 | 367 | ds=x[is]*(1.-ds)+x[is+1]*ds; |
michael@0 | 368 | is=(int)ds; |
michael@0 | 369 | ds-=is; |
michael@0 | 370 | if(ds==0 && is>0){ |
michael@0 | 371 | is--; |
michael@0 | 372 | ds=1.; |
michael@0 | 373 | } |
michael@0 | 374 | |
michael@0 | 375 | /* interpolate the compander settings */ |
michael@0 | 376 | for(i=0;i<NOISE_COMPAND_LEVELS;i++) |
michael@0 | 377 | p->noisecompand[i]=in[is].data[i]*(1.-ds)+in[is+1].data[i]*ds; |
michael@0 | 378 | return; |
michael@0 | 379 | } |
michael@0 | 380 | |
michael@0 | 381 | static void vorbis_encode_peak_setup(vorbis_info *vi,double s,int block, |
michael@0 | 382 | const int *suppress){ |
michael@0 | 383 | int is=s; |
michael@0 | 384 | double ds=s-is; |
michael@0 | 385 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 386 | vorbis_info_psy *p=ci->psy_param[block]; |
michael@0 | 387 | |
michael@0 | 388 | p->tone_abs_limit=suppress[is]*(1.-ds)+suppress[is+1]*ds; |
michael@0 | 389 | |
michael@0 | 390 | return; |
michael@0 | 391 | } |
michael@0 | 392 | |
michael@0 | 393 | static void vorbis_encode_noisebias_setup(vorbis_info *vi,double s,int block, |
michael@0 | 394 | const int *suppress, |
michael@0 | 395 | const noise3 *in, |
michael@0 | 396 | const noiseguard *guard, |
michael@0 | 397 | double userbias){ |
michael@0 | 398 | int i,is=s,j; |
michael@0 | 399 | double ds=s-is; |
michael@0 | 400 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 401 | vorbis_info_psy *p=ci->psy_param[block]; |
michael@0 | 402 | |
michael@0 | 403 | p->noisemaxsupp=suppress[is]*(1.-ds)+suppress[is+1]*ds; |
michael@0 | 404 | p->noisewindowlomin=guard[block].lo; |
michael@0 | 405 | p->noisewindowhimin=guard[block].hi; |
michael@0 | 406 | p->noisewindowfixed=guard[block].fixed; |
michael@0 | 407 | |
michael@0 | 408 | for(j=0;j<P_NOISECURVES;j++) |
michael@0 | 409 | for(i=0;i<P_BANDS;i++) |
michael@0 | 410 | p->noiseoff[j][i]=in[is].data[j][i]*(1.-ds)+in[is+1].data[j][i]*ds; |
michael@0 | 411 | |
michael@0 | 412 | /* impulse blocks may take a user specified bias to boost the |
michael@0 | 413 | nominal/high noise encoding depth */ |
michael@0 | 414 | for(j=0;j<P_NOISECURVES;j++){ |
michael@0 | 415 | float min=p->noiseoff[j][0]+6; /* the lowest it can go */ |
michael@0 | 416 | for(i=0;i<P_BANDS;i++){ |
michael@0 | 417 | p->noiseoff[j][i]+=userbias; |
michael@0 | 418 | if(p->noiseoff[j][i]<min)p->noiseoff[j][i]=min; |
michael@0 | 419 | } |
michael@0 | 420 | } |
michael@0 | 421 | |
michael@0 | 422 | return; |
michael@0 | 423 | } |
michael@0 | 424 | |
michael@0 | 425 | static void vorbis_encode_ath_setup(vorbis_info *vi,int block){ |
michael@0 | 426 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 427 | vorbis_info_psy *p=ci->psy_param[block]; |
michael@0 | 428 | |
michael@0 | 429 | p->ath_adjatt=ci->hi.ath_floating_dB; |
michael@0 | 430 | p->ath_maxatt=ci->hi.ath_absolute_dB; |
michael@0 | 431 | return; |
michael@0 | 432 | } |
michael@0 | 433 | |
michael@0 | 434 | |
michael@0 | 435 | static int book_dup_or_new(codec_setup_info *ci,const static_codebook *book){ |
michael@0 | 436 | int i; |
michael@0 | 437 | for(i=0;i<ci->books;i++) |
michael@0 | 438 | if(ci->book_param[i]==book)return(i); |
michael@0 | 439 | |
michael@0 | 440 | return(ci->books++); |
michael@0 | 441 | } |
michael@0 | 442 | |
michael@0 | 443 | static void vorbis_encode_blocksize_setup(vorbis_info *vi,double s, |
michael@0 | 444 | const int *shortb,const int *longb){ |
michael@0 | 445 | |
michael@0 | 446 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 447 | int is=s; |
michael@0 | 448 | |
michael@0 | 449 | int blockshort=shortb[is]; |
michael@0 | 450 | int blocklong=longb[is]; |
michael@0 | 451 | ci->blocksizes[0]=blockshort; |
michael@0 | 452 | ci->blocksizes[1]=blocklong; |
michael@0 | 453 | |
michael@0 | 454 | } |
michael@0 | 455 | |
michael@0 | 456 | static void vorbis_encode_residue_setup(vorbis_info *vi, |
michael@0 | 457 | int number, int block, |
michael@0 | 458 | const vorbis_residue_template *res){ |
michael@0 | 459 | |
michael@0 | 460 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 461 | int i; |
michael@0 | 462 | |
michael@0 | 463 | vorbis_info_residue0 *r=ci->residue_param[number]= |
michael@0 | 464 | _ogg_malloc(sizeof(*r)); |
michael@0 | 465 | |
michael@0 | 466 | memcpy(r,res->res,sizeof(*r)); |
michael@0 | 467 | if(ci->residues<=number)ci->residues=number+1; |
michael@0 | 468 | |
michael@0 | 469 | r->grouping=res->grouping; |
michael@0 | 470 | ci->residue_type[number]=res->res_type; |
michael@0 | 471 | |
michael@0 | 472 | /* fill in all the books */ |
michael@0 | 473 | { |
michael@0 | 474 | int booklist=0,k; |
michael@0 | 475 | |
michael@0 | 476 | if(ci->hi.managed){ |
michael@0 | 477 | for(i=0;i<r->partitions;i++) |
michael@0 | 478 | for(k=0;k<4;k++) |
michael@0 | 479 | if(res->books_base_managed->books[i][k]) |
michael@0 | 480 | r->secondstages[i]|=(1<<k); |
michael@0 | 481 | |
michael@0 | 482 | r->groupbook=book_dup_or_new(ci,res->book_aux_managed); |
michael@0 | 483 | ci->book_param[r->groupbook]=(static_codebook *)res->book_aux_managed; |
michael@0 | 484 | |
michael@0 | 485 | for(i=0;i<r->partitions;i++){ |
michael@0 | 486 | for(k=0;k<4;k++){ |
michael@0 | 487 | if(res->books_base_managed->books[i][k]){ |
michael@0 | 488 | int bookid=book_dup_or_new(ci,res->books_base_managed->books[i][k]); |
michael@0 | 489 | r->booklist[booklist++]=bookid; |
michael@0 | 490 | ci->book_param[bookid]=(static_codebook *)res->books_base_managed->books[i][k]; |
michael@0 | 491 | } |
michael@0 | 492 | } |
michael@0 | 493 | } |
michael@0 | 494 | |
michael@0 | 495 | }else{ |
michael@0 | 496 | |
michael@0 | 497 | for(i=0;i<r->partitions;i++) |
michael@0 | 498 | for(k=0;k<4;k++) |
michael@0 | 499 | if(res->books_base->books[i][k]) |
michael@0 | 500 | r->secondstages[i]|=(1<<k); |
michael@0 | 501 | |
michael@0 | 502 | r->groupbook=book_dup_or_new(ci,res->book_aux); |
michael@0 | 503 | ci->book_param[r->groupbook]=(static_codebook *)res->book_aux; |
michael@0 | 504 | |
michael@0 | 505 | for(i=0;i<r->partitions;i++){ |
michael@0 | 506 | for(k=0;k<4;k++){ |
michael@0 | 507 | if(res->books_base->books[i][k]){ |
michael@0 | 508 | int bookid=book_dup_or_new(ci,res->books_base->books[i][k]); |
michael@0 | 509 | r->booklist[booklist++]=bookid; |
michael@0 | 510 | ci->book_param[bookid]=(static_codebook *)res->books_base->books[i][k]; |
michael@0 | 511 | } |
michael@0 | 512 | } |
michael@0 | 513 | } |
michael@0 | 514 | } |
michael@0 | 515 | } |
michael@0 | 516 | |
michael@0 | 517 | /* lowpass setup/pointlimit */ |
michael@0 | 518 | { |
michael@0 | 519 | double freq=ci->hi.lowpass_kHz*1000.; |
michael@0 | 520 | vorbis_info_floor1 *f=ci->floor_param[block]; /* by convention */ |
michael@0 | 521 | double nyq=vi->rate/2.; |
michael@0 | 522 | long blocksize=ci->blocksizes[block]>>1; |
michael@0 | 523 | |
michael@0 | 524 | /* lowpass needs to be set in the floor and the residue. */ |
michael@0 | 525 | if(freq>nyq)freq=nyq; |
michael@0 | 526 | /* in the floor, the granularity can be very fine; it doesn't alter |
michael@0 | 527 | the encoding structure, only the samples used to fit the floor |
michael@0 | 528 | approximation */ |
michael@0 | 529 | f->n=freq/nyq*blocksize; |
michael@0 | 530 | |
michael@0 | 531 | /* this res may by limited by the maximum pointlimit of the mode, |
michael@0 | 532 | not the lowpass. the floor is always lowpass limited. */ |
michael@0 | 533 | switch(res->limit_type){ |
michael@0 | 534 | case 1: /* point stereo limited */ |
michael@0 | 535 | if(ci->hi.managed) |
michael@0 | 536 | freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS-1]*1000.; |
michael@0 | 537 | else |
michael@0 | 538 | freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS/2]*1000.; |
michael@0 | 539 | if(freq>nyq)freq=nyq; |
michael@0 | 540 | break; |
michael@0 | 541 | case 2: /* LFE channel; lowpass at ~ 250Hz */ |
michael@0 | 542 | freq=250; |
michael@0 | 543 | break; |
michael@0 | 544 | default: |
michael@0 | 545 | /* already set */ |
michael@0 | 546 | break; |
michael@0 | 547 | } |
michael@0 | 548 | |
michael@0 | 549 | /* in the residue, we're constrained, physically, by partition |
michael@0 | 550 | boundaries. We still lowpass 'wherever', but we have to round up |
michael@0 | 551 | here to next boundary, or the vorbis spec will round it *down* to |
michael@0 | 552 | previous boundary in encode/decode */ |
michael@0 | 553 | if(ci->residue_type[number]==2){ |
michael@0 | 554 | /* residue 2 bundles together multiple channels; used by stereo |
michael@0 | 555 | and surround. Count the channels in use */ |
michael@0 | 556 | /* Multiple maps/submaps can point to the same residue. In the case |
michael@0 | 557 | of residue 2, they all better have the same number of |
michael@0 | 558 | channels/samples. */ |
michael@0 | 559 | int j,k,ch=0; |
michael@0 | 560 | for(i=0;i<ci->maps&&ch==0;i++){ |
michael@0 | 561 | vorbis_info_mapping0 *mi=(vorbis_info_mapping0 *)ci->map_param[i]; |
michael@0 | 562 | for(j=0;j<mi->submaps && ch==0;j++) |
michael@0 | 563 | if(mi->residuesubmap[j]==number) /* we found a submap referencing theis residue backend */ |
michael@0 | 564 | for(k=0;k<vi->channels;k++) |
michael@0 | 565 | if(mi->chmuxlist[k]==j) /* this channel belongs to the submap */ |
michael@0 | 566 | ch++; |
michael@0 | 567 | } |
michael@0 | 568 | |
michael@0 | 569 | r->end=(int)((freq/nyq*blocksize*ch)/r->grouping+.9)* /* round up only if we're well past */ |
michael@0 | 570 | r->grouping; |
michael@0 | 571 | /* the blocksize and grouping may disagree at the end */ |
michael@0 | 572 | if(r->end>blocksize*ch)r->end=blocksize*ch/r->grouping*r->grouping; |
michael@0 | 573 | |
michael@0 | 574 | }else{ |
michael@0 | 575 | |
michael@0 | 576 | r->end=(int)((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */ |
michael@0 | 577 | r->grouping; |
michael@0 | 578 | /* the blocksize and grouping may disagree at the end */ |
michael@0 | 579 | if(r->end>blocksize)r->end=blocksize/r->grouping*r->grouping; |
michael@0 | 580 | |
michael@0 | 581 | } |
michael@0 | 582 | |
michael@0 | 583 | if(r->end==0)r->end=r->grouping; /* LFE channel */ |
michael@0 | 584 | |
michael@0 | 585 | } |
michael@0 | 586 | } |
michael@0 | 587 | |
michael@0 | 588 | /* we assume two maps in this encoder */ |
michael@0 | 589 | static void vorbis_encode_map_n_res_setup(vorbis_info *vi,double s, |
michael@0 | 590 | const vorbis_mapping_template *maps){ |
michael@0 | 591 | |
michael@0 | 592 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 593 | int i,j,is=s,modes=2; |
michael@0 | 594 | const vorbis_info_mapping0 *map=maps[is].map; |
michael@0 | 595 | const vorbis_info_mode *mode=_mode_template; |
michael@0 | 596 | const vorbis_residue_template *res=maps[is].res; |
michael@0 | 597 | |
michael@0 | 598 | if(ci->blocksizes[0]==ci->blocksizes[1])modes=1; |
michael@0 | 599 | |
michael@0 | 600 | for(i=0;i<modes;i++){ |
michael@0 | 601 | |
michael@0 | 602 | ci->map_param[i]=_ogg_calloc(1,sizeof(*map)); |
michael@0 | 603 | ci->mode_param[i]=_ogg_calloc(1,sizeof(*mode)); |
michael@0 | 604 | |
michael@0 | 605 | memcpy(ci->mode_param[i],mode+i,sizeof(*_mode_template)); |
michael@0 | 606 | if(i>=ci->modes)ci->modes=i+1; |
michael@0 | 607 | |
michael@0 | 608 | ci->map_type[i]=0; |
michael@0 | 609 | memcpy(ci->map_param[i],map+i,sizeof(*map)); |
michael@0 | 610 | if(i>=ci->maps)ci->maps=i+1; |
michael@0 | 611 | |
michael@0 | 612 | for(j=0;j<map[i].submaps;j++) |
michael@0 | 613 | vorbis_encode_residue_setup(vi,map[i].residuesubmap[j],i |
michael@0 | 614 | ,res+map[i].residuesubmap[j]); |
michael@0 | 615 | } |
michael@0 | 616 | } |
michael@0 | 617 | |
michael@0 | 618 | static double setting_to_approx_bitrate(vorbis_info *vi){ |
michael@0 | 619 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 620 | highlevel_encode_setup *hi=&ci->hi; |
michael@0 | 621 | ve_setup_data_template *setup=(ve_setup_data_template *)hi->setup; |
michael@0 | 622 | int is=hi->base_setting; |
michael@0 | 623 | double ds=hi->base_setting-is; |
michael@0 | 624 | int ch=vi->channels; |
michael@0 | 625 | const double *r=setup->rate_mapping; |
michael@0 | 626 | |
michael@0 | 627 | if(r==NULL) |
michael@0 | 628 | return(-1); |
michael@0 | 629 | |
michael@0 | 630 | return((r[is]*(1.-ds)+r[is+1]*ds)*ch); |
michael@0 | 631 | } |
michael@0 | 632 | |
michael@0 | 633 | static const void *get_setup_template(long ch,long srate, |
michael@0 | 634 | double req,int q_or_bitrate, |
michael@0 | 635 | double *base_setting){ |
michael@0 | 636 | int i=0,j; |
michael@0 | 637 | if(q_or_bitrate)req/=ch; |
michael@0 | 638 | |
michael@0 | 639 | while(setup_list[i]){ |
michael@0 | 640 | if(setup_list[i]->coupling_restriction==-1 || |
michael@0 | 641 | setup_list[i]->coupling_restriction==ch){ |
michael@0 | 642 | if(srate>=setup_list[i]->samplerate_min_restriction && |
michael@0 | 643 | srate<=setup_list[i]->samplerate_max_restriction){ |
michael@0 | 644 | int mappings=setup_list[i]->mappings; |
michael@0 | 645 | const double *map=(q_or_bitrate? |
michael@0 | 646 | setup_list[i]->rate_mapping: |
michael@0 | 647 | setup_list[i]->quality_mapping); |
michael@0 | 648 | |
michael@0 | 649 | /* the template matches. Does the requested quality mode |
michael@0 | 650 | fall within this template's modes? */ |
michael@0 | 651 | if(req<map[0]){++i;continue;} |
michael@0 | 652 | if(req>map[setup_list[i]->mappings]){++i;continue;} |
michael@0 | 653 | for(j=0;j<mappings;j++) |
michael@0 | 654 | if(req>=map[j] && req<map[j+1])break; |
michael@0 | 655 | /* an all-points match */ |
michael@0 | 656 | if(j==mappings) |
michael@0 | 657 | *base_setting=j-.001; |
michael@0 | 658 | else{ |
michael@0 | 659 | float low=map[j]; |
michael@0 | 660 | float high=map[j+1]; |
michael@0 | 661 | float del=(req-low)/(high-low); |
michael@0 | 662 | *base_setting=j+del; |
michael@0 | 663 | } |
michael@0 | 664 | |
michael@0 | 665 | return(setup_list[i]); |
michael@0 | 666 | } |
michael@0 | 667 | } |
michael@0 | 668 | i++; |
michael@0 | 669 | } |
michael@0 | 670 | |
michael@0 | 671 | return NULL; |
michael@0 | 672 | } |
michael@0 | 673 | |
michael@0 | 674 | /* encoders will need to use vorbis_info_init beforehand and call |
michael@0 | 675 | vorbis_info clear when all done */ |
michael@0 | 676 | |
michael@0 | 677 | /* two interfaces; this, more detailed one, and later a convenience |
michael@0 | 678 | layer on top */ |
michael@0 | 679 | |
michael@0 | 680 | /* the final setup call */ |
michael@0 | 681 | int vorbis_encode_setup_init(vorbis_info *vi){ |
michael@0 | 682 | int i,i0=0,singleblock=0; |
michael@0 | 683 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 684 | ve_setup_data_template *setup=NULL; |
michael@0 | 685 | highlevel_encode_setup *hi=&ci->hi; |
michael@0 | 686 | |
michael@0 | 687 | if(ci==NULL)return(OV_EINVAL); |
michael@0 | 688 | if(!hi->impulse_block_p)i0=1; |
michael@0 | 689 | |
michael@0 | 690 | /* too low/high an ATH floater is nonsensical, but doesn't break anything */ |
michael@0 | 691 | if(hi->ath_floating_dB>-80)hi->ath_floating_dB=-80; |
michael@0 | 692 | if(hi->ath_floating_dB<-200)hi->ath_floating_dB=-200; |
michael@0 | 693 | |
michael@0 | 694 | /* again, bound this to avoid the app shooting itself int he foot |
michael@0 | 695 | too badly */ |
michael@0 | 696 | if(hi->amplitude_track_dBpersec>0.)hi->amplitude_track_dBpersec=0.; |
michael@0 | 697 | if(hi->amplitude_track_dBpersec<-99999.)hi->amplitude_track_dBpersec=-99999.; |
michael@0 | 698 | |
michael@0 | 699 | /* get the appropriate setup template; matches the fetch in previous |
michael@0 | 700 | stages */ |
michael@0 | 701 | setup=(ve_setup_data_template *)hi->setup; |
michael@0 | 702 | if(setup==NULL)return(OV_EINVAL); |
michael@0 | 703 | |
michael@0 | 704 | hi->set_in_stone=1; |
michael@0 | 705 | /* choose block sizes from configured sizes as well as paying |
michael@0 | 706 | attention to long_block_p and short_block_p. If the configured |
michael@0 | 707 | short and long blocks are the same length, we set long_block_p |
michael@0 | 708 | and unset short_block_p */ |
michael@0 | 709 | vorbis_encode_blocksize_setup(vi,hi->base_setting, |
michael@0 | 710 | setup->blocksize_short, |
michael@0 | 711 | setup->blocksize_long); |
michael@0 | 712 | if(ci->blocksizes[0]==ci->blocksizes[1])singleblock=1; |
michael@0 | 713 | |
michael@0 | 714 | /* floor setup; choose proper floor params. Allocated on the floor |
michael@0 | 715 | stack in order; if we alloc only a single long floor, it's 0 */ |
michael@0 | 716 | for(i=0;i<setup->floor_mappings;i++) |
michael@0 | 717 | vorbis_encode_floor_setup(vi,hi->base_setting, |
michael@0 | 718 | setup->floor_books, |
michael@0 | 719 | setup->floor_params, |
michael@0 | 720 | setup->floor_mapping_list[i]); |
michael@0 | 721 | |
michael@0 | 722 | /* setup of [mostly] short block detection and stereo*/ |
michael@0 | 723 | vorbis_encode_global_psych_setup(vi,hi->trigger_setting, |
michael@0 | 724 | setup->global_params, |
michael@0 | 725 | setup->global_mapping); |
michael@0 | 726 | vorbis_encode_global_stereo(vi,hi,setup->stereo_modes); |
michael@0 | 727 | |
michael@0 | 728 | /* basic psych setup and noise normalization */ |
michael@0 | 729 | vorbis_encode_psyset_setup(vi,hi->base_setting, |
michael@0 | 730 | setup->psy_noise_normal_start[0], |
michael@0 | 731 | setup->psy_noise_normal_partition[0], |
michael@0 | 732 | setup->psy_noise_normal_thresh, |
michael@0 | 733 | 0); |
michael@0 | 734 | vorbis_encode_psyset_setup(vi,hi->base_setting, |
michael@0 | 735 | setup->psy_noise_normal_start[0], |
michael@0 | 736 | setup->psy_noise_normal_partition[0], |
michael@0 | 737 | setup->psy_noise_normal_thresh, |
michael@0 | 738 | 1); |
michael@0 | 739 | if(!singleblock){ |
michael@0 | 740 | vorbis_encode_psyset_setup(vi,hi->base_setting, |
michael@0 | 741 | setup->psy_noise_normal_start[1], |
michael@0 | 742 | setup->psy_noise_normal_partition[1], |
michael@0 | 743 | setup->psy_noise_normal_thresh, |
michael@0 | 744 | 2); |
michael@0 | 745 | vorbis_encode_psyset_setup(vi,hi->base_setting, |
michael@0 | 746 | setup->psy_noise_normal_start[1], |
michael@0 | 747 | setup->psy_noise_normal_partition[1], |
michael@0 | 748 | setup->psy_noise_normal_thresh, |
michael@0 | 749 | 3); |
michael@0 | 750 | } |
michael@0 | 751 | |
michael@0 | 752 | /* tone masking setup */ |
michael@0 | 753 | vorbis_encode_tonemask_setup(vi,hi->block[i0].tone_mask_setting,0, |
michael@0 | 754 | setup->psy_tone_masteratt, |
michael@0 | 755 | setup->psy_tone_0dB, |
michael@0 | 756 | setup->psy_tone_adj_impulse); |
michael@0 | 757 | vorbis_encode_tonemask_setup(vi,hi->block[1].tone_mask_setting,1, |
michael@0 | 758 | setup->psy_tone_masteratt, |
michael@0 | 759 | setup->psy_tone_0dB, |
michael@0 | 760 | setup->psy_tone_adj_other); |
michael@0 | 761 | if(!singleblock){ |
michael@0 | 762 | vorbis_encode_tonemask_setup(vi,hi->block[2].tone_mask_setting,2, |
michael@0 | 763 | setup->psy_tone_masteratt, |
michael@0 | 764 | setup->psy_tone_0dB, |
michael@0 | 765 | setup->psy_tone_adj_other); |
michael@0 | 766 | vorbis_encode_tonemask_setup(vi,hi->block[3].tone_mask_setting,3, |
michael@0 | 767 | setup->psy_tone_masteratt, |
michael@0 | 768 | setup->psy_tone_0dB, |
michael@0 | 769 | setup->psy_tone_adj_long); |
michael@0 | 770 | } |
michael@0 | 771 | |
michael@0 | 772 | /* noise companding setup */ |
michael@0 | 773 | vorbis_encode_compand_setup(vi,hi->block[i0].noise_compand_setting,0, |
michael@0 | 774 | setup->psy_noise_compand, |
michael@0 | 775 | setup->psy_noise_compand_short_mapping); |
michael@0 | 776 | vorbis_encode_compand_setup(vi,hi->block[1].noise_compand_setting,1, |
michael@0 | 777 | setup->psy_noise_compand, |
michael@0 | 778 | setup->psy_noise_compand_short_mapping); |
michael@0 | 779 | if(!singleblock){ |
michael@0 | 780 | vorbis_encode_compand_setup(vi,hi->block[2].noise_compand_setting,2, |
michael@0 | 781 | setup->psy_noise_compand, |
michael@0 | 782 | setup->psy_noise_compand_long_mapping); |
michael@0 | 783 | vorbis_encode_compand_setup(vi,hi->block[3].noise_compand_setting,3, |
michael@0 | 784 | setup->psy_noise_compand, |
michael@0 | 785 | setup->psy_noise_compand_long_mapping); |
michael@0 | 786 | } |
michael@0 | 787 | |
michael@0 | 788 | /* peak guarding setup */ |
michael@0 | 789 | vorbis_encode_peak_setup(vi,hi->block[i0].tone_peaklimit_setting,0, |
michael@0 | 790 | setup->psy_tone_dBsuppress); |
michael@0 | 791 | vorbis_encode_peak_setup(vi,hi->block[1].tone_peaklimit_setting,1, |
michael@0 | 792 | setup->psy_tone_dBsuppress); |
michael@0 | 793 | if(!singleblock){ |
michael@0 | 794 | vorbis_encode_peak_setup(vi,hi->block[2].tone_peaklimit_setting,2, |
michael@0 | 795 | setup->psy_tone_dBsuppress); |
michael@0 | 796 | vorbis_encode_peak_setup(vi,hi->block[3].tone_peaklimit_setting,3, |
michael@0 | 797 | setup->psy_tone_dBsuppress); |
michael@0 | 798 | } |
michael@0 | 799 | |
michael@0 | 800 | /* noise bias setup */ |
michael@0 | 801 | vorbis_encode_noisebias_setup(vi,hi->block[i0].noise_bias_setting,0, |
michael@0 | 802 | setup->psy_noise_dBsuppress, |
michael@0 | 803 | setup->psy_noise_bias_impulse, |
michael@0 | 804 | setup->psy_noiseguards, |
michael@0 | 805 | (i0==0?hi->impulse_noisetune:0.)); |
michael@0 | 806 | vorbis_encode_noisebias_setup(vi,hi->block[1].noise_bias_setting,1, |
michael@0 | 807 | setup->psy_noise_dBsuppress, |
michael@0 | 808 | setup->psy_noise_bias_padding, |
michael@0 | 809 | setup->psy_noiseguards,0.); |
michael@0 | 810 | if(!singleblock){ |
michael@0 | 811 | vorbis_encode_noisebias_setup(vi,hi->block[2].noise_bias_setting,2, |
michael@0 | 812 | setup->psy_noise_dBsuppress, |
michael@0 | 813 | setup->psy_noise_bias_trans, |
michael@0 | 814 | setup->psy_noiseguards,0.); |
michael@0 | 815 | vorbis_encode_noisebias_setup(vi,hi->block[3].noise_bias_setting,3, |
michael@0 | 816 | setup->psy_noise_dBsuppress, |
michael@0 | 817 | setup->psy_noise_bias_long, |
michael@0 | 818 | setup->psy_noiseguards,0.); |
michael@0 | 819 | } |
michael@0 | 820 | |
michael@0 | 821 | vorbis_encode_ath_setup(vi,0); |
michael@0 | 822 | vorbis_encode_ath_setup(vi,1); |
michael@0 | 823 | if(!singleblock){ |
michael@0 | 824 | vorbis_encode_ath_setup(vi,2); |
michael@0 | 825 | vorbis_encode_ath_setup(vi,3); |
michael@0 | 826 | } |
michael@0 | 827 | |
michael@0 | 828 | vorbis_encode_map_n_res_setup(vi,hi->base_setting,setup->maps); |
michael@0 | 829 | |
michael@0 | 830 | /* set bitrate readonlies and management */ |
michael@0 | 831 | if(hi->bitrate_av>0) |
michael@0 | 832 | vi->bitrate_nominal=hi->bitrate_av; |
michael@0 | 833 | else{ |
michael@0 | 834 | vi->bitrate_nominal=setting_to_approx_bitrate(vi); |
michael@0 | 835 | } |
michael@0 | 836 | |
michael@0 | 837 | vi->bitrate_lower=hi->bitrate_min; |
michael@0 | 838 | vi->bitrate_upper=hi->bitrate_max; |
michael@0 | 839 | if(hi->bitrate_av) |
michael@0 | 840 | vi->bitrate_window=(double)hi->bitrate_reservoir/hi->bitrate_av; |
michael@0 | 841 | else |
michael@0 | 842 | vi->bitrate_window=0.; |
michael@0 | 843 | |
michael@0 | 844 | if(hi->managed){ |
michael@0 | 845 | ci->bi.avg_rate=hi->bitrate_av; |
michael@0 | 846 | ci->bi.min_rate=hi->bitrate_min; |
michael@0 | 847 | ci->bi.max_rate=hi->bitrate_max; |
michael@0 | 848 | |
michael@0 | 849 | ci->bi.reservoir_bits=hi->bitrate_reservoir; |
michael@0 | 850 | ci->bi.reservoir_bias= |
michael@0 | 851 | hi->bitrate_reservoir_bias; |
michael@0 | 852 | |
michael@0 | 853 | ci->bi.slew_damp=hi->bitrate_av_damp; |
michael@0 | 854 | |
michael@0 | 855 | } |
michael@0 | 856 | |
michael@0 | 857 | return(0); |
michael@0 | 858 | |
michael@0 | 859 | } |
michael@0 | 860 | |
michael@0 | 861 | static void vorbis_encode_setup_setting(vorbis_info *vi, |
michael@0 | 862 | long channels, |
michael@0 | 863 | long rate){ |
michael@0 | 864 | int i,is; |
michael@0 | 865 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 866 | highlevel_encode_setup *hi=&ci->hi; |
michael@0 | 867 | const ve_setup_data_template *setup=hi->setup; |
michael@0 | 868 | double ds; |
michael@0 | 869 | |
michael@0 | 870 | vi->version=0; |
michael@0 | 871 | vi->channels=channels; |
michael@0 | 872 | vi->rate=rate; |
michael@0 | 873 | |
michael@0 | 874 | hi->impulse_block_p=1; |
michael@0 | 875 | hi->noise_normalize_p=1; |
michael@0 | 876 | |
michael@0 | 877 | is=hi->base_setting; |
michael@0 | 878 | ds=hi->base_setting-is; |
michael@0 | 879 | |
michael@0 | 880 | hi->stereo_point_setting=hi->base_setting; |
michael@0 | 881 | |
michael@0 | 882 | if(!hi->lowpass_altered) |
michael@0 | 883 | hi->lowpass_kHz= |
michael@0 | 884 | setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds; |
michael@0 | 885 | |
michael@0 | 886 | hi->ath_floating_dB=setup->psy_ath_float[is]*(1.-ds)+ |
michael@0 | 887 | setup->psy_ath_float[is+1]*ds; |
michael@0 | 888 | hi->ath_absolute_dB=setup->psy_ath_abs[is]*(1.-ds)+ |
michael@0 | 889 | setup->psy_ath_abs[is+1]*ds; |
michael@0 | 890 | |
michael@0 | 891 | hi->amplitude_track_dBpersec=-6.; |
michael@0 | 892 | hi->trigger_setting=hi->base_setting; |
michael@0 | 893 | |
michael@0 | 894 | for(i=0;i<4;i++){ |
michael@0 | 895 | hi->block[i].tone_mask_setting=hi->base_setting; |
michael@0 | 896 | hi->block[i].tone_peaklimit_setting=hi->base_setting; |
michael@0 | 897 | hi->block[i].noise_bias_setting=hi->base_setting; |
michael@0 | 898 | hi->block[i].noise_compand_setting=hi->base_setting; |
michael@0 | 899 | } |
michael@0 | 900 | } |
michael@0 | 901 | |
michael@0 | 902 | int vorbis_encode_setup_vbr(vorbis_info *vi, |
michael@0 | 903 | long channels, |
michael@0 | 904 | long rate, |
michael@0 | 905 | float quality){ |
michael@0 | 906 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 907 | highlevel_encode_setup *hi=&ci->hi; |
michael@0 | 908 | |
michael@0 | 909 | quality+=.0000001; |
michael@0 | 910 | if(quality>=1.)quality=.9999; |
michael@0 | 911 | |
michael@0 | 912 | hi->req=quality; |
michael@0 | 913 | hi->setup=get_setup_template(channels,rate,quality,0,&hi->base_setting); |
michael@0 | 914 | if(!hi->setup)return OV_EIMPL; |
michael@0 | 915 | |
michael@0 | 916 | vorbis_encode_setup_setting(vi,channels,rate); |
michael@0 | 917 | hi->managed=0; |
michael@0 | 918 | hi->coupling_p=1; |
michael@0 | 919 | |
michael@0 | 920 | return 0; |
michael@0 | 921 | } |
michael@0 | 922 | |
michael@0 | 923 | int vorbis_encode_init_vbr(vorbis_info *vi, |
michael@0 | 924 | long channels, |
michael@0 | 925 | long rate, |
michael@0 | 926 | |
michael@0 | 927 | float base_quality /* 0. to 1. */ |
michael@0 | 928 | ){ |
michael@0 | 929 | int ret=0; |
michael@0 | 930 | |
michael@0 | 931 | ret=vorbis_encode_setup_vbr(vi,channels,rate,base_quality); |
michael@0 | 932 | |
michael@0 | 933 | if(ret){ |
michael@0 | 934 | vorbis_info_clear(vi); |
michael@0 | 935 | return ret; |
michael@0 | 936 | } |
michael@0 | 937 | ret=vorbis_encode_setup_init(vi); |
michael@0 | 938 | if(ret) |
michael@0 | 939 | vorbis_info_clear(vi); |
michael@0 | 940 | return(ret); |
michael@0 | 941 | } |
michael@0 | 942 | |
michael@0 | 943 | int vorbis_encode_setup_managed(vorbis_info *vi, |
michael@0 | 944 | long channels, |
michael@0 | 945 | long rate, |
michael@0 | 946 | |
michael@0 | 947 | long max_bitrate, |
michael@0 | 948 | long nominal_bitrate, |
michael@0 | 949 | long min_bitrate){ |
michael@0 | 950 | |
michael@0 | 951 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 952 | highlevel_encode_setup *hi=&ci->hi; |
michael@0 | 953 | double tnominal=nominal_bitrate; |
michael@0 | 954 | |
michael@0 | 955 | if(nominal_bitrate<=0.){ |
michael@0 | 956 | if(max_bitrate>0.){ |
michael@0 | 957 | if(min_bitrate>0.) |
michael@0 | 958 | nominal_bitrate=(max_bitrate+min_bitrate)*.5; |
michael@0 | 959 | else |
michael@0 | 960 | nominal_bitrate=max_bitrate*.875; |
michael@0 | 961 | }else{ |
michael@0 | 962 | if(min_bitrate>0.){ |
michael@0 | 963 | nominal_bitrate=min_bitrate; |
michael@0 | 964 | }else{ |
michael@0 | 965 | return(OV_EINVAL); |
michael@0 | 966 | } |
michael@0 | 967 | } |
michael@0 | 968 | } |
michael@0 | 969 | |
michael@0 | 970 | hi->req=nominal_bitrate; |
michael@0 | 971 | hi->setup=get_setup_template(channels,rate,nominal_bitrate,1,&hi->base_setting); |
michael@0 | 972 | if(!hi->setup)return OV_EIMPL; |
michael@0 | 973 | |
michael@0 | 974 | vorbis_encode_setup_setting(vi,channels,rate); |
michael@0 | 975 | |
michael@0 | 976 | /* initialize management with sane defaults */ |
michael@0 | 977 | hi->coupling_p=1; |
michael@0 | 978 | hi->managed=1; |
michael@0 | 979 | hi->bitrate_min=min_bitrate; |
michael@0 | 980 | hi->bitrate_max=max_bitrate; |
michael@0 | 981 | hi->bitrate_av=tnominal; |
michael@0 | 982 | hi->bitrate_av_damp=1.5f; /* full range in no less than 1.5 second */ |
michael@0 | 983 | hi->bitrate_reservoir=nominal_bitrate*2; |
michael@0 | 984 | hi->bitrate_reservoir_bias=.1; /* bias toward hoarding bits */ |
michael@0 | 985 | |
michael@0 | 986 | return(0); |
michael@0 | 987 | |
michael@0 | 988 | } |
michael@0 | 989 | |
michael@0 | 990 | int vorbis_encode_init(vorbis_info *vi, |
michael@0 | 991 | long channels, |
michael@0 | 992 | long rate, |
michael@0 | 993 | |
michael@0 | 994 | long max_bitrate, |
michael@0 | 995 | long nominal_bitrate, |
michael@0 | 996 | long min_bitrate){ |
michael@0 | 997 | |
michael@0 | 998 | int ret=vorbis_encode_setup_managed(vi,channels,rate, |
michael@0 | 999 | max_bitrate, |
michael@0 | 1000 | nominal_bitrate, |
michael@0 | 1001 | min_bitrate); |
michael@0 | 1002 | if(ret){ |
michael@0 | 1003 | vorbis_info_clear(vi); |
michael@0 | 1004 | return(ret); |
michael@0 | 1005 | } |
michael@0 | 1006 | |
michael@0 | 1007 | ret=vorbis_encode_setup_init(vi); |
michael@0 | 1008 | if(ret) |
michael@0 | 1009 | vorbis_info_clear(vi); |
michael@0 | 1010 | return(ret); |
michael@0 | 1011 | } |
michael@0 | 1012 | |
michael@0 | 1013 | int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ |
michael@0 | 1014 | if(vi){ |
michael@0 | 1015 | codec_setup_info *ci=vi->codec_setup; |
michael@0 | 1016 | highlevel_encode_setup *hi=&ci->hi; |
michael@0 | 1017 | int setp=(number&0xf); /* a read request has a low nibble of 0 */ |
michael@0 | 1018 | |
michael@0 | 1019 | if(setp && hi->set_in_stone)return(OV_EINVAL); |
michael@0 | 1020 | |
michael@0 | 1021 | switch(number){ |
michael@0 | 1022 | |
michael@0 | 1023 | /* now deprecated *****************/ |
michael@0 | 1024 | case OV_ECTL_RATEMANAGE_GET: |
michael@0 | 1025 | { |
michael@0 | 1026 | |
michael@0 | 1027 | struct ovectl_ratemanage_arg *ai= |
michael@0 | 1028 | (struct ovectl_ratemanage_arg *)arg; |
michael@0 | 1029 | |
michael@0 | 1030 | ai->management_active=hi->managed; |
michael@0 | 1031 | ai->bitrate_hard_window=ai->bitrate_av_window= |
michael@0 | 1032 | (double)hi->bitrate_reservoir/vi->rate; |
michael@0 | 1033 | ai->bitrate_av_window_center=1.; |
michael@0 | 1034 | ai->bitrate_hard_min=hi->bitrate_min; |
michael@0 | 1035 | ai->bitrate_hard_max=hi->bitrate_max; |
michael@0 | 1036 | ai->bitrate_av_lo=hi->bitrate_av; |
michael@0 | 1037 | ai->bitrate_av_hi=hi->bitrate_av; |
michael@0 | 1038 | |
michael@0 | 1039 | } |
michael@0 | 1040 | return(0); |
michael@0 | 1041 | |
michael@0 | 1042 | /* now deprecated *****************/ |
michael@0 | 1043 | case OV_ECTL_RATEMANAGE_SET: |
michael@0 | 1044 | { |
michael@0 | 1045 | struct ovectl_ratemanage_arg *ai= |
michael@0 | 1046 | (struct ovectl_ratemanage_arg *)arg; |
michael@0 | 1047 | if(ai==NULL){ |
michael@0 | 1048 | hi->managed=0; |
michael@0 | 1049 | }else{ |
michael@0 | 1050 | hi->managed=ai->management_active; |
michael@0 | 1051 | vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_AVG,arg); |
michael@0 | 1052 | vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_HARD,arg); |
michael@0 | 1053 | } |
michael@0 | 1054 | } |
michael@0 | 1055 | return 0; |
michael@0 | 1056 | |
michael@0 | 1057 | /* now deprecated *****************/ |
michael@0 | 1058 | case OV_ECTL_RATEMANAGE_AVG: |
michael@0 | 1059 | { |
michael@0 | 1060 | struct ovectl_ratemanage_arg *ai= |
michael@0 | 1061 | (struct ovectl_ratemanage_arg *)arg; |
michael@0 | 1062 | if(ai==NULL){ |
michael@0 | 1063 | hi->bitrate_av=0; |
michael@0 | 1064 | }else{ |
michael@0 | 1065 | hi->bitrate_av=(ai->bitrate_av_lo+ai->bitrate_av_hi)*.5; |
michael@0 | 1066 | } |
michael@0 | 1067 | } |
michael@0 | 1068 | return(0); |
michael@0 | 1069 | /* now deprecated *****************/ |
michael@0 | 1070 | case OV_ECTL_RATEMANAGE_HARD: |
michael@0 | 1071 | { |
michael@0 | 1072 | struct ovectl_ratemanage_arg *ai= |
michael@0 | 1073 | (struct ovectl_ratemanage_arg *)arg; |
michael@0 | 1074 | if(ai==NULL){ |
michael@0 | 1075 | hi->bitrate_min=0; |
michael@0 | 1076 | hi->bitrate_max=0; |
michael@0 | 1077 | }else{ |
michael@0 | 1078 | hi->bitrate_min=ai->bitrate_hard_min; |
michael@0 | 1079 | hi->bitrate_max=ai->bitrate_hard_max; |
michael@0 | 1080 | hi->bitrate_reservoir=ai->bitrate_hard_window* |
michael@0 | 1081 | (hi->bitrate_max+hi->bitrate_min)*.5; |
michael@0 | 1082 | } |
michael@0 | 1083 | if(hi->bitrate_reservoir<128.) |
michael@0 | 1084 | hi->bitrate_reservoir=128.; |
michael@0 | 1085 | } |
michael@0 | 1086 | return(0); |
michael@0 | 1087 | |
michael@0 | 1088 | /* replacement ratemanage interface */ |
michael@0 | 1089 | case OV_ECTL_RATEMANAGE2_GET: |
michael@0 | 1090 | { |
michael@0 | 1091 | struct ovectl_ratemanage2_arg *ai= |
michael@0 | 1092 | (struct ovectl_ratemanage2_arg *)arg; |
michael@0 | 1093 | if(ai==NULL)return OV_EINVAL; |
michael@0 | 1094 | |
michael@0 | 1095 | ai->management_active=hi->managed; |
michael@0 | 1096 | ai->bitrate_limit_min_kbps=hi->bitrate_min/1000; |
michael@0 | 1097 | ai->bitrate_limit_max_kbps=hi->bitrate_max/1000; |
michael@0 | 1098 | ai->bitrate_average_kbps=hi->bitrate_av/1000; |
michael@0 | 1099 | ai->bitrate_average_damping=hi->bitrate_av_damp; |
michael@0 | 1100 | ai->bitrate_limit_reservoir_bits=hi->bitrate_reservoir; |
michael@0 | 1101 | ai->bitrate_limit_reservoir_bias=hi->bitrate_reservoir_bias; |
michael@0 | 1102 | } |
michael@0 | 1103 | return (0); |
michael@0 | 1104 | case OV_ECTL_RATEMANAGE2_SET: |
michael@0 | 1105 | { |
michael@0 | 1106 | struct ovectl_ratemanage2_arg *ai= |
michael@0 | 1107 | (struct ovectl_ratemanage2_arg *)arg; |
michael@0 | 1108 | if(ai==NULL){ |
michael@0 | 1109 | hi->managed=0; |
michael@0 | 1110 | }else{ |
michael@0 | 1111 | /* sanity check; only catch invariant violations */ |
michael@0 | 1112 | if(ai->bitrate_limit_min_kbps>0 && |
michael@0 | 1113 | ai->bitrate_average_kbps>0 && |
michael@0 | 1114 | ai->bitrate_limit_min_kbps>ai->bitrate_average_kbps) |
michael@0 | 1115 | return OV_EINVAL; |
michael@0 | 1116 | |
michael@0 | 1117 | if(ai->bitrate_limit_max_kbps>0 && |
michael@0 | 1118 | ai->bitrate_average_kbps>0 && |
michael@0 | 1119 | ai->bitrate_limit_max_kbps<ai->bitrate_average_kbps) |
michael@0 | 1120 | return OV_EINVAL; |
michael@0 | 1121 | |
michael@0 | 1122 | if(ai->bitrate_limit_min_kbps>0 && |
michael@0 | 1123 | ai->bitrate_limit_max_kbps>0 && |
michael@0 | 1124 | ai->bitrate_limit_min_kbps>ai->bitrate_limit_max_kbps) |
michael@0 | 1125 | return OV_EINVAL; |
michael@0 | 1126 | |
michael@0 | 1127 | if(ai->bitrate_average_damping <= 0.) |
michael@0 | 1128 | return OV_EINVAL; |
michael@0 | 1129 | |
michael@0 | 1130 | if(ai->bitrate_limit_reservoir_bits < 0) |
michael@0 | 1131 | return OV_EINVAL; |
michael@0 | 1132 | |
michael@0 | 1133 | if(ai->bitrate_limit_reservoir_bias < 0.) |
michael@0 | 1134 | return OV_EINVAL; |
michael@0 | 1135 | |
michael@0 | 1136 | if(ai->bitrate_limit_reservoir_bias > 1.) |
michael@0 | 1137 | return OV_EINVAL; |
michael@0 | 1138 | |
michael@0 | 1139 | hi->managed=ai->management_active; |
michael@0 | 1140 | hi->bitrate_min=ai->bitrate_limit_min_kbps * 1000; |
michael@0 | 1141 | hi->bitrate_max=ai->bitrate_limit_max_kbps * 1000; |
michael@0 | 1142 | hi->bitrate_av=ai->bitrate_average_kbps * 1000; |
michael@0 | 1143 | hi->bitrate_av_damp=ai->bitrate_average_damping; |
michael@0 | 1144 | hi->bitrate_reservoir=ai->bitrate_limit_reservoir_bits; |
michael@0 | 1145 | hi->bitrate_reservoir_bias=ai->bitrate_limit_reservoir_bias; |
michael@0 | 1146 | } |
michael@0 | 1147 | } |
michael@0 | 1148 | return 0; |
michael@0 | 1149 | |
michael@0 | 1150 | case OV_ECTL_LOWPASS_GET: |
michael@0 | 1151 | { |
michael@0 | 1152 | double *farg=(double *)arg; |
michael@0 | 1153 | *farg=hi->lowpass_kHz; |
michael@0 | 1154 | } |
michael@0 | 1155 | return(0); |
michael@0 | 1156 | case OV_ECTL_LOWPASS_SET: |
michael@0 | 1157 | { |
michael@0 | 1158 | double *farg=(double *)arg; |
michael@0 | 1159 | hi->lowpass_kHz=*farg; |
michael@0 | 1160 | |
michael@0 | 1161 | if(hi->lowpass_kHz<2.)hi->lowpass_kHz=2.; |
michael@0 | 1162 | if(hi->lowpass_kHz>99.)hi->lowpass_kHz=99.; |
michael@0 | 1163 | hi->lowpass_altered=1; |
michael@0 | 1164 | } |
michael@0 | 1165 | return(0); |
michael@0 | 1166 | case OV_ECTL_IBLOCK_GET: |
michael@0 | 1167 | { |
michael@0 | 1168 | double *farg=(double *)arg; |
michael@0 | 1169 | *farg=hi->impulse_noisetune; |
michael@0 | 1170 | } |
michael@0 | 1171 | return(0); |
michael@0 | 1172 | case OV_ECTL_IBLOCK_SET: |
michael@0 | 1173 | { |
michael@0 | 1174 | double *farg=(double *)arg; |
michael@0 | 1175 | hi->impulse_noisetune=*farg; |
michael@0 | 1176 | |
michael@0 | 1177 | if(hi->impulse_noisetune>0.)hi->impulse_noisetune=0.; |
michael@0 | 1178 | if(hi->impulse_noisetune<-15.)hi->impulse_noisetune=-15.; |
michael@0 | 1179 | } |
michael@0 | 1180 | return(0); |
michael@0 | 1181 | case OV_ECTL_COUPLING_GET: |
michael@0 | 1182 | { |
michael@0 | 1183 | int *iarg=(int *)arg; |
michael@0 | 1184 | *iarg=hi->coupling_p; |
michael@0 | 1185 | } |
michael@0 | 1186 | return(0); |
michael@0 | 1187 | case OV_ECTL_COUPLING_SET: |
michael@0 | 1188 | { |
michael@0 | 1189 | const void *new_template; |
michael@0 | 1190 | double new_base=0.; |
michael@0 | 1191 | int *iarg=(int *)arg; |
michael@0 | 1192 | hi->coupling_p=((*iarg)!=0); |
michael@0 | 1193 | |
michael@0 | 1194 | /* Fetching a new template can alter the base_setting, which |
michael@0 | 1195 | many other parameters are based on. Right now, the only |
michael@0 | 1196 | parameter drawn from the base_setting that can be altered |
michael@0 | 1197 | by an encctl is the lowpass, so that is explictly flagged |
michael@0 | 1198 | to not be overwritten when we fetch a new template and |
michael@0 | 1199 | recompute the dependant settings */ |
michael@0 | 1200 | new_template = get_setup_template(hi->coupling_p?vi->channels:-1, |
michael@0 | 1201 | vi->rate, |
michael@0 | 1202 | hi->req, |
michael@0 | 1203 | hi->managed, |
michael@0 | 1204 | &new_base); |
michael@0 | 1205 | if(!hi->setup)return OV_EIMPL; |
michael@0 | 1206 | hi->setup=new_template; |
michael@0 | 1207 | hi->base_setting=new_base; |
michael@0 | 1208 | vorbis_encode_setup_setting(vi,vi->channels,vi->rate); |
michael@0 | 1209 | } |
michael@0 | 1210 | return(0); |
michael@0 | 1211 | } |
michael@0 | 1212 | return(OV_EIMPL); |
michael@0 | 1213 | } |
michael@0 | 1214 | return(OV_EINVAL); |
michael@0 | 1215 | } |