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