vrshoot
diff libs/vorbis/vorbisenc.c @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/vorbis/vorbisenc.c Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,1215 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * 1.7 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.8 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.9 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.10 + * * 1.11 + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 * 1.12 + * by the Xiph.Org Foundation http://www.xiph.org/ * 1.13 + * * 1.14 + ******************************************************************** 1.15 + 1.16 + function: simple programmatic interface for encoder mode setup 1.17 + last mod: $Id: vorbisenc.c 17028 2010-03-25 05:22:15Z xiphmont $ 1.18 + 1.19 + ********************************************************************/ 1.20 + 1.21 +#include <stdlib.h> 1.22 +#include <string.h> 1.23 +#include <math.h> 1.24 + 1.25 +#include "vorbis/codec.h" 1.26 +#include "vorbis/vorbisenc.h" 1.27 + 1.28 +#include "codec_internal.h" 1.29 + 1.30 +#include "os.h" 1.31 +#include "misc.h" 1.32 + 1.33 +/* careful with this; it's using static array sizing to make managing 1.34 + all the modes a little less annoying. If we use a residue backend 1.35 + with > 12 partition types, or a different division of iteration, 1.36 + this needs to be updated. */ 1.37 +typedef struct { 1.38 + const static_codebook *books[12][4]; 1.39 +} static_bookblock; 1.40 + 1.41 +typedef struct { 1.42 + int res_type; 1.43 + int limit_type; /* 0 lowpass limited, 1 point stereo limited */ 1.44 + int grouping; 1.45 + const vorbis_info_residue0 *res; 1.46 + const static_codebook *book_aux; 1.47 + const static_codebook *book_aux_managed; 1.48 + const static_bookblock *books_base; 1.49 + const static_bookblock *books_base_managed; 1.50 +} vorbis_residue_template; 1.51 + 1.52 +typedef struct { 1.53 + const vorbis_info_mapping0 *map; 1.54 + const vorbis_residue_template *res; 1.55 +} vorbis_mapping_template; 1.56 + 1.57 +typedef struct vp_adjblock{ 1.58 + int block[P_BANDS]; 1.59 +} vp_adjblock; 1.60 + 1.61 +typedef struct { 1.62 + int data[NOISE_COMPAND_LEVELS]; 1.63 +} compandblock; 1.64 + 1.65 +/* high level configuration information for setting things up 1.66 + step-by-step with the detailed vorbis_encode_ctl interface. 1.67 + There's a fair amount of redundancy such that interactive setup 1.68 + does not directly deal with any vorbis_info or codec_setup_info 1.69 + initialization; it's all stored (until full init) in this highlevel 1.70 + setup, then flushed out to the real codec setup structs later. */ 1.71 + 1.72 +typedef struct { 1.73 + int att[P_NOISECURVES]; 1.74 + float boost; 1.75 + float decay; 1.76 +} att3; 1.77 +typedef struct { int data[P_NOISECURVES]; } adj3; 1.78 + 1.79 +typedef struct { 1.80 + int pre[PACKETBLOBS]; 1.81 + int post[PACKETBLOBS]; 1.82 + float kHz[PACKETBLOBS]; 1.83 + float lowpasskHz[PACKETBLOBS]; 1.84 +} adj_stereo; 1.85 + 1.86 +typedef struct { 1.87 + int lo; 1.88 + int hi; 1.89 + int fixed; 1.90 +} noiseguard; 1.91 +typedef struct { 1.92 + int data[P_NOISECURVES][17]; 1.93 +} noise3; 1.94 + 1.95 +typedef struct { 1.96 + int mappings; 1.97 + const double *rate_mapping; 1.98 + const double *quality_mapping; 1.99 + int coupling_restriction; 1.100 + long samplerate_min_restriction; 1.101 + long samplerate_max_restriction; 1.102 + 1.103 + 1.104 + const int *blocksize_short; 1.105 + const int *blocksize_long; 1.106 + 1.107 + const att3 *psy_tone_masteratt; 1.108 + const int *psy_tone_0dB; 1.109 + const int *psy_tone_dBsuppress; 1.110 + 1.111 + const vp_adjblock *psy_tone_adj_impulse; 1.112 + const vp_adjblock *psy_tone_adj_long; 1.113 + const vp_adjblock *psy_tone_adj_other; 1.114 + 1.115 + const noiseguard *psy_noiseguards; 1.116 + const noise3 *psy_noise_bias_impulse; 1.117 + const noise3 *psy_noise_bias_padding; 1.118 + const noise3 *psy_noise_bias_trans; 1.119 + const noise3 *psy_noise_bias_long; 1.120 + const int *psy_noise_dBsuppress; 1.121 + 1.122 + const compandblock *psy_noise_compand; 1.123 + const double *psy_noise_compand_short_mapping; 1.124 + const double *psy_noise_compand_long_mapping; 1.125 + 1.126 + const int *psy_noise_normal_start[2]; 1.127 + const int *psy_noise_normal_partition[2]; 1.128 + const double *psy_noise_normal_thresh; 1.129 + 1.130 + const int *psy_ath_float; 1.131 + const int *psy_ath_abs; 1.132 + 1.133 + const double *psy_lowpass; 1.134 + 1.135 + const vorbis_info_psy_global *global_params; 1.136 + const double *global_mapping; 1.137 + const adj_stereo *stereo_modes; 1.138 + 1.139 + const static_codebook *const *const *const floor_books; 1.140 + const vorbis_info_floor1 *floor_params; 1.141 + const int floor_mappings; 1.142 + const int **floor_mapping_list; 1.143 + 1.144 + const vorbis_mapping_template *maps; 1.145 +} ve_setup_data_template; 1.146 + 1.147 +/* a few static coder conventions */ 1.148 +static const vorbis_info_mode _mode_template[2]={ 1.149 + {0,0,0,0}, 1.150 + {1,0,0,1} 1.151 +}; 1.152 + 1.153 +static const vorbis_info_mapping0 _map_nominal[2]={ 1.154 + {1, {0,0}, {0}, {0}, 1,{0},{1}}, 1.155 + {1, {0,0}, {1}, {1}, 1,{0},{1}} 1.156 +}; 1.157 + 1.158 +#include "modes/setup_44.h" 1.159 +#include "modes/setup_44u.h" 1.160 +#include "modes/setup_44p51.h" 1.161 +#include "modes/setup_32.h" 1.162 +#include "modes/setup_8.h" 1.163 +#include "modes/setup_11.h" 1.164 +#include "modes/setup_16.h" 1.165 +#include "modes/setup_22.h" 1.166 +#include "modes/setup_X.h" 1.167 + 1.168 +static const ve_setup_data_template *const setup_list[]={ 1.169 + &ve_setup_44_stereo, 1.170 + &ve_setup_44_51, 1.171 + &ve_setup_44_uncoupled, 1.172 + 1.173 + &ve_setup_32_stereo, 1.174 + &ve_setup_32_uncoupled, 1.175 + 1.176 + &ve_setup_22_stereo, 1.177 + &ve_setup_22_uncoupled, 1.178 + &ve_setup_16_stereo, 1.179 + &ve_setup_16_uncoupled, 1.180 + 1.181 + &ve_setup_11_stereo, 1.182 + &ve_setup_11_uncoupled, 1.183 + &ve_setup_8_stereo, 1.184 + &ve_setup_8_uncoupled, 1.185 + 1.186 + &ve_setup_X_stereo, 1.187 + &ve_setup_X_uncoupled, 1.188 + &ve_setup_XX_stereo, 1.189 + &ve_setup_XX_uncoupled, 1.190 + 0 1.191 +}; 1.192 + 1.193 +static void vorbis_encode_floor_setup(vorbis_info *vi,int s, 1.194 + const static_codebook *const *const *const books, 1.195 + const vorbis_info_floor1 *in, 1.196 + const int *x){ 1.197 + int i,k,is=s; 1.198 + vorbis_info_floor1 *f=_ogg_calloc(1,sizeof(*f)); 1.199 + codec_setup_info *ci=vi->codec_setup; 1.200 + 1.201 + memcpy(f,in+x[is],sizeof(*f)); 1.202 + 1.203 + /* books */ 1.204 + { 1.205 + int partitions=f->partitions; 1.206 + int maxclass=-1; 1.207 + int maxbook=-1; 1.208 + for(i=0;i<partitions;i++) 1.209 + if(f->partitionclass[i]>maxclass)maxclass=f->partitionclass[i]; 1.210 + for(i=0;i<=maxclass;i++){ 1.211 + if(f->class_book[i]>maxbook)maxbook=f->class_book[i]; 1.212 + f->class_book[i]+=ci->books; 1.213 + for(k=0;k<(1<<f->class_subs[i]);k++){ 1.214 + if(f->class_subbook[i][k]>maxbook)maxbook=f->class_subbook[i][k]; 1.215 + if(f->class_subbook[i][k]>=0)f->class_subbook[i][k]+=ci->books; 1.216 + } 1.217 + } 1.218 + 1.219 + for(i=0;i<=maxbook;i++) 1.220 + ci->book_param[ci->books++]=(static_codebook *)books[x[is]][i]; 1.221 + } 1.222 + 1.223 + /* for now, we're only using floor 1 */ 1.224 + ci->floor_type[ci->floors]=1; 1.225 + ci->floor_param[ci->floors]=f; 1.226 + ci->floors++; 1.227 + 1.228 + return; 1.229 +} 1.230 + 1.231 +static void vorbis_encode_global_psych_setup(vorbis_info *vi,double s, 1.232 + const vorbis_info_psy_global *in, 1.233 + const double *x){ 1.234 + int i,is=s; 1.235 + double ds=s-is; 1.236 + codec_setup_info *ci=vi->codec_setup; 1.237 + vorbis_info_psy_global *g=&ci->psy_g_param; 1.238 + 1.239 + memcpy(g,in+(int)x[is],sizeof(*g)); 1.240 + 1.241 + ds=x[is]*(1.-ds)+x[is+1]*ds; 1.242 + is=(int)ds; 1.243 + ds-=is; 1.244 + if(ds==0 && is>0){ 1.245 + is--; 1.246 + ds=1.; 1.247 + } 1.248 + 1.249 + /* interpolate the trigger threshholds */ 1.250 + for(i=0;i<4;i++){ 1.251 + g->preecho_thresh[i]=in[is].preecho_thresh[i]*(1.-ds)+in[is+1].preecho_thresh[i]*ds; 1.252 + g->postecho_thresh[i]=in[is].postecho_thresh[i]*(1.-ds)+in[is+1].postecho_thresh[i]*ds; 1.253 + } 1.254 + g->ampmax_att_per_sec=ci->hi.amplitude_track_dBpersec; 1.255 + return; 1.256 +} 1.257 + 1.258 +static void vorbis_encode_global_stereo(vorbis_info *vi, 1.259 + const highlevel_encode_setup *const hi, 1.260 + const adj_stereo *p){ 1.261 + float s=hi->stereo_point_setting; 1.262 + int i,is=s; 1.263 + double ds=s-is; 1.264 + codec_setup_info *ci=vi->codec_setup; 1.265 + vorbis_info_psy_global *g=&ci->psy_g_param; 1.266 + 1.267 + if(p){ 1.268 + memcpy(g->coupling_prepointamp,p[is].pre,sizeof(*p[is].pre)*PACKETBLOBS); 1.269 + memcpy(g->coupling_postpointamp,p[is].post,sizeof(*p[is].post)*PACKETBLOBS); 1.270 + 1.271 + if(hi->managed){ 1.272 + /* interpolate the kHz threshholds */ 1.273 + for(i=0;i<PACKETBLOBS;i++){ 1.274 + float kHz=p[is].kHz[i]*(1.-ds)+p[is+1].kHz[i]*ds; 1.275 + g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; 1.276 + g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; 1.277 + g->coupling_pkHz[i]=kHz; 1.278 + 1.279 + kHz=p[is].lowpasskHz[i]*(1.-ds)+p[is+1].lowpasskHz[i]*ds; 1.280 + g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; 1.281 + g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; 1.282 + 1.283 + } 1.284 + }else{ 1.285 + float kHz=p[is].kHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].kHz[PACKETBLOBS/2]*ds; 1.286 + for(i=0;i<PACKETBLOBS;i++){ 1.287 + g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; 1.288 + g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; 1.289 + g->coupling_pkHz[i]=kHz; 1.290 + } 1.291 + 1.292 + kHz=p[is].lowpasskHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].lowpasskHz[PACKETBLOBS/2]*ds; 1.293 + for(i=0;i<PACKETBLOBS;i++){ 1.294 + g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; 1.295 + g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; 1.296 + } 1.297 + } 1.298 + }else{ 1.299 + for(i=0;i<PACKETBLOBS;i++){ 1.300 + g->sliding_lowpass[0][i]=ci->blocksizes[0]; 1.301 + g->sliding_lowpass[1][i]=ci->blocksizes[1]; 1.302 + } 1.303 + } 1.304 + return; 1.305 +} 1.306 + 1.307 +static void vorbis_encode_psyset_setup(vorbis_info *vi,double s, 1.308 + const int *nn_start, 1.309 + const int *nn_partition, 1.310 + const double *nn_thresh, 1.311 + int block){ 1.312 + codec_setup_info *ci=vi->codec_setup; 1.313 + vorbis_info_psy *p=ci->psy_param[block]; 1.314 + highlevel_encode_setup *hi=&ci->hi; 1.315 + int is=s; 1.316 + 1.317 + if(block>=ci->psys) 1.318 + ci->psys=block+1; 1.319 + if(!p){ 1.320 + p=_ogg_calloc(1,sizeof(*p)); 1.321 + ci->psy_param[block]=p; 1.322 + } 1.323 + 1.324 + memcpy(p,&_psy_info_template,sizeof(*p)); 1.325 + p->blockflag=block>>1; 1.326 + 1.327 + if(hi->noise_normalize_p){ 1.328 + p->normal_p=1; 1.329 + p->normal_start=nn_start[is]; 1.330 + p->normal_partition=nn_partition[is]; 1.331 + p->normal_thresh=nn_thresh[is]; 1.332 + } 1.333 + 1.334 + return; 1.335 +} 1.336 + 1.337 +static void vorbis_encode_tonemask_setup(vorbis_info *vi,double s,int block, 1.338 + const att3 *att, 1.339 + const int *max, 1.340 + const vp_adjblock *in){ 1.341 + int i,is=s; 1.342 + double ds=s-is; 1.343 + codec_setup_info *ci=vi->codec_setup; 1.344 + vorbis_info_psy *p=ci->psy_param[block]; 1.345 + 1.346 + /* 0 and 2 are only used by bitmanagement, but there's no harm to always 1.347 + filling the values in here */ 1.348 + p->tone_masteratt[0]=att[is].att[0]*(1.-ds)+att[is+1].att[0]*ds; 1.349 + p->tone_masteratt[1]=att[is].att[1]*(1.-ds)+att[is+1].att[1]*ds; 1.350 + p->tone_masteratt[2]=att[is].att[2]*(1.-ds)+att[is+1].att[2]*ds; 1.351 + p->tone_centerboost=att[is].boost*(1.-ds)+att[is+1].boost*ds; 1.352 + p->tone_decay=att[is].decay*(1.-ds)+att[is+1].decay*ds; 1.353 + 1.354 + p->max_curve_dB=max[is]*(1.-ds)+max[is+1]*ds; 1.355 + 1.356 + for(i=0;i<P_BANDS;i++) 1.357 + p->toneatt[i]=in[is].block[i]*(1.-ds)+in[is+1].block[i]*ds; 1.358 + return; 1.359 +} 1.360 + 1.361 + 1.362 +static void vorbis_encode_compand_setup(vorbis_info *vi,double s,int block, 1.363 + const compandblock *in, 1.364 + const double *x){ 1.365 + int i,is=s; 1.366 + double ds=s-is; 1.367 + codec_setup_info *ci=vi->codec_setup; 1.368 + vorbis_info_psy *p=ci->psy_param[block]; 1.369 + 1.370 + ds=x[is]*(1.-ds)+x[is+1]*ds; 1.371 + is=(int)ds; 1.372 + ds-=is; 1.373 + if(ds==0 && is>0){ 1.374 + is--; 1.375 + ds=1.; 1.376 + } 1.377 + 1.378 + /* interpolate the compander settings */ 1.379 + for(i=0;i<NOISE_COMPAND_LEVELS;i++) 1.380 + p->noisecompand[i]=in[is].data[i]*(1.-ds)+in[is+1].data[i]*ds; 1.381 + return; 1.382 +} 1.383 + 1.384 +static void vorbis_encode_peak_setup(vorbis_info *vi,double s,int block, 1.385 + const int *suppress){ 1.386 + int is=s; 1.387 + double ds=s-is; 1.388 + codec_setup_info *ci=vi->codec_setup; 1.389 + vorbis_info_psy *p=ci->psy_param[block]; 1.390 + 1.391 + p->tone_abs_limit=suppress[is]*(1.-ds)+suppress[is+1]*ds; 1.392 + 1.393 + return; 1.394 +} 1.395 + 1.396 +static void vorbis_encode_noisebias_setup(vorbis_info *vi,double s,int block, 1.397 + const int *suppress, 1.398 + const noise3 *in, 1.399 + const noiseguard *guard, 1.400 + double userbias){ 1.401 + int i,is=s,j; 1.402 + double ds=s-is; 1.403 + codec_setup_info *ci=vi->codec_setup; 1.404 + vorbis_info_psy *p=ci->psy_param[block]; 1.405 + 1.406 + p->noisemaxsupp=suppress[is]*(1.-ds)+suppress[is+1]*ds; 1.407 + p->noisewindowlomin=guard[block].lo; 1.408 + p->noisewindowhimin=guard[block].hi; 1.409 + p->noisewindowfixed=guard[block].fixed; 1.410 + 1.411 + for(j=0;j<P_NOISECURVES;j++) 1.412 + for(i=0;i<P_BANDS;i++) 1.413 + p->noiseoff[j][i]=in[is].data[j][i]*(1.-ds)+in[is+1].data[j][i]*ds; 1.414 + 1.415 + /* impulse blocks may take a user specified bias to boost the 1.416 + nominal/high noise encoding depth */ 1.417 + for(j=0;j<P_NOISECURVES;j++){ 1.418 + float min=p->noiseoff[j][0]+6; /* the lowest it can go */ 1.419 + for(i=0;i<P_BANDS;i++){ 1.420 + p->noiseoff[j][i]+=userbias; 1.421 + if(p->noiseoff[j][i]<min)p->noiseoff[j][i]=min; 1.422 + } 1.423 + } 1.424 + 1.425 + return; 1.426 +} 1.427 + 1.428 +static void vorbis_encode_ath_setup(vorbis_info *vi,int block){ 1.429 + codec_setup_info *ci=vi->codec_setup; 1.430 + vorbis_info_psy *p=ci->psy_param[block]; 1.431 + 1.432 + p->ath_adjatt=ci->hi.ath_floating_dB; 1.433 + p->ath_maxatt=ci->hi.ath_absolute_dB; 1.434 + return; 1.435 +} 1.436 + 1.437 + 1.438 +static int book_dup_or_new(codec_setup_info *ci,const static_codebook *book){ 1.439 + int i; 1.440 + for(i=0;i<ci->books;i++) 1.441 + if(ci->book_param[i]==book)return(i); 1.442 + 1.443 + return(ci->books++); 1.444 +} 1.445 + 1.446 +static void vorbis_encode_blocksize_setup(vorbis_info *vi,double s, 1.447 + const int *shortb,const int *longb){ 1.448 + 1.449 + codec_setup_info *ci=vi->codec_setup; 1.450 + int is=s; 1.451 + 1.452 + int blockshort=shortb[is]; 1.453 + int blocklong=longb[is]; 1.454 + ci->blocksizes[0]=blockshort; 1.455 + ci->blocksizes[1]=blocklong; 1.456 + 1.457 +} 1.458 + 1.459 +static void vorbis_encode_residue_setup(vorbis_info *vi, 1.460 + int number, int block, 1.461 + const vorbis_residue_template *res){ 1.462 + 1.463 + codec_setup_info *ci=vi->codec_setup; 1.464 + int i; 1.465 + 1.466 + vorbis_info_residue0 *r=ci->residue_param[number]= 1.467 + _ogg_malloc(sizeof(*r)); 1.468 + 1.469 + memcpy(r,res->res,sizeof(*r)); 1.470 + if(ci->residues<=number)ci->residues=number+1; 1.471 + 1.472 + r->grouping=res->grouping; 1.473 + ci->residue_type[number]=res->res_type; 1.474 + 1.475 + /* fill in all the books */ 1.476 + { 1.477 + int booklist=0,k; 1.478 + 1.479 + if(ci->hi.managed){ 1.480 + for(i=0;i<r->partitions;i++) 1.481 + for(k=0;k<4;k++) 1.482 + if(res->books_base_managed->books[i][k]) 1.483 + r->secondstages[i]|=(1<<k); 1.484 + 1.485 + r->groupbook=book_dup_or_new(ci,res->book_aux_managed); 1.486 + ci->book_param[r->groupbook]=(static_codebook *)res->book_aux_managed; 1.487 + 1.488 + for(i=0;i<r->partitions;i++){ 1.489 + for(k=0;k<4;k++){ 1.490 + if(res->books_base_managed->books[i][k]){ 1.491 + int bookid=book_dup_or_new(ci,res->books_base_managed->books[i][k]); 1.492 + r->booklist[booklist++]=bookid; 1.493 + ci->book_param[bookid]=(static_codebook *)res->books_base_managed->books[i][k]; 1.494 + } 1.495 + } 1.496 + } 1.497 + 1.498 + }else{ 1.499 + 1.500 + for(i=0;i<r->partitions;i++) 1.501 + for(k=0;k<4;k++) 1.502 + if(res->books_base->books[i][k]) 1.503 + r->secondstages[i]|=(1<<k); 1.504 + 1.505 + r->groupbook=book_dup_or_new(ci,res->book_aux); 1.506 + ci->book_param[r->groupbook]=(static_codebook *)res->book_aux; 1.507 + 1.508 + for(i=0;i<r->partitions;i++){ 1.509 + for(k=0;k<4;k++){ 1.510 + if(res->books_base->books[i][k]){ 1.511 + int bookid=book_dup_or_new(ci,res->books_base->books[i][k]); 1.512 + r->booklist[booklist++]=bookid; 1.513 + ci->book_param[bookid]=(static_codebook *)res->books_base->books[i][k]; 1.514 + } 1.515 + } 1.516 + } 1.517 + } 1.518 + } 1.519 + 1.520 + /* lowpass setup/pointlimit */ 1.521 + { 1.522 + double freq=ci->hi.lowpass_kHz*1000.; 1.523 + vorbis_info_floor1 *f=ci->floor_param[block]; /* by convention */ 1.524 + double nyq=vi->rate/2.; 1.525 + long blocksize=ci->blocksizes[block]>>1; 1.526 + 1.527 + /* lowpass needs to be set in the floor and the residue. */ 1.528 + if(freq>nyq)freq=nyq; 1.529 + /* in the floor, the granularity can be very fine; it doesn't alter 1.530 + the encoding structure, only the samples used to fit the floor 1.531 + approximation */ 1.532 + f->n=freq/nyq*blocksize; 1.533 + 1.534 + /* this res may by limited by the maximum pointlimit of the mode, 1.535 + not the lowpass. the floor is always lowpass limited. */ 1.536 + switch(res->limit_type){ 1.537 + case 1: /* point stereo limited */ 1.538 + if(ci->hi.managed) 1.539 + freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS-1]*1000.; 1.540 + else 1.541 + freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS/2]*1000.; 1.542 + if(freq>nyq)freq=nyq; 1.543 + break; 1.544 + case 2: /* LFE channel; lowpass at ~ 250Hz */ 1.545 + freq=250; 1.546 + break; 1.547 + default: 1.548 + /* already set */ 1.549 + break; 1.550 + } 1.551 + 1.552 + /* in the residue, we're constrained, physically, by partition 1.553 + boundaries. We still lowpass 'wherever', but we have to round up 1.554 + here to next boundary, or the vorbis spec will round it *down* to 1.555 + previous boundary in encode/decode */ 1.556 + if(ci->residue_type[number]==2){ 1.557 + /* residue 2 bundles together multiple channels; used by stereo 1.558 + and surround. Count the channels in use */ 1.559 + /* Multiple maps/submaps can point to the same residue. In the case 1.560 + of residue 2, they all better have the same number of 1.561 + channels/samples. */ 1.562 + int j,k,ch=0; 1.563 + for(i=0;i<ci->maps&&ch==0;i++){ 1.564 + vorbis_info_mapping0 *mi=(vorbis_info_mapping0 *)ci->map_param[i]; 1.565 + for(j=0;j<mi->submaps && ch==0;j++) 1.566 + if(mi->residuesubmap[j]==number) /* we found a submap referencing theis residue backend */ 1.567 + for(k=0;k<vi->channels;k++) 1.568 + if(mi->chmuxlist[k]==j) /* this channel belongs to the submap */ 1.569 + ch++; 1.570 + } 1.571 + 1.572 + r->end=(int)((freq/nyq*blocksize*ch)/r->grouping+.9)* /* round up only if we're well past */ 1.573 + r->grouping; 1.574 + /* the blocksize and grouping may disagree at the end */ 1.575 + if(r->end>blocksize*ch)r->end=blocksize*ch/r->grouping*r->grouping; 1.576 + 1.577 + }else{ 1.578 + 1.579 + r->end=(int)((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */ 1.580 + r->grouping; 1.581 + /* the blocksize and grouping may disagree at the end */ 1.582 + if(r->end>blocksize)r->end=blocksize/r->grouping*r->grouping; 1.583 + 1.584 + } 1.585 + 1.586 + if(r->end==0)r->end=r->grouping; /* LFE channel */ 1.587 + 1.588 + } 1.589 +} 1.590 + 1.591 +/* we assume two maps in this encoder */ 1.592 +static void vorbis_encode_map_n_res_setup(vorbis_info *vi,double s, 1.593 + const vorbis_mapping_template *maps){ 1.594 + 1.595 + codec_setup_info *ci=vi->codec_setup; 1.596 + int i,j,is=s,modes=2; 1.597 + const vorbis_info_mapping0 *map=maps[is].map; 1.598 + const vorbis_info_mode *mode=_mode_template; 1.599 + const vorbis_residue_template *res=maps[is].res; 1.600 + 1.601 + if(ci->blocksizes[0]==ci->blocksizes[1])modes=1; 1.602 + 1.603 + for(i=0;i<modes;i++){ 1.604 + 1.605 + ci->map_param[i]=_ogg_calloc(1,sizeof(*map)); 1.606 + ci->mode_param[i]=_ogg_calloc(1,sizeof(*mode)); 1.607 + 1.608 + memcpy(ci->mode_param[i],mode+i,sizeof(*_mode_template)); 1.609 + if(i>=ci->modes)ci->modes=i+1; 1.610 + 1.611 + ci->map_type[i]=0; 1.612 + memcpy(ci->map_param[i],map+i,sizeof(*map)); 1.613 + if(i>=ci->maps)ci->maps=i+1; 1.614 + 1.615 + for(j=0;j<map[i].submaps;j++) 1.616 + vorbis_encode_residue_setup(vi,map[i].residuesubmap[j],i 1.617 + ,res+map[i].residuesubmap[j]); 1.618 + } 1.619 +} 1.620 + 1.621 +static double setting_to_approx_bitrate(vorbis_info *vi){ 1.622 + codec_setup_info *ci=vi->codec_setup; 1.623 + highlevel_encode_setup *hi=&ci->hi; 1.624 + ve_setup_data_template *setup=(ve_setup_data_template *)hi->setup; 1.625 + int is=hi->base_setting; 1.626 + double ds=hi->base_setting-is; 1.627 + int ch=vi->channels; 1.628 + const double *r=setup->rate_mapping; 1.629 + 1.630 + if(r==NULL) 1.631 + return(-1); 1.632 + 1.633 + return((r[is]*(1.-ds)+r[is+1]*ds)*ch); 1.634 +} 1.635 + 1.636 +static const void *get_setup_template(long ch,long srate, 1.637 + double req,int q_or_bitrate, 1.638 + double *base_setting){ 1.639 + int i=0,j; 1.640 + if(q_or_bitrate)req/=ch; 1.641 + 1.642 + while(setup_list[i]){ 1.643 + if(setup_list[i]->coupling_restriction==-1 || 1.644 + setup_list[i]->coupling_restriction==ch){ 1.645 + if(srate>=setup_list[i]->samplerate_min_restriction && 1.646 + srate<=setup_list[i]->samplerate_max_restriction){ 1.647 + int mappings=setup_list[i]->mappings; 1.648 + const double *map=(q_or_bitrate? 1.649 + setup_list[i]->rate_mapping: 1.650 + setup_list[i]->quality_mapping); 1.651 + 1.652 + /* the template matches. Does the requested quality mode 1.653 + fall within this template's modes? */ 1.654 + if(req<map[0]){++i;continue;} 1.655 + if(req>map[setup_list[i]->mappings]){++i;continue;} 1.656 + for(j=0;j<mappings;j++) 1.657 + if(req>=map[j] && req<map[j+1])break; 1.658 + /* an all-points match */ 1.659 + if(j==mappings) 1.660 + *base_setting=j-.001; 1.661 + else{ 1.662 + float low=map[j]; 1.663 + float high=map[j+1]; 1.664 + float del=(req-low)/(high-low); 1.665 + *base_setting=j+del; 1.666 + } 1.667 + 1.668 + return(setup_list[i]); 1.669 + } 1.670 + } 1.671 + i++; 1.672 + } 1.673 + 1.674 + return NULL; 1.675 +} 1.676 + 1.677 +/* encoders will need to use vorbis_info_init beforehand and call 1.678 + vorbis_info clear when all done */ 1.679 + 1.680 +/* two interfaces; this, more detailed one, and later a convenience 1.681 + layer on top */ 1.682 + 1.683 +/* the final setup call */ 1.684 +int vorbis_encode_setup_init(vorbis_info *vi){ 1.685 + int i,i0=0,singleblock=0; 1.686 + codec_setup_info *ci=vi->codec_setup; 1.687 + ve_setup_data_template *setup=NULL; 1.688 + highlevel_encode_setup *hi=&ci->hi; 1.689 + 1.690 + if(ci==NULL)return(OV_EINVAL); 1.691 + if(!hi->impulse_block_p)i0=1; 1.692 + 1.693 + /* too low/high an ATH floater is nonsensical, but doesn't break anything */ 1.694 + if(hi->ath_floating_dB>-80)hi->ath_floating_dB=-80; 1.695 + if(hi->ath_floating_dB<-200)hi->ath_floating_dB=-200; 1.696 + 1.697 + /* again, bound this to avoid the app shooting itself int he foot 1.698 + too badly */ 1.699 + if(hi->amplitude_track_dBpersec>0.)hi->amplitude_track_dBpersec=0.; 1.700 + if(hi->amplitude_track_dBpersec<-99999.)hi->amplitude_track_dBpersec=-99999.; 1.701 + 1.702 + /* get the appropriate setup template; matches the fetch in previous 1.703 + stages */ 1.704 + setup=(ve_setup_data_template *)hi->setup; 1.705 + if(setup==NULL)return(OV_EINVAL); 1.706 + 1.707 + hi->set_in_stone=1; 1.708 + /* choose block sizes from configured sizes as well as paying 1.709 + attention to long_block_p and short_block_p. If the configured 1.710 + short and long blocks are the same length, we set long_block_p 1.711 + and unset short_block_p */ 1.712 + vorbis_encode_blocksize_setup(vi,hi->base_setting, 1.713 + setup->blocksize_short, 1.714 + setup->blocksize_long); 1.715 + if(ci->blocksizes[0]==ci->blocksizes[1])singleblock=1; 1.716 + 1.717 + /* floor setup; choose proper floor params. Allocated on the floor 1.718 + stack in order; if we alloc only a single long floor, it's 0 */ 1.719 + for(i=0;i<setup->floor_mappings;i++) 1.720 + vorbis_encode_floor_setup(vi,hi->base_setting, 1.721 + setup->floor_books, 1.722 + setup->floor_params, 1.723 + setup->floor_mapping_list[i]); 1.724 + 1.725 + /* setup of [mostly] short block detection and stereo*/ 1.726 + vorbis_encode_global_psych_setup(vi,hi->trigger_setting, 1.727 + setup->global_params, 1.728 + setup->global_mapping); 1.729 + vorbis_encode_global_stereo(vi,hi,setup->stereo_modes); 1.730 + 1.731 + /* basic psych setup and noise normalization */ 1.732 + vorbis_encode_psyset_setup(vi,hi->base_setting, 1.733 + setup->psy_noise_normal_start[0], 1.734 + setup->psy_noise_normal_partition[0], 1.735 + setup->psy_noise_normal_thresh, 1.736 + 0); 1.737 + vorbis_encode_psyset_setup(vi,hi->base_setting, 1.738 + setup->psy_noise_normal_start[0], 1.739 + setup->psy_noise_normal_partition[0], 1.740 + setup->psy_noise_normal_thresh, 1.741 + 1); 1.742 + if(!singleblock){ 1.743 + vorbis_encode_psyset_setup(vi,hi->base_setting, 1.744 + setup->psy_noise_normal_start[1], 1.745 + setup->psy_noise_normal_partition[1], 1.746 + setup->psy_noise_normal_thresh, 1.747 + 2); 1.748 + vorbis_encode_psyset_setup(vi,hi->base_setting, 1.749 + setup->psy_noise_normal_start[1], 1.750 + setup->psy_noise_normal_partition[1], 1.751 + setup->psy_noise_normal_thresh, 1.752 + 3); 1.753 + } 1.754 + 1.755 + /* tone masking setup */ 1.756 + vorbis_encode_tonemask_setup(vi,hi->block[i0].tone_mask_setting,0, 1.757 + setup->psy_tone_masteratt, 1.758 + setup->psy_tone_0dB, 1.759 + setup->psy_tone_adj_impulse); 1.760 + vorbis_encode_tonemask_setup(vi,hi->block[1].tone_mask_setting,1, 1.761 + setup->psy_tone_masteratt, 1.762 + setup->psy_tone_0dB, 1.763 + setup->psy_tone_adj_other); 1.764 + if(!singleblock){ 1.765 + vorbis_encode_tonemask_setup(vi,hi->block[2].tone_mask_setting,2, 1.766 + setup->psy_tone_masteratt, 1.767 + setup->psy_tone_0dB, 1.768 + setup->psy_tone_adj_other); 1.769 + vorbis_encode_tonemask_setup(vi,hi->block[3].tone_mask_setting,3, 1.770 + setup->psy_tone_masteratt, 1.771 + setup->psy_tone_0dB, 1.772 + setup->psy_tone_adj_long); 1.773 + } 1.774 + 1.775 + /* noise companding setup */ 1.776 + vorbis_encode_compand_setup(vi,hi->block[i0].noise_compand_setting,0, 1.777 + setup->psy_noise_compand, 1.778 + setup->psy_noise_compand_short_mapping); 1.779 + vorbis_encode_compand_setup(vi,hi->block[1].noise_compand_setting,1, 1.780 + setup->psy_noise_compand, 1.781 + setup->psy_noise_compand_short_mapping); 1.782 + if(!singleblock){ 1.783 + vorbis_encode_compand_setup(vi,hi->block[2].noise_compand_setting,2, 1.784 + setup->psy_noise_compand, 1.785 + setup->psy_noise_compand_long_mapping); 1.786 + vorbis_encode_compand_setup(vi,hi->block[3].noise_compand_setting,3, 1.787 + setup->psy_noise_compand, 1.788 + setup->psy_noise_compand_long_mapping); 1.789 + } 1.790 + 1.791 + /* peak guarding setup */ 1.792 + vorbis_encode_peak_setup(vi,hi->block[i0].tone_peaklimit_setting,0, 1.793 + setup->psy_tone_dBsuppress); 1.794 + vorbis_encode_peak_setup(vi,hi->block[1].tone_peaklimit_setting,1, 1.795 + setup->psy_tone_dBsuppress); 1.796 + if(!singleblock){ 1.797 + vorbis_encode_peak_setup(vi,hi->block[2].tone_peaklimit_setting,2, 1.798 + setup->psy_tone_dBsuppress); 1.799 + vorbis_encode_peak_setup(vi,hi->block[3].tone_peaklimit_setting,3, 1.800 + setup->psy_tone_dBsuppress); 1.801 + } 1.802 + 1.803 + /* noise bias setup */ 1.804 + vorbis_encode_noisebias_setup(vi,hi->block[i0].noise_bias_setting,0, 1.805 + setup->psy_noise_dBsuppress, 1.806 + setup->psy_noise_bias_impulse, 1.807 + setup->psy_noiseguards, 1.808 + (i0==0?hi->impulse_noisetune:0.)); 1.809 + vorbis_encode_noisebias_setup(vi,hi->block[1].noise_bias_setting,1, 1.810 + setup->psy_noise_dBsuppress, 1.811 + setup->psy_noise_bias_padding, 1.812 + setup->psy_noiseguards,0.); 1.813 + if(!singleblock){ 1.814 + vorbis_encode_noisebias_setup(vi,hi->block[2].noise_bias_setting,2, 1.815 + setup->psy_noise_dBsuppress, 1.816 + setup->psy_noise_bias_trans, 1.817 + setup->psy_noiseguards,0.); 1.818 + vorbis_encode_noisebias_setup(vi,hi->block[3].noise_bias_setting,3, 1.819 + setup->psy_noise_dBsuppress, 1.820 + setup->psy_noise_bias_long, 1.821 + setup->psy_noiseguards,0.); 1.822 + } 1.823 + 1.824 + vorbis_encode_ath_setup(vi,0); 1.825 + vorbis_encode_ath_setup(vi,1); 1.826 + if(!singleblock){ 1.827 + vorbis_encode_ath_setup(vi,2); 1.828 + vorbis_encode_ath_setup(vi,3); 1.829 + } 1.830 + 1.831 + vorbis_encode_map_n_res_setup(vi,hi->base_setting,setup->maps); 1.832 + 1.833 + /* set bitrate readonlies and management */ 1.834 + if(hi->bitrate_av>0) 1.835 + vi->bitrate_nominal=hi->bitrate_av; 1.836 + else{ 1.837 + vi->bitrate_nominal=setting_to_approx_bitrate(vi); 1.838 + } 1.839 + 1.840 + vi->bitrate_lower=hi->bitrate_min; 1.841 + vi->bitrate_upper=hi->bitrate_max; 1.842 + if(hi->bitrate_av) 1.843 + vi->bitrate_window=(double)hi->bitrate_reservoir/hi->bitrate_av; 1.844 + else 1.845 + vi->bitrate_window=0.; 1.846 + 1.847 + if(hi->managed){ 1.848 + ci->bi.avg_rate=hi->bitrate_av; 1.849 + ci->bi.min_rate=hi->bitrate_min; 1.850 + ci->bi.max_rate=hi->bitrate_max; 1.851 + 1.852 + ci->bi.reservoir_bits=hi->bitrate_reservoir; 1.853 + ci->bi.reservoir_bias= 1.854 + hi->bitrate_reservoir_bias; 1.855 + 1.856 + ci->bi.slew_damp=hi->bitrate_av_damp; 1.857 + 1.858 + } 1.859 + 1.860 + return(0); 1.861 + 1.862 +} 1.863 + 1.864 +static void vorbis_encode_setup_setting(vorbis_info *vi, 1.865 + long channels, 1.866 + long rate){ 1.867 + int i,is; 1.868 + codec_setup_info *ci=vi->codec_setup; 1.869 + highlevel_encode_setup *hi=&ci->hi; 1.870 + const ve_setup_data_template *setup=hi->setup; 1.871 + double ds; 1.872 + 1.873 + vi->version=0; 1.874 + vi->channels=channels; 1.875 + vi->rate=rate; 1.876 + 1.877 + hi->impulse_block_p=1; 1.878 + hi->noise_normalize_p=1; 1.879 + 1.880 + is=hi->base_setting; 1.881 + ds=hi->base_setting-is; 1.882 + 1.883 + hi->stereo_point_setting=hi->base_setting; 1.884 + 1.885 + if(!hi->lowpass_altered) 1.886 + hi->lowpass_kHz= 1.887 + setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds; 1.888 + 1.889 + hi->ath_floating_dB=setup->psy_ath_float[is]*(1.-ds)+ 1.890 + setup->psy_ath_float[is+1]*ds; 1.891 + hi->ath_absolute_dB=setup->psy_ath_abs[is]*(1.-ds)+ 1.892 + setup->psy_ath_abs[is+1]*ds; 1.893 + 1.894 + hi->amplitude_track_dBpersec=-6.; 1.895 + hi->trigger_setting=hi->base_setting; 1.896 + 1.897 + for(i=0;i<4;i++){ 1.898 + hi->block[i].tone_mask_setting=hi->base_setting; 1.899 + hi->block[i].tone_peaklimit_setting=hi->base_setting; 1.900 + hi->block[i].noise_bias_setting=hi->base_setting; 1.901 + hi->block[i].noise_compand_setting=hi->base_setting; 1.902 + } 1.903 +} 1.904 + 1.905 +int vorbis_encode_setup_vbr(vorbis_info *vi, 1.906 + long channels, 1.907 + long rate, 1.908 + float quality){ 1.909 + codec_setup_info *ci=vi->codec_setup; 1.910 + highlevel_encode_setup *hi=&ci->hi; 1.911 + 1.912 + quality+=.0000001; 1.913 + if(quality>=1.)quality=.9999; 1.914 + 1.915 + hi->req=quality; 1.916 + hi->setup=get_setup_template(channels,rate,quality,0,&hi->base_setting); 1.917 + if(!hi->setup)return OV_EIMPL; 1.918 + 1.919 + vorbis_encode_setup_setting(vi,channels,rate); 1.920 + hi->managed=0; 1.921 + hi->coupling_p=1; 1.922 + 1.923 + return 0; 1.924 +} 1.925 + 1.926 +int vorbis_encode_init_vbr(vorbis_info *vi, 1.927 + long channels, 1.928 + long rate, 1.929 + 1.930 + float base_quality /* 0. to 1. */ 1.931 + ){ 1.932 + int ret=0; 1.933 + 1.934 + ret=vorbis_encode_setup_vbr(vi,channels,rate,base_quality); 1.935 + 1.936 + if(ret){ 1.937 + vorbis_info_clear(vi); 1.938 + return ret; 1.939 + } 1.940 + ret=vorbis_encode_setup_init(vi); 1.941 + if(ret) 1.942 + vorbis_info_clear(vi); 1.943 + return(ret); 1.944 +} 1.945 + 1.946 +int vorbis_encode_setup_managed(vorbis_info *vi, 1.947 + long channels, 1.948 + long rate, 1.949 + 1.950 + long max_bitrate, 1.951 + long nominal_bitrate, 1.952 + long min_bitrate){ 1.953 + 1.954 + codec_setup_info *ci=vi->codec_setup; 1.955 + highlevel_encode_setup *hi=&ci->hi; 1.956 + double tnominal=nominal_bitrate; 1.957 + 1.958 + if(nominal_bitrate<=0.){ 1.959 + if(max_bitrate>0.){ 1.960 + if(min_bitrate>0.) 1.961 + nominal_bitrate=(max_bitrate+min_bitrate)*.5; 1.962 + else 1.963 + nominal_bitrate=max_bitrate*.875; 1.964 + }else{ 1.965 + if(min_bitrate>0.){ 1.966 + nominal_bitrate=min_bitrate; 1.967 + }else{ 1.968 + return(OV_EINVAL); 1.969 + } 1.970 + } 1.971 + } 1.972 + 1.973 + hi->req=nominal_bitrate; 1.974 + hi->setup=get_setup_template(channels,rate,nominal_bitrate,1,&hi->base_setting); 1.975 + if(!hi->setup)return OV_EIMPL; 1.976 + 1.977 + vorbis_encode_setup_setting(vi,channels,rate); 1.978 + 1.979 + /* initialize management with sane defaults */ 1.980 + hi->coupling_p=1; 1.981 + hi->managed=1; 1.982 + hi->bitrate_min=min_bitrate; 1.983 + hi->bitrate_max=max_bitrate; 1.984 + hi->bitrate_av=tnominal; 1.985 + hi->bitrate_av_damp=1.5f; /* full range in no less than 1.5 second */ 1.986 + hi->bitrate_reservoir=nominal_bitrate*2; 1.987 + hi->bitrate_reservoir_bias=.1; /* bias toward hoarding bits */ 1.988 + 1.989 + return(0); 1.990 + 1.991 +} 1.992 + 1.993 +int vorbis_encode_init(vorbis_info *vi, 1.994 + long channels, 1.995 + long rate, 1.996 + 1.997 + long max_bitrate, 1.998 + long nominal_bitrate, 1.999 + long min_bitrate){ 1.1000 + 1.1001 + int ret=vorbis_encode_setup_managed(vi,channels,rate, 1.1002 + max_bitrate, 1.1003 + nominal_bitrate, 1.1004 + min_bitrate); 1.1005 + if(ret){ 1.1006 + vorbis_info_clear(vi); 1.1007 + return(ret); 1.1008 + } 1.1009 + 1.1010 + ret=vorbis_encode_setup_init(vi); 1.1011 + if(ret) 1.1012 + vorbis_info_clear(vi); 1.1013 + return(ret); 1.1014 +} 1.1015 + 1.1016 +int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ 1.1017 + if(vi){ 1.1018 + codec_setup_info *ci=vi->codec_setup; 1.1019 + highlevel_encode_setup *hi=&ci->hi; 1.1020 + int setp=(number&0xf); /* a read request has a low nibble of 0 */ 1.1021 + 1.1022 + if(setp && hi->set_in_stone)return(OV_EINVAL); 1.1023 + 1.1024 + switch(number){ 1.1025 + 1.1026 + /* now deprecated *****************/ 1.1027 + case OV_ECTL_RATEMANAGE_GET: 1.1028 + { 1.1029 + 1.1030 + struct ovectl_ratemanage_arg *ai= 1.1031 + (struct ovectl_ratemanage_arg *)arg; 1.1032 + 1.1033 + ai->management_active=hi->managed; 1.1034 + ai->bitrate_hard_window=ai->bitrate_av_window= 1.1035 + (double)hi->bitrate_reservoir/vi->rate; 1.1036 + ai->bitrate_av_window_center=1.; 1.1037 + ai->bitrate_hard_min=hi->bitrate_min; 1.1038 + ai->bitrate_hard_max=hi->bitrate_max; 1.1039 + ai->bitrate_av_lo=hi->bitrate_av; 1.1040 + ai->bitrate_av_hi=hi->bitrate_av; 1.1041 + 1.1042 + } 1.1043 + return(0); 1.1044 + 1.1045 + /* now deprecated *****************/ 1.1046 + case OV_ECTL_RATEMANAGE_SET: 1.1047 + { 1.1048 + struct ovectl_ratemanage_arg *ai= 1.1049 + (struct ovectl_ratemanage_arg *)arg; 1.1050 + if(ai==NULL){ 1.1051 + hi->managed=0; 1.1052 + }else{ 1.1053 + hi->managed=ai->management_active; 1.1054 + vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_AVG,arg); 1.1055 + vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_HARD,arg); 1.1056 + } 1.1057 + } 1.1058 + return 0; 1.1059 + 1.1060 + /* now deprecated *****************/ 1.1061 + case OV_ECTL_RATEMANAGE_AVG: 1.1062 + { 1.1063 + struct ovectl_ratemanage_arg *ai= 1.1064 + (struct ovectl_ratemanage_arg *)arg; 1.1065 + if(ai==NULL){ 1.1066 + hi->bitrate_av=0; 1.1067 + }else{ 1.1068 + hi->bitrate_av=(ai->bitrate_av_lo+ai->bitrate_av_hi)*.5; 1.1069 + } 1.1070 + } 1.1071 + return(0); 1.1072 + /* now deprecated *****************/ 1.1073 + case OV_ECTL_RATEMANAGE_HARD: 1.1074 + { 1.1075 + struct ovectl_ratemanage_arg *ai= 1.1076 + (struct ovectl_ratemanage_arg *)arg; 1.1077 + if(ai==NULL){ 1.1078 + hi->bitrate_min=0; 1.1079 + hi->bitrate_max=0; 1.1080 + }else{ 1.1081 + hi->bitrate_min=ai->bitrate_hard_min; 1.1082 + hi->bitrate_max=ai->bitrate_hard_max; 1.1083 + hi->bitrate_reservoir=ai->bitrate_hard_window* 1.1084 + (hi->bitrate_max+hi->bitrate_min)*.5; 1.1085 + } 1.1086 + if(hi->bitrate_reservoir<128.) 1.1087 + hi->bitrate_reservoir=128.; 1.1088 + } 1.1089 + return(0); 1.1090 + 1.1091 + /* replacement ratemanage interface */ 1.1092 + case OV_ECTL_RATEMANAGE2_GET: 1.1093 + { 1.1094 + struct ovectl_ratemanage2_arg *ai= 1.1095 + (struct ovectl_ratemanage2_arg *)arg; 1.1096 + if(ai==NULL)return OV_EINVAL; 1.1097 + 1.1098 + ai->management_active=hi->managed; 1.1099 + ai->bitrate_limit_min_kbps=hi->bitrate_min/1000; 1.1100 + ai->bitrate_limit_max_kbps=hi->bitrate_max/1000; 1.1101 + ai->bitrate_average_kbps=hi->bitrate_av/1000; 1.1102 + ai->bitrate_average_damping=hi->bitrate_av_damp; 1.1103 + ai->bitrate_limit_reservoir_bits=hi->bitrate_reservoir; 1.1104 + ai->bitrate_limit_reservoir_bias=hi->bitrate_reservoir_bias; 1.1105 + } 1.1106 + return (0); 1.1107 + case OV_ECTL_RATEMANAGE2_SET: 1.1108 + { 1.1109 + struct ovectl_ratemanage2_arg *ai= 1.1110 + (struct ovectl_ratemanage2_arg *)arg; 1.1111 + if(ai==NULL){ 1.1112 + hi->managed=0; 1.1113 + }else{ 1.1114 + /* sanity check; only catch invariant violations */ 1.1115 + if(ai->bitrate_limit_min_kbps>0 && 1.1116 + ai->bitrate_average_kbps>0 && 1.1117 + ai->bitrate_limit_min_kbps>ai->bitrate_average_kbps) 1.1118 + return OV_EINVAL; 1.1119 + 1.1120 + if(ai->bitrate_limit_max_kbps>0 && 1.1121 + ai->bitrate_average_kbps>0 && 1.1122 + ai->bitrate_limit_max_kbps<ai->bitrate_average_kbps) 1.1123 + return OV_EINVAL; 1.1124 + 1.1125 + if(ai->bitrate_limit_min_kbps>0 && 1.1126 + ai->bitrate_limit_max_kbps>0 && 1.1127 + ai->bitrate_limit_min_kbps>ai->bitrate_limit_max_kbps) 1.1128 + return OV_EINVAL; 1.1129 + 1.1130 + if(ai->bitrate_average_damping <= 0.) 1.1131 + return OV_EINVAL; 1.1132 + 1.1133 + if(ai->bitrate_limit_reservoir_bits < 0) 1.1134 + return OV_EINVAL; 1.1135 + 1.1136 + if(ai->bitrate_limit_reservoir_bias < 0.) 1.1137 + return OV_EINVAL; 1.1138 + 1.1139 + if(ai->bitrate_limit_reservoir_bias > 1.) 1.1140 + return OV_EINVAL; 1.1141 + 1.1142 + hi->managed=ai->management_active; 1.1143 + hi->bitrate_min=ai->bitrate_limit_min_kbps * 1000; 1.1144 + hi->bitrate_max=ai->bitrate_limit_max_kbps * 1000; 1.1145 + hi->bitrate_av=ai->bitrate_average_kbps * 1000; 1.1146 + hi->bitrate_av_damp=ai->bitrate_average_damping; 1.1147 + hi->bitrate_reservoir=ai->bitrate_limit_reservoir_bits; 1.1148 + hi->bitrate_reservoir_bias=ai->bitrate_limit_reservoir_bias; 1.1149 + } 1.1150 + } 1.1151 + return 0; 1.1152 + 1.1153 + case OV_ECTL_LOWPASS_GET: 1.1154 + { 1.1155 + double *farg=(double *)arg; 1.1156 + *farg=hi->lowpass_kHz; 1.1157 + } 1.1158 + return(0); 1.1159 + case OV_ECTL_LOWPASS_SET: 1.1160 + { 1.1161 + double *farg=(double *)arg; 1.1162 + hi->lowpass_kHz=*farg; 1.1163 + 1.1164 + if(hi->lowpass_kHz<2.)hi->lowpass_kHz=2.; 1.1165 + if(hi->lowpass_kHz>99.)hi->lowpass_kHz=99.; 1.1166 + hi->lowpass_altered=1; 1.1167 + } 1.1168 + return(0); 1.1169 + case OV_ECTL_IBLOCK_GET: 1.1170 + { 1.1171 + double *farg=(double *)arg; 1.1172 + *farg=hi->impulse_noisetune; 1.1173 + } 1.1174 + return(0); 1.1175 + case OV_ECTL_IBLOCK_SET: 1.1176 + { 1.1177 + double *farg=(double *)arg; 1.1178 + hi->impulse_noisetune=*farg; 1.1179 + 1.1180 + if(hi->impulse_noisetune>0.)hi->impulse_noisetune=0.; 1.1181 + if(hi->impulse_noisetune<-15.)hi->impulse_noisetune=-15.; 1.1182 + } 1.1183 + return(0); 1.1184 + case OV_ECTL_COUPLING_GET: 1.1185 + { 1.1186 + int *iarg=(int *)arg; 1.1187 + *iarg=hi->coupling_p; 1.1188 + } 1.1189 + return(0); 1.1190 + case OV_ECTL_COUPLING_SET: 1.1191 + { 1.1192 + const void *new_template; 1.1193 + double new_base=0.; 1.1194 + int *iarg=(int *)arg; 1.1195 + hi->coupling_p=((*iarg)!=0); 1.1196 + 1.1197 + /* Fetching a new template can alter the base_setting, which 1.1198 + many other parameters are based on. Right now, the only 1.1199 + parameter drawn from the base_setting that can be altered 1.1200 + by an encctl is the lowpass, so that is explictly flagged 1.1201 + to not be overwritten when we fetch a new template and 1.1202 + recompute the dependant settings */ 1.1203 + new_template = get_setup_template(hi->coupling_p?vi->channels:-1, 1.1204 + vi->rate, 1.1205 + hi->req, 1.1206 + hi->managed, 1.1207 + &new_base); 1.1208 + if(!hi->setup)return OV_EIMPL; 1.1209 + hi->setup=new_template; 1.1210 + hi->base_setting=new_base; 1.1211 + vorbis_encode_setup_setting(vi,vi->channels,vi->rate); 1.1212 + } 1.1213 + return(0); 1.1214 + } 1.1215 + return(OV_EIMPL); 1.1216 + } 1.1217 + return(OV_EINVAL); 1.1218 +}