Blame lib/vorbisenc.c

Packit 06404a
/********************************************************************
Packit 06404a
 *                                                                  *
Packit 06404a
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
Packit 06404a
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
Packit 06404a
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
Packit 06404a
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
Packit 06404a
 *                                                                  *
Packit 06404a
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015             *
Packit 06404a
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Packit 06404a
 *                                                                  *
Packit 06404a
 ********************************************************************
Packit 06404a
Packit 06404a
 function: simple programmatic interface for encoder mode setup
Packit 06404a
 last mod: $Id: vorbisenc.c 19457 2015-03-03 00:15:29Z giles $
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include <math.h>
Packit 06404a
Packit 06404a
#include "vorbis/codec.h"
Packit 06404a
#include "vorbis/vorbisenc.h"
Packit 06404a
Packit 06404a
#include "codec_internal.h"
Packit 06404a
Packit 06404a
#include "os.h"
Packit 06404a
#include "misc.h"
Packit 06404a
Packit 06404a
/* careful with this; it's using static array sizing to make managing
Packit 06404a
   all the modes a little less annoying.  If we use a residue backend
Packit 06404a
   with > 12 partition types, or a different division of iteration,
Packit 06404a
   this needs to be updated. */
Packit 06404a
typedef struct {
Packit 06404a
  const static_codebook *books[12][4];
Packit 06404a
} static_bookblock;
Packit 06404a
Packit 06404a
typedef struct {
Packit 06404a
  int res_type;
Packit 06404a
  int limit_type; /* 0 lowpass limited, 1 point stereo limited */
Packit 06404a
  int grouping;
Packit 06404a
  const vorbis_info_residue0 *res;
Packit 06404a
  const static_codebook  *book_aux;
Packit 06404a
  const static_codebook  *book_aux_managed;
Packit 06404a
  const static_bookblock *books_base;
Packit 06404a
  const static_bookblock *books_base_managed;
Packit 06404a
} vorbis_residue_template;
Packit 06404a
Packit 06404a
typedef struct {
Packit 06404a
  const vorbis_info_mapping0    *map;
Packit 06404a
  const vorbis_residue_template *res;
Packit 06404a
} vorbis_mapping_template;
Packit 06404a
Packit 06404a
typedef struct vp_adjblock{
Packit 06404a
  int block[P_BANDS];
Packit 06404a
} vp_adjblock;
Packit 06404a
Packit 06404a
typedef struct {
Packit 06404a
  int data[NOISE_COMPAND_LEVELS];
Packit 06404a
} compandblock;
Packit 06404a
Packit 06404a
/* high level configuration information for setting things up
Packit 06404a
   step-by-step with the detailed vorbis_encode_ctl interface.
Packit 06404a
   There's a fair amount of redundancy such that interactive setup
Packit 06404a
   does not directly deal with any vorbis_info or codec_setup_info
Packit 06404a
   initialization; it's all stored (until full init) in this highlevel
Packit 06404a
   setup, then flushed out to the real codec setup structs later. */
Packit 06404a
Packit 06404a
typedef struct {
Packit 06404a
  int att[P_NOISECURVES];
Packit 06404a
  float boost;
Packit 06404a
  float decay;
Packit 06404a
} att3;
Packit 06404a
typedef struct { int data[P_NOISECURVES]; } adj3;
Packit 06404a
Packit 06404a
typedef struct {
Packit 06404a
  int   pre[PACKETBLOBS];
Packit 06404a
  int   post[PACKETBLOBS];
Packit 06404a
  float kHz[PACKETBLOBS];
Packit 06404a
  float lowpasskHz[PACKETBLOBS];
Packit 06404a
} adj_stereo;
Packit 06404a
Packit 06404a
typedef struct {
Packit 06404a
  int lo;
Packit 06404a
  int hi;
Packit 06404a
  int fixed;
Packit 06404a
} noiseguard;
Packit 06404a
typedef struct {
Packit 06404a
  int data[P_NOISECURVES][17];
Packit 06404a
} noise3;
Packit 06404a
Packit 06404a
typedef struct {
Packit 06404a
  int      mappings;
Packit 06404a
  const double  *rate_mapping;
Packit 06404a
  const double  *quality_mapping;
Packit 06404a
  int      coupling_restriction;
Packit 06404a
  long     samplerate_min_restriction;
Packit 06404a
  long     samplerate_max_restriction;
Packit 06404a
Packit 06404a
Packit 06404a
  const int     *blocksize_short;
Packit 06404a
  const int     *blocksize_long;
Packit 06404a
Packit 06404a
  const att3    *psy_tone_masteratt;
Packit 06404a
  const int     *psy_tone_0dB;
Packit 06404a
  const int     *psy_tone_dBsuppress;
Packit 06404a
Packit 06404a
  const vp_adjblock *psy_tone_adj_impulse;
Packit 06404a
  const vp_adjblock *psy_tone_adj_long;
Packit 06404a
  const vp_adjblock *psy_tone_adj_other;
Packit 06404a
Packit 06404a
  const noiseguard  *psy_noiseguards;
Packit 06404a
  const noise3      *psy_noise_bias_impulse;
Packit 06404a
  const noise3      *psy_noise_bias_padding;
Packit 06404a
  const noise3      *psy_noise_bias_trans;
Packit 06404a
  const noise3      *psy_noise_bias_long;
Packit 06404a
  const int         *psy_noise_dBsuppress;
Packit 06404a
Packit 06404a
  const compandblock  *psy_noise_compand;
Packit 06404a
  const double        *psy_noise_compand_short_mapping;
Packit 06404a
  const double        *psy_noise_compand_long_mapping;
Packit 06404a
Packit 06404a
  const int      *psy_noise_normal_start[2];
Packit 06404a
  const int      *psy_noise_normal_partition[2];
Packit 06404a
  const double   *psy_noise_normal_thresh;
Packit 06404a
Packit 06404a
  const int      *psy_ath_float;
Packit 06404a
  const int      *psy_ath_abs;
Packit 06404a
Packit 06404a
  const double   *psy_lowpass;
Packit 06404a
Packit 06404a
  const vorbis_info_psy_global *global_params;
Packit 06404a
  const double     *global_mapping;
Packit 06404a
  const adj_stereo *stereo_modes;
Packit 06404a
Packit 06404a
  const static_codebook *const *const *const floor_books;
Packit 06404a
  const vorbis_info_floor1 *floor_params;
Packit 06404a
  const int floor_mappings;
Packit 06404a
  const int **floor_mapping_list;
Packit 06404a
Packit 06404a
  const vorbis_mapping_template *maps;
Packit 06404a
} ve_setup_data_template;
Packit 06404a
Packit 06404a
/* a few static coder conventions */
Packit 06404a
static const vorbis_info_mode _mode_template[2]={
Packit 06404a
  {0,0,0,0},
Packit 06404a
  {1,0,0,1}
Packit 06404a
};
Packit 06404a
Packit 06404a
static const vorbis_info_mapping0 _map_nominal[2]={
Packit 06404a
  {1, {0,0}, {0}, {0}, 1,{0},{1}},
Packit 06404a
  {1, {0,0}, {1}, {1}, 1,{0},{1}}
Packit 06404a
};
Packit 06404a
Packit 06404a
#include "modes/setup_44.h"
Packit 06404a
#include "modes/setup_44u.h"
Packit 06404a
#include "modes/setup_44p51.h"
Packit 06404a
#include "modes/setup_32.h"
Packit 06404a
#include "modes/setup_8.h"
Packit 06404a
#include "modes/setup_11.h"
Packit 06404a
#include "modes/setup_16.h"
Packit 06404a
#include "modes/setup_22.h"
Packit 06404a
#include "modes/setup_X.h"
Packit 06404a
Packit 06404a
static const ve_setup_data_template *const setup_list[]={
Packit 06404a
  &ve_setup_44_stereo,
Packit 06404a
  &ve_setup_44_51,
Packit 06404a
  &ve_setup_44_uncoupled,
Packit 06404a
Packit 06404a
  &ve_setup_32_stereo,
Packit 06404a
  &ve_setup_32_uncoupled,
Packit 06404a
Packit 06404a
  &ve_setup_22_stereo,
Packit 06404a
  &ve_setup_22_uncoupled,
Packit 06404a
  &ve_setup_16_stereo,
Packit 06404a
  &ve_setup_16_uncoupled,
Packit 06404a
Packit 06404a
  &ve_setup_11_stereo,
Packit 06404a
  &ve_setup_11_uncoupled,
Packit 06404a
  &ve_setup_8_stereo,
Packit 06404a
  &ve_setup_8_uncoupled,
Packit 06404a
Packit 06404a
  &ve_setup_X_stereo,
Packit 06404a
  &ve_setup_X_uncoupled,
Packit 06404a
  &ve_setup_XX_stereo,
Packit 06404a
  &ve_setup_XX_uncoupled,
Packit 06404a
  0
Packit 06404a
};
Packit 06404a
Packit 06404a
static void vorbis_encode_floor_setup(vorbis_info *vi,int s,
Packit 06404a
                                     const static_codebook *const *const *const books,
Packit 06404a
                                     const vorbis_info_floor1 *in,
Packit 06404a
                                     const int *x){
Packit 06404a
  int i,k,is=s;
Packit 06404a
  vorbis_info_floor1 *f=_ogg_calloc(1,sizeof(*f));
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
Packit 06404a
  memcpy(f,in+x[is],sizeof(*f));
Packit 06404a
Packit 06404a
  /* books */
Packit 06404a
  {
Packit 06404a
    int partitions=f->partitions;
Packit 06404a
    int maxclass=-1;
Packit 06404a
    int maxbook=-1;
Packit 06404a
    for(i=0;i
Packit 06404a
      if(f->partitionclass[i]>maxclass)maxclass=f->partitionclass[i];
Packit 06404a
    for(i=0;i<=maxclass;i++){
Packit 06404a
      if(f->class_book[i]>maxbook)maxbook=f->class_book[i];
Packit 06404a
      f->class_book[i]+=ci->books;
Packit 06404a
      for(k=0;k<(1<<f->class_subs[i]);k++){
Packit 06404a
        if(f->class_subbook[i][k]>maxbook)maxbook=f->class_subbook[i][k];
Packit 06404a
        if(f->class_subbook[i][k]>=0)f->class_subbook[i][k]+=ci->books;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
Packit 06404a
    for(i=0;i<=maxbook;i++)
Packit 06404a
      ci->book_param[ci->books++]=(static_codebook *)books[x[is]][i];
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* for now, we're only using floor 1 */
Packit 06404a
  ci->floor_type[ci->floors]=1;
Packit 06404a
  ci->floor_param[ci->floors]=f;
Packit 06404a
  ci->floors++;
Packit 06404a
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_global_psych_setup(vorbis_info *vi,double s,
Packit 06404a
                                            const vorbis_info_psy_global *in,
Packit 06404a
                                            const double *x){
Packit 06404a
  int i,is=s;
Packit 06404a
  double ds=s-is;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy_global *g=&ci->psy_g_param;
Packit 06404a
Packit 06404a
  memcpy(g,in+(int)x[is],sizeof(*g));
Packit 06404a
Packit 06404a
  ds=x[is]*(1.-ds)+x[is+1]*ds;
Packit 06404a
  is=(int)ds;
Packit 06404a
  ds-=is;
Packit 06404a
  if(ds==0 && is>0){
Packit 06404a
    is--;
Packit 06404a
    ds=1.;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* interpolate the trigger threshholds */
Packit 06404a
  for(i=0;i<4;i++){
Packit 06404a
    g->preecho_thresh[i]=in[is].preecho_thresh[i]*(1.-ds)+in[is+1].preecho_thresh[i]*ds;
Packit 06404a
    g->postecho_thresh[i]=in[is].postecho_thresh[i]*(1.-ds)+in[is+1].postecho_thresh[i]*ds;
Packit 06404a
  }
Packit 06404a
  g->ampmax_att_per_sec=ci->hi.amplitude_track_dBpersec;
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_global_stereo(vorbis_info *vi,
Packit 06404a
                                        const highlevel_encode_setup *const hi,
Packit 06404a
                                        const adj_stereo *p){
Packit 06404a
  float s=hi->stereo_point_setting;
Packit 06404a
  int i,is=s;
Packit 06404a
  double ds=s-is;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy_global *g=&ci->psy_g_param;
Packit 06404a
Packit 06404a
  if(p){
Packit 06404a
    memcpy(g->coupling_prepointamp,p[is].pre,sizeof(*p[is].pre)*PACKETBLOBS);
Packit 06404a
    memcpy(g->coupling_postpointamp,p[is].post,sizeof(*p[is].post)*PACKETBLOBS);
Packit 06404a
Packit 06404a
    if(hi->managed){
Packit 06404a
      /* interpolate the kHz threshholds */
Packit 06404a
      for(i=0;i
Packit 06404a
        float kHz=p[is].kHz[i]*(1.-ds)+p[is+1].kHz[i]*ds;
Packit 06404a
        g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0];
Packit 06404a
        g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1];
Packit 06404a
        g->coupling_pkHz[i]=kHz;
Packit 06404a
Packit 06404a
        kHz=p[is].lowpasskHz[i]*(1.-ds)+p[is+1].lowpasskHz[i]*ds;
Packit 06404a
        g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0];
Packit 06404a
        g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1];
Packit 06404a
Packit 06404a
      }
Packit 06404a
    }else{
Packit 06404a
      float kHz=p[is].kHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].kHz[PACKETBLOBS/2]*ds;
Packit 06404a
      for(i=0;i
Packit 06404a
        g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0];
Packit 06404a
        g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1];
Packit 06404a
        g->coupling_pkHz[i]=kHz;
Packit 06404a
      }
Packit 06404a
Packit 06404a
      kHz=p[is].lowpasskHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].lowpasskHz[PACKETBLOBS/2]*ds;
Packit 06404a
      for(i=0;i
Packit 06404a
        g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0];
Packit 06404a
        g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1];
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }else{
Packit 06404a
    for(i=0;i
Packit 06404a
      g->sliding_lowpass[0][i]=ci->blocksizes[0];
Packit 06404a
      g->sliding_lowpass[1][i]=ci->blocksizes[1];
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_psyset_setup(vorbis_info *vi,double s,
Packit 06404a
                                       const int *nn_start,
Packit 06404a
                                       const int *nn_partition,
Packit 06404a
                                       const double *nn_thresh,
Packit 06404a
                                       int block){
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy *p=ci->psy_param[block];
Packit 06404a
  highlevel_encode_setup *hi=&ci->hi;
Packit 06404a
  int is=s;
Packit 06404a
Packit 06404a
  if(block>=ci->psys)
Packit 06404a
    ci->psys=block+1;
Packit 06404a
  if(!p){
Packit 06404a
    p=_ogg_calloc(1,sizeof(*p));
Packit 06404a
    ci->psy_param[block]=p;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  memcpy(p,&_psy_info_template,sizeof(*p));
Packit 06404a
  p->blockflag=block>>1;
Packit 06404a
Packit 06404a
  if(hi->noise_normalize_p){
Packit 06404a
    p->normal_p=1;
Packit 06404a
    p->normal_start=nn_start[is];
Packit 06404a
    p->normal_partition=nn_partition[is];
Packit 06404a
    p->normal_thresh=nn_thresh[is];
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_tonemask_setup(vorbis_info *vi,double s,int block,
Packit 06404a
                                         const att3 *att,
Packit 06404a
                                         const int  *max,
Packit 06404a
                                         const vp_adjblock *in){
Packit 06404a
  int i,is=s;
Packit 06404a
  double ds=s-is;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy *p=ci->psy_param[block];
Packit 06404a
Packit 06404a
  /* 0 and 2 are only used by bitmanagement, but there's no harm to always
Packit 06404a
     filling the values in here */
Packit 06404a
  p->tone_masteratt[0]=att[is].att[0]*(1.-ds)+att[is+1].att[0]*ds;
Packit 06404a
  p->tone_masteratt[1]=att[is].att[1]*(1.-ds)+att[is+1].att[1]*ds;
Packit 06404a
  p->tone_masteratt[2]=att[is].att[2]*(1.-ds)+att[is+1].att[2]*ds;
Packit 06404a
  p->tone_centerboost=att[is].boost*(1.-ds)+att[is+1].boost*ds;
Packit 06404a
  p->tone_decay=att[is].decay*(1.-ds)+att[is+1].decay*ds;
Packit 06404a
Packit 06404a
  p->max_curve_dB=max[is]*(1.-ds)+max[is+1]*ds;
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    p->toneatt[i]=in[is].block[i]*(1.-ds)+in[is+1].block[i]*ds;
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
Packit 06404a
static void vorbis_encode_compand_setup(vorbis_info *vi,double s,int block,
Packit 06404a
                                        const compandblock *in,
Packit 06404a
                                        const double *x){
Packit 06404a
  int i,is=s;
Packit 06404a
  double ds=s-is;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy *p=ci->psy_param[block];
Packit 06404a
Packit 06404a
  ds=x[is]*(1.-ds)+x[is+1]*ds;
Packit 06404a
  is=(int)ds;
Packit 06404a
  ds-=is;
Packit 06404a
  if(ds==0 && is>0){
Packit 06404a
    is--;
Packit 06404a
    ds=1.;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* interpolate the compander settings */
Packit 06404a
  for(i=0;i
Packit 06404a
    p->noisecompand[i]=in[is].data[i]*(1.-ds)+in[is+1].data[i]*ds;
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_peak_setup(vorbis_info *vi,double s,int block,
Packit 06404a
                                    const int *suppress){
Packit 06404a
  int is=s;
Packit 06404a
  double ds=s-is;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy *p=ci->psy_param[block];
Packit 06404a
Packit 06404a
  p->tone_abs_limit=suppress[is]*(1.-ds)+suppress[is+1]*ds;
Packit 06404a
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_noisebias_setup(vorbis_info *vi,double s,int block,
Packit 06404a
                                         const int *suppress,
Packit 06404a
                                         const noise3 *in,
Packit 06404a
                                         const noiseguard *guard,
Packit 06404a
                                         double userbias){
Packit 06404a
  int i,is=s,j;
Packit 06404a
  double ds=s-is;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy *p=ci->psy_param[block];
Packit 06404a
Packit 06404a
  p->noisemaxsupp=suppress[is]*(1.-ds)+suppress[is+1]*ds;
Packit 06404a
  p->noisewindowlomin=guard[block].lo;
Packit 06404a
  p->noisewindowhimin=guard[block].hi;
Packit 06404a
  p->noisewindowfixed=guard[block].fixed;
Packit 06404a
Packit 06404a
  for(j=0;j
Packit 06404a
    for(i=0;i
Packit 06404a
      p->noiseoff[j][i]=in[is].data[j][i]*(1.-ds)+in[is+1].data[j][i]*ds;
Packit 06404a
Packit 06404a
  /* impulse blocks may take a user specified bias to boost the
Packit 06404a
     nominal/high noise encoding depth */
Packit 06404a
  for(j=0;j
Packit 06404a
    float min=p->noiseoff[j][0]+6; /* the lowest it can go */
Packit 06404a
    for(i=0;i
Packit 06404a
      p->noiseoff[j][i]+=userbias;
Packit 06404a
      if(p->noiseoff[j][i]<min)p->noiseoff[j][i]=min;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_ath_setup(vorbis_info *vi,int block){
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy *p=ci->psy_param[block];
Packit 06404a
Packit 06404a
  p->ath_adjatt=ci->hi.ath_floating_dB;
Packit 06404a
  p->ath_maxatt=ci->hi.ath_absolute_dB;
Packit 06404a
  return;
Packit 06404a
}
Packit 06404a
Packit 06404a
Packit 06404a
static int book_dup_or_new(codec_setup_info *ci,const static_codebook *book){
Packit 06404a
  int i;
Packit 06404a
  for(i=0;i<ci->books;i++)
Packit 06404a
    if(ci->book_param[i]==book)return(i);
Packit 06404a
Packit 06404a
  return(ci->books++);
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_blocksize_setup(vorbis_info *vi,double s,
Packit 06404a
                                         const int *shortb,const int *longb){
Packit 06404a
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  int is=s;
Packit 06404a
Packit 06404a
  int blockshort=shortb[is];
Packit 06404a
  int blocklong=longb[is];
Packit 06404a
  ci->blocksizes[0]=blockshort;
Packit 06404a
  ci->blocksizes[1]=blocklong;
Packit 06404a
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_residue_setup(vorbis_info *vi,
Packit 06404a
                                        int number, int block,
Packit 06404a
                                        const vorbis_residue_template *res){
Packit 06404a
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  int i;
Packit 06404a
Packit 06404a
  vorbis_info_residue0 *r=ci->residue_param[number]=
Packit 06404a
    _ogg_malloc(sizeof(*r));
Packit 06404a
Packit 06404a
  memcpy(r,res->res,sizeof(*r));
Packit 06404a
  if(ci->residues<=number)ci->residues=number+1;
Packit 06404a
Packit 06404a
  r->grouping=res->grouping;
Packit 06404a
  ci->residue_type[number]=res->res_type;
Packit 06404a
Packit 06404a
  /* fill in all the books */
Packit 06404a
  {
Packit 06404a
    int booklist=0,k;
Packit 06404a
Packit 06404a
    if(ci->hi.managed){
Packit 06404a
      for(i=0;i<r->partitions;i++)
Packit 06404a
        for(k=0;k<4;k++)
Packit 06404a
          if(res->books_base_managed->books[i][k])
Packit 06404a
            r->secondstages[i]|=(1<
Packit 06404a
Packit 06404a
      r->groupbook=book_dup_or_new(ci,res->book_aux_managed);
Packit 06404a
      ci->book_param[r->groupbook]=(static_codebook *)res->book_aux_managed;
Packit 06404a
Packit 06404a
      for(i=0;i<r->partitions;i++){
Packit 06404a
        for(k=0;k<4;k++){
Packit 06404a
          if(res->books_base_managed->books[i][k]){
Packit 06404a
            int bookid=book_dup_or_new(ci,res->books_base_managed->books[i][k]);
Packit 06404a
            r->booklist[booklist++]=bookid;
Packit 06404a
            ci->book_param[bookid]=(static_codebook *)res->books_base_managed->books[i][k];
Packit 06404a
          }
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
Packit 06404a
    }else{
Packit 06404a
Packit 06404a
      for(i=0;i<r->partitions;i++)
Packit 06404a
        for(k=0;k<4;k++)
Packit 06404a
          if(res->books_base->books[i][k])
Packit 06404a
            r->secondstages[i]|=(1<
Packit 06404a
Packit 06404a
      r->groupbook=book_dup_or_new(ci,res->book_aux);
Packit 06404a
      ci->book_param[r->groupbook]=(static_codebook *)res->book_aux;
Packit 06404a
Packit 06404a
      for(i=0;i<r->partitions;i++){
Packit 06404a
        for(k=0;k<4;k++){
Packit 06404a
          if(res->books_base->books[i][k]){
Packit 06404a
            int bookid=book_dup_or_new(ci,res->books_base->books[i][k]);
Packit 06404a
            r->booklist[booklist++]=bookid;
Packit 06404a
            ci->book_param[bookid]=(static_codebook *)res->books_base->books[i][k];
Packit 06404a
          }
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* lowpass setup/pointlimit */
Packit 06404a
  {
Packit 06404a
    double freq=ci->hi.lowpass_kHz*1000.;
Packit 06404a
    vorbis_info_floor1 *f=ci->floor_param[block]; /* by convention */
Packit 06404a
    double nyq=vi->rate/2.;
Packit 06404a
    long blocksize=ci->blocksizes[block]>>1;
Packit 06404a
Packit 06404a
    /* lowpass needs to be set in the floor and the residue. */
Packit 06404a
    if(freq>nyq)freq=nyq;
Packit 06404a
    /* in the floor, the granularity can be very fine; it doesn't alter
Packit 06404a
       the encoding structure, only the samples used to fit the floor
Packit 06404a
       approximation */
Packit 06404a
    f->n=freq/nyq*blocksize;
Packit 06404a
Packit 06404a
    /* this res may by limited by the maximum pointlimit of the mode,
Packit 06404a
       not the lowpass. the floor is always lowpass limited. */
Packit 06404a
    switch(res->limit_type){
Packit 06404a
    case 1: /* point stereo limited */
Packit 06404a
      if(ci->hi.managed)
Packit 06404a
        freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS-1]*1000.;
Packit 06404a
      else
Packit 06404a
        freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS/2]*1000.;
Packit 06404a
      if(freq>nyq)freq=nyq;
Packit 06404a
      break;
Packit 06404a
    case 2: /* LFE channel; lowpass at ~ 250Hz */
Packit 06404a
      freq=250;
Packit 06404a
      break;
Packit 06404a
    default:
Packit 06404a
      /* already set */
Packit 06404a
      break;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* in the residue, we're constrained, physically, by partition
Packit 06404a
       boundaries.  We still lowpass 'wherever', but we have to round up
Packit 06404a
       here to next boundary, or the vorbis spec will round it *down* to
Packit 06404a
       previous boundary in encode/decode */
Packit 06404a
    if(ci->residue_type[number]==2){
Packit 06404a
      /* residue 2 bundles together multiple channels; used by stereo
Packit 06404a
         and surround.  Count the channels in use */
Packit 06404a
      /* Multiple maps/submaps can point to the same residue.  In the case
Packit 06404a
         of residue 2, they all better have the same number of
Packit 06404a
         channels/samples. */
Packit 06404a
      int j,k,ch=0;
Packit 06404a
      for(i=0;i<ci->maps&&ch==0;i++){
Packit 06404a
        vorbis_info_mapping0 *mi=(vorbis_info_mapping0 *)ci->map_param[i];
Packit 06404a
        for(j=0;j<mi->submaps && ch==0;j++)
Packit 06404a
          if(mi->residuesubmap[j]==number) /* we found a submap referencing theis residue backend */
Packit 06404a
            for(k=0;k<vi->channels;k++)
Packit 06404a
              if(mi->chmuxlist[k]==j) /* this channel belongs to the submap */
Packit 06404a
                ch++;
Packit 06404a
      }
Packit 06404a
Packit 06404a
      r->end=(int)((freq/nyq*blocksize*ch)/r->grouping+.9)* /* round up only if we're well past */
Packit 06404a
        r->grouping;
Packit 06404a
      /* the blocksize and grouping may disagree at the end */
Packit 06404a
      if(r->end>blocksize*ch)r->end=blocksize*ch/r->grouping*r->grouping;
Packit 06404a
Packit 06404a
    }else{
Packit 06404a
Packit 06404a
      r->end=(int)((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */
Packit 06404a
        r->grouping;
Packit 06404a
      /* the blocksize and grouping may disagree at the end */
Packit 06404a
      if(r->end>blocksize)r->end=blocksize/r->grouping*r->grouping;
Packit 06404a
Packit 06404a
    }
Packit 06404a
Packit 06404a
    if(r->end==0)r->end=r->grouping; /* LFE channel */
Packit 06404a
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
/* we assume two maps in this encoder */
Packit 06404a
static void vorbis_encode_map_n_res_setup(vorbis_info *vi,double s,
Packit 06404a
                                          const vorbis_mapping_template *maps){
Packit 06404a
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  int i,j,is=s,modes=2;
Packit 06404a
  const vorbis_info_mapping0 *map=maps[is].map;
Packit 06404a
  const vorbis_info_mode *mode=_mode_template;
Packit 06404a
  const vorbis_residue_template *res=maps[is].res;
Packit 06404a
Packit 06404a
  if(ci->blocksizes[0]==ci->blocksizes[1])modes=1;
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
Packit 06404a
    ci->map_param[i]=_ogg_calloc(1,sizeof(*map));
Packit 06404a
    ci->mode_param[i]=_ogg_calloc(1,sizeof(*mode));
Packit 06404a
Packit 06404a
    memcpy(ci->mode_param[i],mode+i,sizeof(*_mode_template));
Packit 06404a
    if(i>=ci->modes)ci->modes=i+1;
Packit 06404a
Packit 06404a
    ci->map_type[i]=0;
Packit 06404a
    memcpy(ci->map_param[i],map+i,sizeof(*map));
Packit 06404a
    if(i>=ci->maps)ci->maps=i+1;
Packit 06404a
Packit 06404a
    for(j=0;j
Packit 06404a
      vorbis_encode_residue_setup(vi,map[i].residuesubmap[j],i
Packit 06404a
                                  ,res+map[i].residuesubmap[j]);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static double setting_to_approx_bitrate(vorbis_info *vi){
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  highlevel_encode_setup *hi=&ci->hi;
Packit 06404a
  ve_setup_data_template *setup=(ve_setup_data_template *)hi->setup;
Packit 06404a
  int is=hi->base_setting;
Packit 06404a
  double ds=hi->base_setting-is;
Packit 06404a
  int ch=vi->channels;
Packit 06404a
  const double *r=setup->rate_mapping;
Packit 06404a
Packit 06404a
  if(r==NULL)
Packit 06404a
    return(-1);
Packit 06404a
Packit 06404a
  return((r[is]*(1.-ds)+r[is+1]*ds)*ch);
Packit 06404a
}
Packit 06404a
Packit 06404a
static const void *get_setup_template(long ch,long srate,
Packit 06404a
                                      double req,int q_or_bitrate,
Packit 06404a
                                      double *base_setting){
Packit 06404a
  int i=0,j;
Packit 06404a
  if(q_or_bitrate)req/=ch;
Packit 06404a
Packit 06404a
  while(setup_list[i]){
Packit 06404a
    if(setup_list[i]->coupling_restriction==-1 ||
Packit 06404a
       setup_list[i]->coupling_restriction==ch){
Packit 06404a
      if(srate>=setup_list[i]->samplerate_min_restriction &&
Packit 06404a
         srate<=setup_list[i]->samplerate_max_restriction){
Packit 06404a
        int mappings=setup_list[i]->mappings;
Packit 06404a
        const double *map=(q_or_bitrate?
Packit 06404a
                     setup_list[i]->rate_mapping:
Packit 06404a
                     setup_list[i]->quality_mapping);
Packit 06404a
Packit 06404a
        /* the template matches.  Does the requested quality mode
Packit 06404a
           fall within this template's modes? */
Packit 06404a
        if(req
Packit 06404a
        if(req>map[setup_list[i]->mappings]){++i;continue;}
Packit 06404a
        for(j=0;j
Packit 06404a
          if(req>=map[j] && req
Packit 06404a
        /* an all-points match */
Packit 06404a
        if(j==mappings)
Packit 06404a
          *base_setting=j-.001;
Packit 06404a
        else{
Packit 06404a
          float low=map[j];
Packit 06404a
          float high=map[j+1];
Packit 06404a
          float del=(req-low)/(high-low);
Packit 06404a
          *base_setting=j+del;
Packit 06404a
        }
Packit 06404a
Packit 06404a
        return(setup_list[i]);
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
    i++;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return NULL;
Packit 06404a
}
Packit 06404a
Packit 06404a
/* encoders will need to use vorbis_info_init beforehand and call
Packit 06404a
   vorbis_info clear when all done */
Packit 06404a
Packit 06404a
/* two interfaces; this, more detailed one, and later a convenience
Packit 06404a
   layer on top */
Packit 06404a
Packit 06404a
/* the final setup call */
Packit 06404a
int vorbis_encode_setup_init(vorbis_info *vi){
Packit 06404a
  int i,i0=0,singleblock=0;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  ve_setup_data_template *setup=NULL;
Packit 06404a
  highlevel_encode_setup *hi=&ci->hi;
Packit 06404a
Packit 06404a
  if(ci==NULL)return(OV_EINVAL);
Packit 06404a
  if(!hi->impulse_block_p)i0=1;
Packit 06404a
Packit 06404a
  /* too low/high an ATH floater is nonsensical, but doesn't break anything */
Packit 06404a
  if(hi->ath_floating_dB>-80)hi->ath_floating_dB=-80;
Packit 06404a
  if(hi->ath_floating_dB<-200)hi->ath_floating_dB=-200;
Packit 06404a
Packit 06404a
  /* again, bound this to avoid the app shooting itself int he foot
Packit 06404a
     too badly */
Packit 06404a
  if(hi->amplitude_track_dBpersec>0.)hi->amplitude_track_dBpersec=0.;
Packit 06404a
  if(hi->amplitude_track_dBpersec<-99999.)hi->amplitude_track_dBpersec=-99999.;
Packit 06404a
Packit 06404a
  /* get the appropriate setup template; matches the fetch in previous
Packit 06404a
     stages */
Packit 06404a
  setup=(ve_setup_data_template *)hi->setup;
Packit 06404a
  if(setup==NULL)return(OV_EINVAL);
Packit 06404a
Packit 06404a
  hi->set_in_stone=1;
Packit 06404a
  /* choose block sizes from configured sizes as well as paying
Packit 06404a
     attention to long_block_p and short_block_p.  If the configured
Packit 06404a
     short and long blocks are the same length, we set long_block_p
Packit 06404a
     and unset short_block_p */
Packit 06404a
  vorbis_encode_blocksize_setup(vi,hi->base_setting,
Packit 06404a
                                setup->blocksize_short,
Packit 06404a
                                setup->blocksize_long);
Packit 06404a
  if(ci->blocksizes[0]==ci->blocksizes[1])singleblock=1;
Packit 06404a
Packit 06404a
  /* floor setup; choose proper floor params.  Allocated on the floor
Packit 06404a
     stack in order; if we alloc only a single long floor, it's 0 */
Packit 06404a
  for(i=0;i<setup->floor_mappings;i++)
Packit 06404a
    vorbis_encode_floor_setup(vi,hi->base_setting,
Packit 06404a
                              setup->floor_books,
Packit 06404a
                              setup->floor_params,
Packit 06404a
                              setup->floor_mapping_list[i]);
Packit 06404a
Packit 06404a
  /* setup of [mostly] short block detection and stereo*/
Packit 06404a
  vorbis_encode_global_psych_setup(vi,hi->trigger_setting,
Packit 06404a
                                   setup->global_params,
Packit 06404a
                                   setup->global_mapping);
Packit 06404a
  vorbis_encode_global_stereo(vi,hi,setup->stereo_modes);
Packit 06404a
Packit 06404a
  /* basic psych setup and noise normalization */
Packit 06404a
  vorbis_encode_psyset_setup(vi,hi->base_setting,
Packit 06404a
                             setup->psy_noise_normal_start[0],
Packit 06404a
                             setup->psy_noise_normal_partition[0],
Packit 06404a
                             setup->psy_noise_normal_thresh,
Packit 06404a
                             0);
Packit 06404a
  vorbis_encode_psyset_setup(vi,hi->base_setting,
Packit 06404a
                             setup->psy_noise_normal_start[0],
Packit 06404a
                             setup->psy_noise_normal_partition[0],
Packit 06404a
                             setup->psy_noise_normal_thresh,
Packit 06404a
                             1);
Packit 06404a
  if(!singleblock){
Packit 06404a
    vorbis_encode_psyset_setup(vi,hi->base_setting,
Packit 06404a
                               setup->psy_noise_normal_start[1],
Packit 06404a
                               setup->psy_noise_normal_partition[1],
Packit 06404a
                                    setup->psy_noise_normal_thresh,
Packit 06404a
                               2);
Packit 06404a
    vorbis_encode_psyset_setup(vi,hi->base_setting,
Packit 06404a
                               setup->psy_noise_normal_start[1],
Packit 06404a
                               setup->psy_noise_normal_partition[1],
Packit 06404a
                               setup->psy_noise_normal_thresh,
Packit 06404a
                               3);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* tone masking setup */
Packit 06404a
  vorbis_encode_tonemask_setup(vi,hi->block[i0].tone_mask_setting,0,
Packit 06404a
                               setup->psy_tone_masteratt,
Packit 06404a
                               setup->psy_tone_0dB,
Packit 06404a
                               setup->psy_tone_adj_impulse);
Packit 06404a
  vorbis_encode_tonemask_setup(vi,hi->block[1].tone_mask_setting,1,
Packit 06404a
                               setup->psy_tone_masteratt,
Packit 06404a
                               setup->psy_tone_0dB,
Packit 06404a
                               setup->psy_tone_adj_other);
Packit 06404a
  if(!singleblock){
Packit 06404a
    vorbis_encode_tonemask_setup(vi,hi->block[2].tone_mask_setting,2,
Packit 06404a
                                 setup->psy_tone_masteratt,
Packit 06404a
                                 setup->psy_tone_0dB,
Packit 06404a
                                 setup->psy_tone_adj_other);
Packit 06404a
    vorbis_encode_tonemask_setup(vi,hi->block[3].tone_mask_setting,3,
Packit 06404a
                                 setup->psy_tone_masteratt,
Packit 06404a
                                 setup->psy_tone_0dB,
Packit 06404a
                                 setup->psy_tone_adj_long);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* noise companding setup */
Packit 06404a
  vorbis_encode_compand_setup(vi,hi->block[i0].noise_compand_setting,0,
Packit 06404a
                              setup->psy_noise_compand,
Packit 06404a
                              setup->psy_noise_compand_short_mapping);
Packit 06404a
  vorbis_encode_compand_setup(vi,hi->block[1].noise_compand_setting,1,
Packit 06404a
                              setup->psy_noise_compand,
Packit 06404a
                              setup->psy_noise_compand_short_mapping);
Packit 06404a
  if(!singleblock){
Packit 06404a
    vorbis_encode_compand_setup(vi,hi->block[2].noise_compand_setting,2,
Packit 06404a
                                setup->psy_noise_compand,
Packit 06404a
                                setup->psy_noise_compand_long_mapping);
Packit 06404a
    vorbis_encode_compand_setup(vi,hi->block[3].noise_compand_setting,3,
Packit 06404a
                                setup->psy_noise_compand,
Packit 06404a
                                setup->psy_noise_compand_long_mapping);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* peak guarding setup  */
Packit 06404a
  vorbis_encode_peak_setup(vi,hi->block[i0].tone_peaklimit_setting,0,
Packit 06404a
                           setup->psy_tone_dBsuppress);
Packit 06404a
  vorbis_encode_peak_setup(vi,hi->block[1].tone_peaklimit_setting,1,
Packit 06404a
                           setup->psy_tone_dBsuppress);
Packit 06404a
  if(!singleblock){
Packit 06404a
    vorbis_encode_peak_setup(vi,hi->block[2].tone_peaklimit_setting,2,
Packit 06404a
                             setup->psy_tone_dBsuppress);
Packit 06404a
    vorbis_encode_peak_setup(vi,hi->block[3].tone_peaklimit_setting,3,
Packit 06404a
                             setup->psy_tone_dBsuppress);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* noise bias setup */
Packit 06404a
  vorbis_encode_noisebias_setup(vi,hi->block[i0].noise_bias_setting,0,
Packit 06404a
                                setup->psy_noise_dBsuppress,
Packit 06404a
                                setup->psy_noise_bias_impulse,
Packit 06404a
                                setup->psy_noiseguards,
Packit 06404a
                                (i0==0?hi->impulse_noisetune:0.));
Packit 06404a
  vorbis_encode_noisebias_setup(vi,hi->block[1].noise_bias_setting,1,
Packit 06404a
                                setup->psy_noise_dBsuppress,
Packit 06404a
                                setup->psy_noise_bias_padding,
Packit 06404a
                                setup->psy_noiseguards,0.);
Packit 06404a
  if(!singleblock){
Packit 06404a
    vorbis_encode_noisebias_setup(vi,hi->block[2].noise_bias_setting,2,
Packit 06404a
                                  setup->psy_noise_dBsuppress,
Packit 06404a
                                  setup->psy_noise_bias_trans,
Packit 06404a
                                  setup->psy_noiseguards,0.);
Packit 06404a
    vorbis_encode_noisebias_setup(vi,hi->block[3].noise_bias_setting,3,
Packit 06404a
                                  setup->psy_noise_dBsuppress,
Packit 06404a
                                  setup->psy_noise_bias_long,
Packit 06404a
                                  setup->psy_noiseguards,0.);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  vorbis_encode_ath_setup(vi,0);
Packit 06404a
  vorbis_encode_ath_setup(vi,1);
Packit 06404a
  if(!singleblock){
Packit 06404a
    vorbis_encode_ath_setup(vi,2);
Packit 06404a
    vorbis_encode_ath_setup(vi,3);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  vorbis_encode_map_n_res_setup(vi,hi->base_setting,setup->maps);
Packit 06404a
Packit 06404a
  /* set bitrate readonlies and management */
Packit 06404a
  if(hi->bitrate_av>0)
Packit 06404a
    vi->bitrate_nominal=hi->bitrate_av;
Packit 06404a
  else{
Packit 06404a
    vi->bitrate_nominal=setting_to_approx_bitrate(vi);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  vi->bitrate_lower=hi->bitrate_min;
Packit 06404a
  vi->bitrate_upper=hi->bitrate_max;
Packit 06404a
  if(hi->bitrate_av)
Packit 06404a
    vi->bitrate_window=(double)hi->bitrate_reservoir/hi->bitrate_av;
Packit 06404a
  else
Packit 06404a
    vi->bitrate_window=0.;
Packit 06404a
Packit 06404a
  if(hi->managed){
Packit 06404a
    ci->bi.avg_rate=hi->bitrate_av;
Packit 06404a
    ci->bi.min_rate=hi->bitrate_min;
Packit 06404a
    ci->bi.max_rate=hi->bitrate_max;
Packit 06404a
Packit 06404a
    ci->bi.reservoir_bits=hi->bitrate_reservoir;
Packit 06404a
    ci->bi.reservoir_bias=
Packit 06404a
      hi->bitrate_reservoir_bias;
Packit 06404a
Packit 06404a
    ci->bi.slew_damp=hi->bitrate_av_damp;
Packit 06404a
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return(0);
Packit 06404a
Packit 06404a
}
Packit 06404a
Packit 06404a
static void vorbis_encode_setup_setting(vorbis_info *vi,
Packit 06404a
                                       long  channels,
Packit 06404a
                                       long  rate){
Packit 06404a
  int i,is;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  highlevel_encode_setup *hi=&ci->hi;
Packit 06404a
  const ve_setup_data_template *setup=hi->setup;
Packit 06404a
  double ds;
Packit 06404a
Packit 06404a
  vi->version=0;
Packit 06404a
  vi->channels=channels;
Packit 06404a
  vi->rate=rate;
Packit 06404a
Packit 06404a
  hi->impulse_block_p=1;
Packit 06404a
  hi->noise_normalize_p=1;
Packit 06404a
Packit 06404a
  is=hi->base_setting;
Packit 06404a
  ds=hi->base_setting-is;
Packit 06404a
Packit 06404a
  hi->stereo_point_setting=hi->base_setting;
Packit 06404a
Packit 06404a
  if(!hi->lowpass_altered)
Packit 06404a
    hi->lowpass_kHz=
Packit 06404a
      setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds;
Packit 06404a
Packit 06404a
  hi->ath_floating_dB=setup->psy_ath_float[is]*(1.-ds)+
Packit 06404a
    setup->psy_ath_float[is+1]*ds;
Packit 06404a
  hi->ath_absolute_dB=setup->psy_ath_abs[is]*(1.-ds)+
Packit 06404a
    setup->psy_ath_abs[is+1]*ds;
Packit 06404a
Packit 06404a
  hi->amplitude_track_dBpersec=-6.;
Packit 06404a
  hi->trigger_setting=hi->base_setting;
Packit 06404a
Packit 06404a
  for(i=0;i<4;i++){
Packit 06404a
    hi->block[i].tone_mask_setting=hi->base_setting;
Packit 06404a
    hi->block[i].tone_peaklimit_setting=hi->base_setting;
Packit 06404a
    hi->block[i].noise_bias_setting=hi->base_setting;
Packit 06404a
    hi->block[i].noise_compand_setting=hi->base_setting;
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
int vorbis_encode_setup_vbr(vorbis_info *vi,
Packit 06404a
                            long  channels,
Packit 06404a
                            long  rate,
Packit 06404a
                            float quality){
Packit 06404a
  codec_setup_info *ci;
Packit 06404a
  highlevel_encode_setup *hi;
Packit 06404a
  if(rate<=0) return OV_EINVAL;
Packit 06404a
Packit 06404a
  ci=vi->codec_setup;
Packit 06404a
  hi=&ci->hi;
Packit 06404a
Packit 06404a
  quality+=.0000001;
Packit 06404a
  if(quality>=1.)quality=.9999;
Packit 06404a
Packit 06404a
  hi->req=quality;
Packit 06404a
  hi->setup=get_setup_template(channels,rate,quality,0,&hi->base_setting);
Packit 06404a
  if(!hi->setup)return OV_EIMPL;
Packit 06404a
Packit 06404a
  vorbis_encode_setup_setting(vi,channels,rate);
Packit 06404a
  hi->managed=0;
Packit 06404a
  hi->coupling_p=1;
Packit 06404a
Packit 06404a
  return 0;
Packit 06404a
}
Packit 06404a
Packit 06404a
int vorbis_encode_init_vbr(vorbis_info *vi,
Packit 06404a
                           long channels,
Packit 06404a
                           long rate,
Packit 06404a
Packit 06404a
                           float base_quality /* 0. to 1. */
Packit 06404a
                           ){
Packit 06404a
  int ret=0;
Packit 06404a
Packit 06404a
  ret=vorbis_encode_setup_vbr(vi,channels,rate,base_quality);
Packit 06404a
Packit 06404a
  if(ret){
Packit 06404a
    vorbis_info_clear(vi);
Packit 06404a
    return ret;
Packit 06404a
  }
Packit 06404a
  ret=vorbis_encode_setup_init(vi);
Packit 06404a
  if(ret)
Packit 06404a
    vorbis_info_clear(vi);
Packit 06404a
  return(ret);
Packit 06404a
}
Packit 06404a
Packit 06404a
int vorbis_encode_setup_managed(vorbis_info *vi,
Packit 06404a
                                long channels,
Packit 06404a
                                long rate,
Packit 06404a
Packit 06404a
                                long max_bitrate,
Packit 06404a
                                long nominal_bitrate,
Packit 06404a
                                long min_bitrate){
Packit 06404a
Packit 06404a
  codec_setup_info *ci;
Packit 06404a
  highlevel_encode_setup *hi;
Packit 06404a
  double tnominal;
Packit 06404a
  if(rate<=0) return OV_EINVAL;
Packit 06404a
Packit 06404a
  ci=vi->codec_setup;
Packit 06404a
  hi=&ci->hi;
Packit 06404a
  tnominal=nominal_bitrate;
Packit 06404a
Packit 06404a
  if(nominal_bitrate<=0.){
Packit 06404a
    if(max_bitrate>0.){
Packit 06404a
      if(min_bitrate>0.)
Packit 06404a
        nominal_bitrate=(max_bitrate+min_bitrate)*.5;
Packit 06404a
      else
Packit 06404a
        nominal_bitrate=max_bitrate*.875;
Packit 06404a
    }else{
Packit 06404a
      if(min_bitrate>0.){
Packit 06404a
        nominal_bitrate=min_bitrate;
Packit 06404a
      }else{
Packit 06404a
        return(OV_EINVAL);
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  hi->req=nominal_bitrate;
Packit 06404a
  hi->setup=get_setup_template(channels,rate,nominal_bitrate,1,&hi->base_setting);
Packit 06404a
  if(!hi->setup)return OV_EIMPL;
Packit 06404a
Packit 06404a
  vorbis_encode_setup_setting(vi,channels,rate);
Packit 06404a
Packit 06404a
  /* initialize management with sane defaults */
Packit 06404a
  hi->coupling_p=1;
Packit 06404a
  hi->managed=1;
Packit 06404a
  hi->bitrate_min=min_bitrate;
Packit 06404a
  hi->bitrate_max=max_bitrate;
Packit 06404a
  hi->bitrate_av=tnominal;
Packit 06404a
  hi->bitrate_av_damp=1.5f; /* full range in no less than 1.5 second */
Packit 06404a
  hi->bitrate_reservoir=nominal_bitrate*2;
Packit 06404a
  hi->bitrate_reservoir_bias=.1; /* bias toward hoarding bits */
Packit 06404a
Packit 06404a
  return(0);
Packit 06404a
Packit 06404a
}
Packit 06404a
Packit 06404a
int vorbis_encode_init(vorbis_info *vi,
Packit 06404a
                       long channels,
Packit 06404a
                       long rate,
Packit 06404a
Packit 06404a
                       long max_bitrate,
Packit 06404a
                       long nominal_bitrate,
Packit 06404a
                       long min_bitrate){
Packit 06404a
Packit 06404a
  int ret=vorbis_encode_setup_managed(vi,channels,rate,
Packit 06404a
                                      max_bitrate,
Packit 06404a
                                      nominal_bitrate,
Packit 06404a
                                      min_bitrate);
Packit 06404a
  if(ret){
Packit 06404a
    vorbis_info_clear(vi);
Packit 06404a
    return(ret);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  ret=vorbis_encode_setup_init(vi);
Packit 06404a
  if(ret)
Packit 06404a
    vorbis_info_clear(vi);
Packit 06404a
  return(ret);
Packit 06404a
}
Packit 06404a
Packit 06404a
int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){
Packit 06404a
  if(vi){
Packit 06404a
    codec_setup_info *ci=vi->codec_setup;
Packit 06404a
    highlevel_encode_setup *hi=&ci->hi;
Packit 06404a
    int setp=(number&0xf); /* a read request has a low nibble of 0 */
Packit 06404a
Packit 06404a
    if(setp && hi->set_in_stone)return(OV_EINVAL);
Packit 06404a
Packit 06404a
    switch(number){
Packit 06404a
Packit 06404a
    /* now deprecated *****************/
Packit 06404a
    case OV_ECTL_RATEMANAGE_GET:
Packit 06404a
      {
Packit 06404a
Packit 06404a
        struct ovectl_ratemanage_arg *ai=
Packit 06404a
          (struct ovectl_ratemanage_arg *)arg;
Packit 06404a
Packit 06404a
        ai->management_active=hi->managed;
Packit 06404a
        ai->bitrate_hard_window=ai->bitrate_av_window=
Packit 06404a
          (double)hi->bitrate_reservoir/vi->rate;
Packit 06404a
        ai->bitrate_av_window_center=1.;
Packit 06404a
        ai->bitrate_hard_min=hi->bitrate_min;
Packit 06404a
        ai->bitrate_hard_max=hi->bitrate_max;
Packit 06404a
        ai->bitrate_av_lo=hi->bitrate_av;
Packit 06404a
        ai->bitrate_av_hi=hi->bitrate_av;
Packit 06404a
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
Packit 06404a
    /* now deprecated *****************/
Packit 06404a
    case OV_ECTL_RATEMANAGE_SET:
Packit 06404a
      {
Packit 06404a
        struct ovectl_ratemanage_arg *ai=
Packit 06404a
          (struct ovectl_ratemanage_arg *)arg;
Packit 06404a
        if(ai==NULL){
Packit 06404a
          hi->managed=0;
Packit 06404a
        }else{
Packit 06404a
          hi->managed=ai->management_active;
Packit 06404a
          vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_AVG,arg);
Packit 06404a
          vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_HARD,arg);
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
      return 0;
Packit 06404a
Packit 06404a
    /* now deprecated *****************/
Packit 06404a
    case OV_ECTL_RATEMANAGE_AVG:
Packit 06404a
      {
Packit 06404a
        struct ovectl_ratemanage_arg *ai=
Packit 06404a
          (struct ovectl_ratemanage_arg *)arg;
Packit 06404a
        if(ai==NULL){
Packit 06404a
          hi->bitrate_av=0;
Packit 06404a
        }else{
Packit 06404a
          hi->bitrate_av=(ai->bitrate_av_lo+ai->bitrate_av_hi)*.5;
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
    /* now deprecated *****************/
Packit 06404a
    case OV_ECTL_RATEMANAGE_HARD:
Packit 06404a
      {
Packit 06404a
        struct ovectl_ratemanage_arg *ai=
Packit 06404a
          (struct ovectl_ratemanage_arg *)arg;
Packit 06404a
        if(ai==NULL){
Packit 06404a
          hi->bitrate_min=0;
Packit 06404a
          hi->bitrate_max=0;
Packit 06404a
        }else{
Packit 06404a
          hi->bitrate_min=ai->bitrate_hard_min;
Packit 06404a
          hi->bitrate_max=ai->bitrate_hard_max;
Packit 06404a
          hi->bitrate_reservoir=ai->bitrate_hard_window*
Packit 06404a
            (hi->bitrate_max+hi->bitrate_min)*.5;
Packit 06404a
        }
Packit 06404a
        if(hi->bitrate_reservoir<128.)
Packit 06404a
          hi->bitrate_reservoir=128.;
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
Packit 06404a
      /* replacement ratemanage interface */
Packit 06404a
    case OV_ECTL_RATEMANAGE2_GET:
Packit 06404a
      {
Packit 06404a
        struct ovectl_ratemanage2_arg *ai=
Packit 06404a
          (struct ovectl_ratemanage2_arg *)arg;
Packit 06404a
        if(ai==NULL)return OV_EINVAL;
Packit 06404a
Packit 06404a
        ai->management_active=hi->managed;
Packit 06404a
        ai->bitrate_limit_min_kbps=hi->bitrate_min/1000;
Packit 06404a
        ai->bitrate_limit_max_kbps=hi->bitrate_max/1000;
Packit 06404a
        ai->bitrate_average_kbps=hi->bitrate_av/1000;
Packit 06404a
        ai->bitrate_average_damping=hi->bitrate_av_damp;
Packit 06404a
        ai->bitrate_limit_reservoir_bits=hi->bitrate_reservoir;
Packit 06404a
        ai->bitrate_limit_reservoir_bias=hi->bitrate_reservoir_bias;
Packit 06404a
      }
Packit 06404a
      return (0);
Packit 06404a
    case OV_ECTL_RATEMANAGE2_SET:
Packit 06404a
      {
Packit 06404a
        struct ovectl_ratemanage2_arg *ai=
Packit 06404a
          (struct ovectl_ratemanage2_arg *)arg;
Packit 06404a
        if(ai==NULL){
Packit 06404a
          hi->managed=0;
Packit 06404a
        }else{
Packit 06404a
          /* sanity check; only catch invariant violations */
Packit 06404a
          if(ai->bitrate_limit_min_kbps>0 &&
Packit 06404a
             ai->bitrate_average_kbps>0 &&
Packit 06404a
             ai->bitrate_limit_min_kbps>ai->bitrate_average_kbps)
Packit 06404a
            return OV_EINVAL;
Packit 06404a
Packit 06404a
          if(ai->bitrate_limit_max_kbps>0 &&
Packit 06404a
             ai->bitrate_average_kbps>0 &&
Packit 06404a
             ai->bitrate_limit_max_kbps<ai->bitrate_average_kbps)
Packit 06404a
            return OV_EINVAL;
Packit 06404a
Packit 06404a
          if(ai->bitrate_limit_min_kbps>0 &&
Packit 06404a
             ai->bitrate_limit_max_kbps>0 &&
Packit 06404a
             ai->bitrate_limit_min_kbps>ai->bitrate_limit_max_kbps)
Packit 06404a
            return OV_EINVAL;
Packit 06404a
Packit 06404a
          if(ai->bitrate_average_damping <= 0.)
Packit 06404a
            return OV_EINVAL;
Packit 06404a
Packit 06404a
          if(ai->bitrate_limit_reservoir_bits < 0)
Packit 06404a
            return OV_EINVAL;
Packit 06404a
Packit 06404a
          if(ai->bitrate_limit_reservoir_bias < 0.)
Packit 06404a
            return OV_EINVAL;
Packit 06404a
Packit 06404a
          if(ai->bitrate_limit_reservoir_bias > 1.)
Packit 06404a
            return OV_EINVAL;
Packit 06404a
Packit 06404a
          hi->managed=ai->management_active;
Packit 06404a
          hi->bitrate_min=ai->bitrate_limit_min_kbps * 1000;
Packit 06404a
          hi->bitrate_max=ai->bitrate_limit_max_kbps * 1000;
Packit 06404a
          hi->bitrate_av=ai->bitrate_average_kbps * 1000;
Packit 06404a
          hi->bitrate_av_damp=ai->bitrate_average_damping;
Packit 06404a
          hi->bitrate_reservoir=ai->bitrate_limit_reservoir_bits;
Packit 06404a
          hi->bitrate_reservoir_bias=ai->bitrate_limit_reservoir_bias;
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
      return 0;
Packit 06404a
Packit 06404a
    case OV_ECTL_LOWPASS_GET:
Packit 06404a
      {
Packit 06404a
        double *farg=(double *)arg;
Packit 06404a
        *farg=hi->lowpass_kHz;
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
    case OV_ECTL_LOWPASS_SET:
Packit 06404a
      {
Packit 06404a
        double *farg=(double *)arg;
Packit 06404a
        hi->lowpass_kHz=*farg;
Packit 06404a
Packit 06404a
        if(hi->lowpass_kHz<2.)hi->lowpass_kHz=2.;
Packit 06404a
        if(hi->lowpass_kHz>99.)hi->lowpass_kHz=99.;
Packit 06404a
        hi->lowpass_altered=1;
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
    case OV_ECTL_IBLOCK_GET:
Packit 06404a
      {
Packit 06404a
        double *farg=(double *)arg;
Packit 06404a
        *farg=hi->impulse_noisetune;
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
    case OV_ECTL_IBLOCK_SET:
Packit 06404a
      {
Packit 06404a
        double *farg=(double *)arg;
Packit 06404a
        hi->impulse_noisetune=*farg;
Packit 06404a
Packit 06404a
        if(hi->impulse_noisetune>0.)hi->impulse_noisetune=0.;
Packit 06404a
        if(hi->impulse_noisetune<-15.)hi->impulse_noisetune=-15.;
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
    case OV_ECTL_COUPLING_GET:
Packit 06404a
      {
Packit 06404a
        int *iarg=(int *)arg;
Packit 06404a
        *iarg=hi->coupling_p;
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
    case OV_ECTL_COUPLING_SET:
Packit 06404a
      {
Packit 06404a
        const void *new_template;
Packit 06404a
        double new_base=0.;
Packit 06404a
        int *iarg=(int *)arg;
Packit 06404a
        hi->coupling_p=((*iarg)!=0);
Packit 06404a
Packit 06404a
        /* Fetching a new template can alter the base_setting, which
Packit 06404a
           many other parameters are based on.  Right now, the only
Packit 06404a
           parameter drawn from the base_setting that can be altered
Packit 06404a
           by an encctl is the lowpass, so that is explictly flagged
Packit 06404a
           to not be overwritten when we fetch a new template and
Packit 06404a
           recompute the dependant settings */
Packit 06404a
        new_template = get_setup_template(hi->coupling_p?vi->channels:-1,
Packit 06404a
                                          vi->rate,
Packit 06404a
                                          hi->req,
Packit 06404a
                                          hi->managed,
Packit 06404a
                                          &new_base);
Packit 06404a
        if(!hi->setup)return OV_EIMPL;
Packit 06404a
        hi->setup=new_template;
Packit 06404a
        hi->base_setting=new_base;
Packit 06404a
        vorbis_encode_setup_setting(vi,vi->channels,vi->rate);
Packit 06404a
      }
Packit 06404a
      return(0);
Packit 06404a
    }
Packit 06404a
    return(OV_EIMPL);
Packit 06404a
  }
Packit 06404a
  return(OV_EINVAL);
Packit 06404a
}