* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: simple programmatic interface for encoder mode setup
- last mod: $Id$
********************************************************************/
with > 12 partition types, or a different division of iteration,
this needs to be updated. */
typedef struct {
- const static_codebook *books[12][3];
+ const static_codebook *books[12][4];
} static_bookblock;
typedef struct {
int res_type;
int limit_type; /* 0 lowpass limited, 1 point stereo limited */
+ int grouping;
const vorbis_info_residue0 *res;
const static_codebook *book_aux;
const static_codebook *book_aux_managed;
#include "modes/setup_44.h"
#include "modes/setup_44u.h"
+#include "modes/setup_44p51.h"
#include "modes/setup_32.h"
#include "modes/setup_8.h"
#include "modes/setup_11.h"
static const ve_setup_data_template *const setup_list[]={
&ve_setup_44_stereo,
+ &ve_setup_44_51,
&ve_setup_44_uncoupled,
&ve_setup_32_stereo,
0
};
-static int vorbis_encode_toplevel_setup(vorbis_info *vi,int ch,long rate){
- if(vi && vi->codec_setup){
-
- vi->version=0;
- vi->channels=ch;
- vi->rate=rate;
-
- return(0);
- }
- return(OV_EINVAL);
-}
-
static void vorbis_encode_floor_setup(vorbis_info *vi,int s,
const static_codebook *const *const *const books,
const vorbis_info_floor1 *in,
p->blockflag=block>>1;
if(hi->noise_normalize_p){
- p->normal_channel_p=1;
- p->normal_point_p=1;
+ p->normal_p=1;
p->normal_start=nn_start[is];
p->normal_partition=nn_partition[is];
p->normal_thresh=nn_thresh[is];
const vorbis_residue_template *res){
codec_setup_info *ci=vi->codec_setup;
- int i,n;
+ 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;
- switch(ci->blocksizes[block]){
- case 64:case 128:case 256:
- r->grouping=16;
- break;
- default:
- r->grouping=32;
- break;
- }
+ r->grouping=res->grouping;
ci->residue_type[number]=res->res_type;
- /* to be adjusted by lowpass/pointlimit later */
- n=r->end=ci->blocksizes[block]>>1;
- if(res->res_type==2)
- n=r->end*=vi->channels;
-
/* fill in all the books */
{
int booklist=0,k;
if(ci->hi.managed){
for(i=0;i<r->partitions;i++)
- for(k=0;k<3;k++)
+ for(k=0;k<4;k++)
if(res->books_base_managed->books[i][k])
r->secondstages[i]|=(1<<k);
ci->book_param[r->groupbook]=(static_codebook *)res->book_aux_managed;
for(i=0;i<r->partitions;i++){
- for(k=0;k<3;k++){
+ 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;
}else{
for(i=0;i<r->partitions;i++)
- for(k=0;k<3;k++)
+ for(k=0;k<4;k++)
if(res->books_base->books[i][k])
r->secondstages[i]|=(1<<k);
ci->book_param[r->groupbook]=(static_codebook *)res->book_aux;
for(i=0;i<r->partitions;i++){
- for(k=0;k<3;k++){
+ 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;
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[block]==2)
- r->end=(int)((freq/nyq*blocksize*2)/r->grouping+.9)* /* round up only if we're well past */
+ 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;
- else
+ /* 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 */
+
}
}
return((r[is]*(1.-ds)+r[is+1]*ds)*ch);
}
-static void get_setup_template(vorbis_info *vi,
- long ch,long srate,
- double req,int q_or_bitrate){
+static const void *get_setup_template(long ch,long srate,
+ double req,int q_or_bitrate,
+ double *base_setting){
int i=0,j;
- codec_setup_info *ci=vi->codec_setup;
- highlevel_encode_setup *hi=&ci->hi;
if(q_or_bitrate)req/=ch;
while(setup_list[i]){
for(j=0;j<mappings;j++)
if(req>=map[j] && req<map[j+1])break;
/* an all-points match */
- hi->setup=setup_list[i];
if(j==mappings)
- hi->base_setting=j-.001;
+ *base_setting=j-.001;
else{
float low=map[j];
float high=map[j+1];
float del=(req-low)/(high-low);
- hi->base_setting=j+del;
+ *base_setting=j+del;
}
- return;
+ return(setup_list[i]);
}
}
i++;
}
- hi->setup=NULL;
+ return NULL;
}
/* encoders will need to use vorbis_info_init beforehand and call
}
-static int vorbis_encode_setup_setting(vorbis_info *vi,
+static void vorbis_encode_setup_setting(vorbis_info *vi,
long channels,
long rate){
- int ret=0,i,is;
+ int i,is;
codec_setup_info *ci=vi->codec_setup;
highlevel_encode_setup *hi=&ci->hi;
const ve_setup_data_template *setup=hi->setup;
double ds;
- ret=vorbis_encode_toplevel_setup(vi,channels,rate);
- if(ret)return(ret);
-
- is=hi->base_setting;
- ds=hi->base_setting-is;
-
- hi->managed=0;
+ vi->version=0;
+ vi->channels=channels;
+ vi->rate=rate;
hi->impulse_block_p=1;
hi->noise_normalize_p=1;
+ is=hi->base_setting;
+ ds=hi->base_setting-is;
+
hi->stereo_point_setting=hi->base_setting;
- hi->lowpass_kHz=
- setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds;
+
+ if(!hi->lowpass_altered)
+ hi->lowpass_kHz=
+ setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds;
hi->ath_floating_dB=setup->psy_ath_float[is]*(1.-ds)+
setup->psy_ath_float[is+1]*ds;
hi->block[i].noise_bias_setting=hi->base_setting;
hi->block[i].noise_compand_setting=hi->base_setting;
}
-
- return(ret);
}
int vorbis_encode_setup_vbr(vorbis_info *vi,
long channels,
long rate,
float quality){
- codec_setup_info *ci=vi->codec_setup;
- highlevel_encode_setup *hi=&ci->hi;
+ codec_setup_info *ci;
+ highlevel_encode_setup *hi;
+ if(rate<=0) return OV_EINVAL;
+
+ ci=vi->codec_setup;
+ hi=&ci->hi;
quality+=.0000001;
if(quality>=1.)quality=.9999;
- get_setup_template(vi,channels,rate,quality,0);
+ hi->req=quality;
+ hi->setup=get_setup_template(channels,rate,quality,0,&hi->base_setting);
if(!hi->setup)return OV_EIMPL;
- return vorbis_encode_setup_setting(vi,channels,rate);
+ vorbis_encode_setup_setting(vi,channels,rate);
+ hi->managed=0;
+ hi->coupling_p=1;
+
+ return 0;
}
int vorbis_encode_init_vbr(vorbis_info *vi,
long nominal_bitrate,
long min_bitrate){
- codec_setup_info *ci=vi->codec_setup;
- highlevel_encode_setup *hi=&ci->hi;
- double tnominal=nominal_bitrate;
- int ret=0;
+ codec_setup_info *ci;
+ highlevel_encode_setup *hi;
+ double tnominal;
+ if(rate<=0) return OV_EINVAL;
+
+ ci=vi->codec_setup;
+ hi=&ci->hi;
+ tnominal=nominal_bitrate;
if(nominal_bitrate<=0.){
if(max_bitrate>0.){
}
}
- get_setup_template(vi,channels,rate,nominal_bitrate,1);
+ hi->req=nominal_bitrate;
+ hi->setup=get_setup_template(channels,rate,nominal_bitrate,1,&hi->base_setting);
if(!hi->setup)return OV_EIMPL;
- ret=vorbis_encode_setup_setting(vi,channels,rate);
- if(ret){
- vorbis_info_clear(vi);
- return ret;
- }
+ vorbis_encode_setup_setting(vi,channels,rate);
/* initialize management with sane defaults */
+ hi->coupling_p=1;
hi->managed=1;
hi->bitrate_min=min_bitrate;
hi->bitrate_max=max_bitrate;
hi->bitrate_reservoir=nominal_bitrate*2;
hi->bitrate_reservoir_bias=.1; /* bias toward hoarding bits */
- return(ret);
+ return(0);
}
if(hi->lowpass_kHz<2.)hi->lowpass_kHz=2.;
if(hi->lowpass_kHz>99.)hi->lowpass_kHz=99.;
+ hi->lowpass_altered=1;
}
return(0);
case OV_ECTL_IBLOCK_GET:
if(hi->impulse_noisetune<-15.)hi->impulse_noisetune=-15.;
}
return(0);
+ case OV_ECTL_COUPLING_GET:
+ {
+ int *iarg=(int *)arg;
+ *iarg=hi->coupling_p;
+ }
+ return(0);
+ case OV_ECTL_COUPLING_SET:
+ {
+ const void *new_template;
+ double new_base=0.;
+ int *iarg=(int *)arg;
+ hi->coupling_p=((*iarg)!=0);
+
+ /* Fetching a new template can alter the base_setting, which
+ many other parameters are based on. Right now, the only
+ parameter drawn from the base_setting that can be altered
+ by an encctl is the lowpass, so that is explictly flagged
+ to not be overwritten when we fetch a new template and
+ recompute the dependant settings */
+ new_template = get_setup_template(hi->coupling_p?vi->channels:-1,
+ vi->rate,
+ hi->req,
+ hi->managed,
+ &new_base);
+ if(!new_template)return OV_EIMPL;
+ hi->setup=new_template;
+ hi->base_setting=new_base;
+ vorbis_encode_setup_setting(vi,vi->channels,vi->rate);
+ }
+ return(0);
}
-
-
return(OV_EIMPL);
}
return(OV_EINVAL);