+ return;
+}
+
+static void vorbis_encode_ath_setup(vorbis_info *vi,int block){
+ codec_setup_info *ci=vi->codec_setup;
+ vorbis_info_psy *p=ci->psy_param[block];
+
+ p->ath_adjatt=ci->hi.ath_floating_dB;
+ p->ath_maxatt=ci->hi.ath_absolute_dB;
+ return;
+}
+
+
+static int book_dup_or_new(codec_setup_info *ci,const static_codebook *book){
+ int i;
+ for(i=0;i<ci->books;i++)
+ if(ci->book_param[i]==book)return(i);
+
+ return(ci->books++);
+}
+
+static void vorbis_encode_blocksize_setup(vorbis_info *vi,double s,
+ const int *shortb,const int *longb){
+
+ codec_setup_info *ci=vi->codec_setup;
+ int is=s;
+
+ int blockshort=shortb[is];
+ int blocklong=longb[is];
+ ci->blocksizes[0]=blockshort;
+ ci->blocksizes[1]=blocklong;
+
+}
+
+static void vorbis_encode_residue_setup(vorbis_info *vi,
+ int number, int block,
+ const vorbis_residue_template *res){
+
+ codec_setup_info *ci=vi->codec_setup;
+ int i;
+
+ vorbis_info_residue0 *r=ci->residue_param[number]=
+ _ogg_malloc(sizeof(*r));
+
+ memcpy(r,res->res,sizeof(*r));
+ if(ci->residues<=number)ci->residues=number+1;
+
+ r->grouping=res->grouping;
+ ci->residue_type[number]=res->res_type;
+
+ /* fill in all the books */
+ {
+ int booklist=0,k;
+
+ if(ci->hi.managed){
+ for(i=0;i<r->partitions;i++)
+ for(k=0;k<4;k++)
+ if(res->books_base_managed->books[i][k])
+ r->secondstages[i]|=(1<<k);
+
+ r->groupbook=book_dup_or_new(ci,res->book_aux_managed);
+ ci->book_param[r->groupbook]=(static_codebook *)res->book_aux_managed;
+
+ for(i=0;i<r->partitions;i++){
+ for(k=0;k<4;k++){
+ if(res->books_base_managed->books[i][k]){
+ int bookid=book_dup_or_new(ci,res->books_base_managed->books[i][k]);
+ r->booklist[booklist++]=bookid;
+ ci->book_param[bookid]=(static_codebook *)res->books_base_managed->books[i][k];
+ }
+ }
+ }
+
+ }else{
+
+ for(i=0;i<r->partitions;i++)
+ for(k=0;k<4;k++)
+ if(res->books_base->books[i][k])
+ r->secondstages[i]|=(1<<k);
+
+ r->groupbook=book_dup_or_new(ci,res->book_aux);
+ ci->book_param[r->groupbook]=(static_codebook *)res->book_aux;
+
+ for(i=0;i<r->partitions;i++){
+ for(k=0;k<4;k++){
+ if(res->books_base->books[i][k]){
+ int bookid=book_dup_or_new(ci,res->books_base->books[i][k]);
+ r->booklist[booklist++]=bookid;
+ ci->book_param[bookid]=(static_codebook *)res->books_base->books[i][k];
+ }
+ }
+ }
+ }
+ }
+
+ /* lowpass setup/pointlimit */
+ {
+ double freq=ci->hi.lowpass_kHz*1000.;
+ vorbis_info_floor1 *f=ci->floor_param[block]; /* by convention */
+ double nyq=vi->rate/2.;
+ long blocksize=ci->blocksizes[block]>>1;
+
+ /* lowpass needs to be set in the floor and the residue. */
+ if(freq>nyq)freq=nyq;
+ /* in the floor, the granularity can be very fine; it doesn't alter
+ the encoding structure, only the samples used to fit the floor
+ approximation */
+ f->n=freq/nyq*blocksize;
+
+ /* this res may by limited by the maximum pointlimit of the mode,
+ not the lowpass. the floor is always lowpass limited. */
+ switch(res->limit_type){
+ case 1: /* point stereo limited */
+ if(ci->hi.managed)
+ freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS-1]*1000.;
+ else
+ freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS/2]*1000.;
+ if(freq>nyq)freq=nyq;
+ break;
+ case 2: /* LFE channel; lowpass at ~ 250Hz */
+ freq=250;
+ break;
+ default:
+ /* already set */
+ break;
+ }
+
+ /* in the residue, we're constrained, physically, by partition
+ boundaries. We still lowpass 'wherever', but we have to round up
+ here to next boundary, or the vorbis spec will round it *down* to
+ previous boundary in encode/decode */
+ if(ci->residue_type[number]==2){
+ /* residue 2 bundles together multiple channels; used by stereo
+ and surround. Count the channels in use */
+ /* Multiple maps/submaps can point to the same residue. In the case
+ of residue 2, they all better have the same number of
+ channels/samples. */
+ int j,k,ch=0;
+ for(i=0;i<ci->maps&&ch==0;i++){
+ vorbis_info_mapping0 *mi=(vorbis_info_mapping0 *)ci->map_param[i];
+ for(j=0;j<mi->submaps && ch==0;j++)
+ if(mi->residuesubmap[j]==number) /* we found a submap referencing theis residue backend */
+ for(k=0;k<vi->channels;k++)
+ if(mi->chmuxlist[k]==j) /* this channel belongs to the submap */
+ ch++;
+ }
+
+ r->end=(int)((freq/nyq*blocksize*ch)/r->grouping+.9)* /* round up only if we're well past */
+ r->grouping;
+ /* the blocksize and grouping may disagree at the end */
+ if(r->end>blocksize*ch)r->end=blocksize*ch/r->grouping*r->grouping;
+
+ }else{
+
+ r->end=(int)((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */
+ r->grouping;
+ /* the blocksize and grouping may disagree at the end */
+ if(r->end>blocksize)r->end=blocksize/r->grouping*r->grouping;
+
+ }
+
+ if(r->end==0)r->end=r->grouping; /* LFE channel */
+
+ }
+}
+
+/* we assume two maps in this encoder */
+static void vorbis_encode_map_n_res_setup(vorbis_info *vi,double s,
+ const vorbis_mapping_template *maps){
+
+ codec_setup_info *ci=vi->codec_setup;
+ int i,j,is=s,modes=2;
+ const vorbis_info_mapping0 *map=maps[is].map;
+ const vorbis_info_mode *mode=_mode_template;
+ const vorbis_residue_template *res=maps[is].res;
+
+ if(ci->blocksizes[0]==ci->blocksizes[1])modes=1;
+
+ for(i=0;i<modes;i++){
+
+ ci->map_param[i]=_ogg_calloc(1,sizeof(*map));
+ ci->mode_param[i]=_ogg_calloc(1,sizeof(*mode));
+
+ memcpy(ci->mode_param[i],mode+i,sizeof(*_mode_template));
+ if(i>=ci->modes)ci->modes=i+1;
+
+ ci->map_type[i]=0;
+ memcpy(ci->map_param[i],map+i,sizeof(*map));
+ if(i>=ci->maps)ci->maps=i+1;
+
+ for(j=0;j<map[i].submaps;j++)
+ vorbis_encode_residue_setup(vi,map[i].residuesubmap[j],i
+ ,res+map[i].residuesubmap[j]);
+ }
+}
+
+static double setting_to_approx_bitrate(vorbis_info *vi){
+ codec_setup_info *ci=vi->codec_setup;
+ highlevel_encode_setup *hi=&ci->hi;
+ ve_setup_data_template *setup=(ve_setup_data_template *)hi->setup;
+ int is=hi->base_setting;
+ double ds=hi->base_setting-is;
+ int ch=vi->channels;
+ const double *r=setup->rate_mapping;
+
+ if(r==NULL)
+ return(-1);
+
+ return((r[is]*(1.-ds)+r[is+1]*ds)*ch);
+}
+
+static const void *get_setup_template(long ch,long srate,
+ double req,int q_or_bitrate,
+ double *base_setting){
+ int i=0,j;
+ if(q_or_bitrate)req/=ch;
+
+ while(setup_list[i]){
+ if(setup_list[i]->coupling_restriction==-1 ||
+ setup_list[i]->coupling_restriction==ch){
+ if(srate>=setup_list[i]->samplerate_min_restriction &&
+ srate<=setup_list[i]->samplerate_max_restriction){
+ int mappings=setup_list[i]->mappings;
+ const double *map=(q_or_bitrate?
+ setup_list[i]->rate_mapping:
+ setup_list[i]->quality_mapping);
+
+ /* the template matches. Does the requested quality mode
+ fall within this template's modes? */
+ if(req<map[0]){++i;continue;}
+ if(req>map[setup_list[i]->mappings]){++i;continue;}
+ for(j=0;j<mappings;j++)
+ if(req>=map[j] && req<map[j+1])break;
+ /* an all-points match */
+ if(j==mappings)
+ *base_setting=j-.001;
+ else{
+ float low=map[j];
+ float high=map[j+1];
+ float del=(req-low)/(high-low);
+ *base_setting=j+del;
+ }
+
+ return(setup_list[i]);
+ }
+ }
+ i++;
+ }
+
+ return NULL;