diff options
author | Monty <xiphmont@xiph.org> | 2001-12-04 11:16:23 +0000 |
---|---|---|
committer | Monty <xiphmont@xiph.org> | 2001-12-04 11:16:23 +0000 |
commit | 7ed3a072522aa3879a130068db8f8cc7d3c0c376 (patch) | |
tree | fe5fa56a678cf9f749a75e57a94857a4fafbaf41 | |
parent | c6a4aa086365ea15177ba42511e2fd4f731d6c4c (diff) | |
download | libvorbis-git-7ed3a072522aa3879a130068db8f8cc7d3c0c376.tar.gz |
Continued incremental work
svn path=/branches/branch_monty_20011009/vorbis/; revision=2419
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/bitrate.c | 118 | ||||
-rw-r--r-- | lib/codec_internal.h | 6 | ||||
-rw-r--r-- | lib/modes/Makefile.am | 5 | ||||
-rw-r--r-- | lib/modes/mode_44c_A.h | 41 | ||||
-rw-r--r-- | lib/psy.c | 9 | ||||
-rw-r--r-- | lib/psy.h | 15 | ||||
-rw-r--r-- | lib/registry-api.h | 23 | ||||
-rw-r--r-- | lib/registry.c | 59 | ||||
-rw-r--r-- | lib/vorbisenc.c | 663 |
10 files changed, 834 insertions, 109 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 7e94d55c..8444970d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -16,13 +16,13 @@ libvorbis_la_SOURCES = mdct.c smallft.c block.c envelope.c window.c lsp.c \ envelope.h lpc.h lsp.h codebook.h misc.h psy.h\ masking.h iir.h os.h mdct.h smallft.h\ registry.h scales.h window.h lookup.h lookup_data.h\ - codec_internal.h backends.h bitrate.h + codec_internal.h backends.h bitrate.h libvorbis_la_LDFLAGS = -version-info @V_LIB_CURRENT@:@V_LIB_REVISION@:@V_LIB_AGE@ libvorbisfile_la_SOURCES = vorbisfile.c libvorbisfile_la_LDFLAGS = -version-info @VF_LIB_CURRENT@:@VF_LIB_REVISION@:@VF_LIB_AGE@ -libvorbisenc_la_SOURCES = vorbisenc.c +libvorbisenc_la_SOURCES = vorbisenc.c registry-api.h libvorbisenc_la_LDFLAGS = -version-info @VE_LIB_CURRENT@:@VE_LIB_REVISION@:@VE_LIB_AGE@ EXTRA_PROGRAMS = barkmel tone psytune diff --git a/lib/bitrate.c b/lib/bitrate.c index 4790c0e5..4286e366 100644 --- a/lib/bitrate.c +++ b/lib/bitrate.c @@ -11,7 +11,7 @@ ******************************************************************** function: bitrate tracking and management - last mod: $Id: bitrate.c,v 1.1.2.4 2001/11/24 05:26:10 xiphmont Exp $ + last mod: $Id: bitrate.c,v 1.1.2.5 2001/12/04 11:16:19 xiphmont Exp $ ********************************************************************/ @@ -87,67 +87,70 @@ void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){ codec_setup_info *ci=vi->codec_setup; bitrate_manager_info *bi=ci->bi; long maxlatency; - + memset(bm,0,sizeof(*bm)); - bm->avg_sampledesired=bi->queue_avg_time*vi->rate; - bm->avg_centerdesired=bi->queue_avg_time*vi->rate*bi->queue_avg_center; - bm->minmax_sampledesired=bi->queue_minmax_time*vi->rate; - - if(bm->avg_sampledesired<0)bm->avg_sampledesired=0; - if(bm->avg_centerdesired<0)bm->avg_centerdesired=0; - if(bm->minmax_sampledesired<0)bm->minmax_sampledesired=0; - - /* first find the max possible needed queue size */ - maxlatency=max(bm->avg_sampledesired-bm->avg_centerdesired, - bm->minmax_sampledesired)+bm->avg_centerdesired; - - if(maxlatency>0 && - (bi->queue_avgmin>0 || bi->queue_avgmax>0 || bi->queue_hardmax>0 || - bi->queue_hardmin>0)){ - long maxpackets=maxlatency/(ci->blocksizes[0]>>1)+3; - long bins=BITTRACK_DIVISOR*ci->passlimit[ci->coupling_passes-1]; + if(bi){ + + bm->avg_sampledesired=bi->queue_avg_time*vi->rate; + bm->avg_centerdesired=bi->queue_avg_time*vi->rate*bi->queue_avg_center; + bm->minmax_sampledesired=bi->queue_minmax_time*vi->rate; + + if(bm->avg_sampledesired<0)bm->avg_sampledesired=0; + if(bm->avg_centerdesired<0)bm->avg_centerdesired=0; + if(bm->minmax_sampledesired<0)bm->minmax_sampledesired=0; - bm->queue_size=maxpackets; - bm->queue_bins=bins; - bm->queue_binned=_ogg_malloc(maxpackets*bins*sizeof(*bm->queue_binned)); - bm->queue_actual=_ogg_malloc(maxpackets*sizeof(*bm->queue_actual)); + /* first find the max possible needed queue size */ + maxlatency=max(bm->avg_sampledesired-bm->avg_centerdesired, + bm->minmax_sampledesired)+bm->avg_centerdesired; - if((bi->queue_avgmin>0 || bi->queue_avgmax>0) && - bi->queue_avg_time>0){ + if(maxlatency>0 && + (bi->queue_avgmin>0 || bi->queue_avgmax>0 || bi->queue_hardmax>0 || + bi->queue_hardmin>0)){ + long maxpackets=maxlatency/(ci->blocksizes[0]>>1)+3; + long bins=BITTRACK_DIVISOR*ci->passlimit[ci->coupling_passes-1]; - bm->avg_binacc=_ogg_malloc(bins*sizeof(*bm->avg_binacc)); - bm->avgfloat=bi->avgfloat_initial; + bm->queue_size=maxpackets; + bm->queue_bins=bins; + bm->queue_binned=_ogg_malloc(maxpackets*bins*sizeof(*bm->queue_binned)); + bm->queue_actual=_ogg_malloc(maxpackets*sizeof(*bm->queue_actual)); + if((bi->queue_avgmin>0 || bi->queue_avgmax>0) && + bi->queue_avg_time>0){ + + bm->avg_binacc=_ogg_malloc(bins*sizeof(*bm->avg_binacc)); + bm->avgfloat=bi->avgfloat_initial; + + + }else{ + bm->avg_tail= -1; + } - }else{ - bm->avg_tail= -1; - } - - if((bi->queue_hardmin>0 || bi->queue_hardmax>0) && + if((bi->queue_hardmin>0 || bi->queue_hardmax>0) && bi->queue_minmax_time>0){ - - bm->minmax_binstack=_ogg_malloc((bins+1)*bins*2* - sizeof(bm->minmax_binstack)); - bm->minmax_posstack=_ogg_malloc((bins+1)* + + bm->minmax_binstack=_ogg_malloc((bins+1)*bins*2* + sizeof(bm->minmax_binstack)); + bm->minmax_posstack=_ogg_malloc((bins+1)* sizeof(bm->minmax_posstack)); - bm->minmax_limitstack=_ogg_malloc((bins+1)* - sizeof(bm->minmax_limitstack)); + bm->minmax_limitstack=_ogg_malloc((bins+1)* + sizeof(bm->minmax_limitstack)); + }else{ + bm->minmax_tail= -1; + } + + /* space for the packet queueing */ + bm->queue_packet_buffers=calloc(maxpackets,sizeof(*bm->queue_packet_buffers)); + bm->queue_packets=calloc(maxpackets,sizeof(*bm->queue_packets)); + for(i=0;i<maxpackets;i++) + oggpack_writeinit(bm->queue_packet_buffers+i); + }else{ - bm->minmax_tail= -1; - } - - /* space for the packet queueing */ - bm->queue_packet_buffers=calloc(maxpackets,sizeof(*bm->queue_packet_buffers)); - bm->queue_packets=calloc(maxpackets,sizeof(*bm->queue_packets)); - for(i=0;i<maxpackets;i++) - oggpack_writeinit(bm->queue_packet_buffers+i); - - }else{ - bm->queue_packet_buffers=calloc(1,sizeof(*bm->queue_packet_buffers)); - bm->queue_packets=calloc(1,sizeof(*bm->queue_packets)); - oggpack_writeinit(bm->queue_packet_buffers); - } + bm->queue_packet_buffers=calloc(1,sizeof(*bm->queue_packet_buffers)); + bm->queue_packets=calloc(1,sizeof(*bm->queue_packets)); + oggpack_writeinit(bm->queue_packet_buffers); + } + } } void vorbis_bitrate_clear(bitrate_manager_state *bm){ @@ -322,7 +325,7 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ bm->avg_centeracc-=samples; bm->avg_center++; - if(bm->noisetrigger_postpone)bm->noisetrigger_postpone--; + if(bm->noisetrigger_postpone)bm->noisetrigger_postpone-=samples; if(bm->avg_center>=bm->queue_size)bm->avg_center=0; } new_minmax_head=bm->avg_center; @@ -334,18 +337,18 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ if(bm->avgfloat>bi->avgfloat_noise_hightrigger) bm->noisetrigger_request-=1.f; - if(bm->noisetrigger_postpone==0){ + if(bm->noisetrigger_postpone<=0){ if(bm->noisetrigger_request<0.){ bm->avgnoise-=1.f; if(bm->noisetrigger_request<bm->avg_sampleacc/2) bm->avgnoise-=1.f; - bm->noisetrigger_postpone=bm->avg_sampleacc; + bm->noisetrigger_postpone=bm->avg_sampleacc/2; } if(bm->noisetrigger_request>0.){ bm->avgnoise+=1.f; if(bm->noisetrigger_request>bm->avg_sampleacc/2) bm->avgnoise+=1.f; - bm->noisetrigger_postpone=bm->avg_sampleacc; + bm->noisetrigger_postpone=bm->avg_sampleacc/2; } /* we generally want the noise bias to drift back to zero */ @@ -360,6 +363,9 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ if(bm->avgnoise>bi->avgfloat_noise_maxval) bm->avgnoise=bi->avgfloat_noise_maxval; } + fprintf(stderr,"noise:%f req:%d trigger:%d\n",bm->avgnoise, + bm->noisetrigger_request,bm->noisetrigger_postpone); + } }else{ /* if we're not using an average tracker, the 'float' is nailed to diff --git a/lib/codec_internal.h b/lib/codec_internal.h index d2a5bed7..71b297cd 100644 --- a/lib/codec_internal.h +++ b/lib/codec_internal.h @@ -10,7 +10,7 @@ ******************************************************************** function: libvorbis codec headers - last mod: $Id: codec_internal.h,v 1.9.4.6 2001/11/22 06:21:07 xiphmont Exp $ + last mod: $Id: codec_internal.h,v 1.9.4.7 2001/12/04 11:16:19 xiphmont Exp $ ********************************************************************/ @@ -111,8 +111,8 @@ typedef struct codec_setup_info { static_codebook *book_param[256]; vorbis_info_psy *psy_param[64]; /* encode only */ - vorbis_info_psy_global *psy_g_param; - bitrate_manager_info *bi; + vorbis_info_psy_global psy_g_param; + bitrate_manager_info bi; int passlimit[32]; /* iteration limit per couple/quant pass */ int coupling_passes; diff --git a/lib/modes/Makefile.am b/lib/modes/Makefile.am new file mode 100644 index 00000000..803fd232 --- /dev/null +++ b/lib/modes/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = foreign + +EXTRA_DIST = floor_44.h psych_44.h residue_44.h diff --git a/lib/modes/mode_44c_A.h b/lib/modes/mode_44c_A.h index cc0b670c..ef015e50 100644 --- a/lib/modes/mode_44c_A.h +++ b/lib/modes/mode_44c_A.h @@ -11,7 +11,7 @@ ******************************************************************** function: predefined encoding modes; 44kHz stereo ~64kbps true VBR - last mod: $Id: mode_44c_A.h,v 1.4.2.11 2001/11/24 05:26:11 xiphmont Exp $ + last mod: $Id: mode_44c_A.h,v 1.4.2.12 2001/12/04 11:16:23 xiphmont Exp $ ********************************************************************/ @@ -81,18 +81,7 @@ #include "maskadj_A.h" static bitrate_manager_info _bm_set_44c_A={ - /* progressive coding and bitrate controls */ - 2.,.5, - //2., 128000, 128000, - // 128000, 128000, - - 2., 0, 0, - 0, 0, - - 4.0, 0., -1., .05, - -.05, .05, - 3.0,5.0, - -10.f,+4.f + 0 }; static vorbis_info_psy_global _psy_set_44c_AG={ @@ -100,7 +89,7 @@ static vorbis_info_psy_global _psy_set_44c_AG={ 8, /* lines per eighth octave */ /* thresh sample period, preecho clamp trigger threshhold, range, minenergy */ - 256, {26.f,26.f,26.f,30.f}, {-30.f,-30.f,-30.f,-34.f}, -90.f, + 256, {26.f,26.f,26.f,30.f}, {-26.f,-26.f,-26.f,-30.f}, -90.f, -6.f, 0, @@ -108,18 +97,6 @@ static vorbis_info_psy_global _psy_set_44c_AG={ static struct vp_couple_pass _psy_pass_44c_A0[]={ {1.f,1.f, - {{ 24, 0, 9e10, 0}, - {9999, 0, 9e10, 4.5}} - }, - {1.f,1.f, - {{ 64, 0, 9e10, 0}, - {9999, 0, 9e10, 2.5}} - }, - {.333333f,3.f, - {{ 64, 0, 9e10, 0}, - {9999, 0, 9e10, 2.5}} - }, - {.111111f,9.f, {{ 64, 0, 9e10, 0}, {9999, 0, 9e10, 2.5}} }, @@ -127,18 +104,6 @@ static struct vp_couple_pass _psy_pass_44c_A0[]={ static vp_couple_pass _psy_pass_44c_A[]={ {1.f,1.f, - {{ 288, 0, 9e10, 0}, - {9999, 0, 9e10, 4.5}} - }, - {1.f,1.f, - {{ 512, 0, 9e10, 0}, - {9999, 0, 9e10, 2.5}} - }, - {.333333f,3.f, - {{ 512, 0, 9e10, 0}, - {9999, 0, 9e10, 2.5}} - }, - {.111111f,9.f, {{ 512, 0, 9e10, 0}, {9999, 0, 9e10, 2.5}} }, @@ -11,7 +11,7 @@ ******************************************************************** function: psychoacoustics not including preecho - last mod: $Id: psy.c,v 1.56.2.4 2001/11/16 08:17:05 xiphmont Exp $ + last mod: $Id: psy.c,v 1.56.2.5 2001/12/04 11:16:19 xiphmont Exp $ ********************************************************************/ @@ -69,6 +69,13 @@ void _vp_global_free(vorbis_look_psy_global *look){ _ogg_free(look); } +void _vi_gpsy_free(vorbis_info_psy_global *i){ + if(i){ + memset(i,0,sizeof(*i)); + _ogg_free(i); + } +} + void _vi_psy_free(vorbis_info_psy *i){ if(i){ memset(i,0,sizeof(*i)); @@ -11,7 +11,7 @@ ******************************************************************** function: random psychoacoustics (not including preecho) - last mod: $Id: psy.h,v 1.24.2.4 2001/11/16 08:17:07 xiphmont Exp $ + last mod: $Id: psy.h,v 1.24.2.5 2001/12/04 11:16:19 xiphmont Exp $ ********************************************************************/ @@ -59,7 +59,7 @@ typedef struct vp_attenblock{ #define NOISE_COMPAND_LEVELS 40 typedef struct vorbis_info_psy{ - float *ath; + float ath[27]; float ath_adjatt; float ath_maxatt; @@ -67,11 +67,11 @@ typedef struct vorbis_info_psy{ float tone_masteratt; float tone_guard; float tone_abs_limit; - vp_attenblock *toneatt; + vp_attenblock toneatt; int peakattp; int curvelimitp; - vp_attenblock *peakatt; + vp_attenblock peakatt; int noisemaskp; float noisemaxsupp; @@ -81,16 +81,15 @@ typedef struct vorbis_info_psy{ int noisewindowhimin; int noisewindowfixed; float noiseoff[P_BANDS]; - float *noisecompand; + float noisecompand[NOISE_COMPAND_LEVELS]; float max_curve_dB; - vp_couple_pass *couple_pass; + vp_couple_pass couple_pass[8]; } vorbis_info_psy; typedef struct{ - float decaydBpms; int eighth_octave_lines; /* for block long/short tuning; encode only */ @@ -108,8 +107,6 @@ typedef struct{ typedef struct { float ampmax; - float **decay; - int decaylines; int channels; vorbis_info_psy_global *gi; diff --git a/lib/registry-api.h b/lib/registry-api.h new file mode 100644 index 00000000..0f6ef7f0 --- /dev/null +++ b/lib/registry-api.h @@ -0,0 +1,23 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * 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-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + * * + ******************************************************************** + + function: registry exposure + last mod: $Id: registry-api.h,v 1.1.2.1 2001/12/04 11:16:20 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_REGAPI_H_ +#define _V_REGAPI_H_ + +extern void residue_free_info(vorbis_info_residue *r,int type); + +#endif diff --git a/lib/registry.c b/lib/registry.c new file mode 100644 index 00000000..2ab78e56 --- /dev/null +++ b/lib/registry.c @@ -0,0 +1,59 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * 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-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + + ******************************************************************** + + function: registry for time, floor, res backends and channel mappings + last mod: $Id: registry.c,v 1.10.2.1 2001/12/04 11:16:20 xiphmont Exp $ + + ********************************************************************/ + +#include "vorbis/codec.h" +#include "codec_internal.h" +#include "registry.h" +#include "registry_api.h" +#include "misc.h" + + +/* seems like major overkill now; the backend numbers will grow into + the infrastructure soon enough */ + +extern vorbis_func_time time0_exportbundle; +extern vorbis_func_floor floor0_exportbundle; +extern vorbis_func_floor floor1_exportbundle; +extern vorbis_func_residue residue0_exportbundle; +extern vorbis_func_residue residue1_exportbundle; +extern vorbis_func_residue residue2_exportbundle; +extern vorbis_func_mapping mapping0_exportbundle; + +vorbis_func_time *_time_P[]={ + &time0_exportbundle, +}; + +vorbis_func_floor *_floor_P[]={ + &floor0_exportbundle, + &floor1_exportbundle, +}; + +vorbis_func_residue *_residue_P[]={ + &residue0_exportbundle, + &residue1_exportbundle, + &residue2_exportbundle, +}; + +vorbis_func_mapping *_mapping_P[]={ + &mapping0_exportbundle, +}; + +/* make Windows happy; can't access the registry directly outside of + libvorbis, and vorbisenc needs a few functions */ +void residue_free_info(vorbis_info_residue *r,int type){ + _residue_P[type]->free_info(r); +} diff --git a/lib/vorbisenc.c b/lib/vorbisenc.c new file mode 100644 index 00000000..af28212b --- /dev/null +++ b/lib/vorbisenc.c @@ -0,0 +1,663 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * 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-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + + ******************************************************************** + + function: simple programmatic interface for encoder mode setup + last mod: $Id: vorbisenc.c,v 1.17.2.1 2001/12/04 11:16:20 xiphmont Exp $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "vorbis/codec.h" +#include "vorbis/vorbisenc.h" + +#include "codec_internal.h" +#include "registry-api.h" + +#include "os.h" +#include "misc.h" + +/* careful with this; it's using static array sizing to make managing + all the modes a little less annoying. If we use a residue backend + with > 10 partition types, or a different division of iteration, + this needs to be updated. */ +typedef struct { + vorbis_info_residue0 *res; + static_codebook *book_aux[2]; + static_codebook *books_base[6][10][3]; + static_codebook *books_stereo_backfill[6][10]; + static_codebook *books_residue_backfill[6][10][2]; +} vorbis_residue_template; + +#include "modes/residue_44.h" +#include "modes/psych_44.h" +#include "modes/floor_44.h" + +/* a few static coder conventions */ +static vorbis_info_time0 _time_dummy={0}; +static vorbis_info_mode _mode_set_short={0,0,0,0}; +static vorbis_info_mode _mode_set_long={1,0,0,1}; + +/* mapping conventions: + only one submap (this would change for efficient 5.1 support for example) +/* three psychoacoustic profiles are used: One for + short blocks, and two for long blocks (transition and regular) */ +static vorbis_info_mapping0 _mapping_set_short={ + 1, {0,0}, {0}, {0}, {0}, {0,0}, 0,{0},{0}}; +static vorbis_info_mapping0 _mapping_set_long={ + 1, {0,0}, {0}, {1}, {1}, {1,2}, 0,{0},{0}}; + +static int vorbis_encode_toplevel_init(vorbis_info *vi,int small,int large,int ch,long rate){ + if(vi && vi->codec_setup){ + codec_setup_info *ci=vi->ci; + + vi->version=0; + vi->channels=ch; + vi->rate=rate; + + ci->blocksizes[0]=small; + ci->blocksizes[1]=large; + + /* time mapping hooks are unused in vorbis I */ + ci->times=1; + ci->time_type[0]=0; + ci->time_param[0]=&time_dummy; + + /* by convention, two modes: one for short, one for long blocks. + short block mode uses mapping sero, long block uses mapping 1 */ + ci->modes=2; + ci->mode_param[0]=&_mode_set_short; + ci->mode_param[1]=&_mode_set_long; + + /* by convention two mappings, both mapping type zero (polyphonic + PCM), first for short, second for long blocks */ + ci->maps=2; + ci->map_type[0]=0; + ci->map_param[0]=&_mapping_set_short; + ci->map_type[1]=0; + ci->map_param[1]=&_mapping_set_short; + + return(0); + } + return(OV_EINVAL); +} + +static int vorbis_encode_floor_init(vorbis_info *vi,double q,int block, + static_codebook **books, + vorbis_info_floor1 **in, + ...){ + int x[11],i,k,iq=rint(q*10); + vorbis_info_floor1 *f=calloc(1,sizeof(*f)); + codec_setup_info *ci=vi->ci; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + x[i]=va_arg(ap,int); + va_end(ap); + + memcpy(f,in[x[iq]],sizoef(*f)); + /* fill in the lowpass field, even if it's temporary */ + f->n=ci->blocksizes[block]>>1; + + /* books */ + { + int partitions=f->partitions; + int maxclass=-1; + int maxbook=-1; + for(i=0;i<partitions;i++) + if(f->partitionclass[i]>maxclass)maxclass=f->partitionclass[i]; + for(i=0;i<maxclass;i++){ + if(f->class_book[i]>maxbook)maxbook=f->class_book[i]; + f->class_book[i]+=ci->books; + for(k=0;k<(1<<info->class_subs[i]);k++){ + if(f->class_subbook[i][k]>maxbook)maxbook=f->class_subbook[i][k]; + f->class_subbook[i][k]+=ci->books; + } + } + + for(i=0;i<=maxbook;i++) + ci->book_param[ci->books++]=books[x[iq]][i]; + } + + /* for now, we're only using floor 1 */ + vi->floor_type[vi->floors]=1; + vi->floor_param[vi->floors]=f; + vi->floors++; + + return(0); +} + +static int vorbis_encode_global_psych_init(vorbis_info *vi,double q, + vorbis_info_psy_global **in, ...){ + int i,iq=q*10; + double x[11],dq; + codec_setup_info *ci=vi->ci; + vorbis_info_psy_global *g=&ci->g; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + x[i]=va_arg(ap,double); + va_end(ap); + + if(iq==10){ + iq=9; + dq=1.; + }else{ + dq=q*10.-iq; + } + + memcpy(g,in[(int)x[iq]],sizeof(*g)); + + /* interpolate the trigger threshholds */ + for(i=0;i<4;i++){ + g->preecho_thresh[i]=in[iq]->preecho_thresh[i]*(1.-dq)+in[iq+1]->preecho_thresh[i]*dq; + g->preecho_thresh[i]=in[iq]->postecho_thresh[i]*(1.-dq)+in[iq+1]->postecho_thresh[i]*dq; + } + g->ampmax_att_per_sec=in[iq]->ampmax_att_per_sec*(1.-dq)+in[iq+1]->ampmax_att_per_sec*dq; + return(0); +} + +static int vorbis_encode_psyset_init(vorbis_info *vi,double q,int block, + vorbis_info_psy *in, ...){ + int i,j,iq=q*10; + double x[11],dq; + codec_setup_info *ci=vi->ci; + vorbis_info_psy *p=&ci->psy_param[block]; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + x[i]=va_arg(ap,double); + va_end(ap); + + if(iq==10){ + iq=9; + dq=1.; + }else{ + dq=q*10.-iq; + } + + if(block>=ci->psys) + ci->psys=block+1; + if(!p){ + p=calloc(1,sizeof(*p)); + ci->psy_params[block]=p; + } + + memcpy(p,in[(int)(q*10.)],sizeof(*p)); + + p->ath_adjatt=in[iq]->ath_adjatt*(1.-dq)+in[iq+1]->ath_adjatt*dq; + p->ath_maxatt=in[iq]->ath_maxatt*(1.-dq)+in[iq+1]->ath_maxatt*dq; + + p->tone_masteratt=in[iq]->tone_masteratt*(1.-dq)+in[iq+1]->tone_masteratt*dq; + p->tone_guard=in[iq]->tone_guard*(1.-dq)+in[iq+1]->tone_guard*dq; + p->tone_abs_limit=in[iq]->tone_abs_limit*(1.-dq)+in[iq+1]->tone_abs_limit*dq; + + p->noisemaxsupp=in[iq]->noisemaxsupp*(1.-dq)+in[iq+1]->noisemaxsupp*dq; + +} + +static int vorbis_encode_compand_init(vorbis_info *vi,double q,int block, + float **in, ...){ + int i,iq=q*10; + double x[11],dq; + codec_setup_info *ci=vi->ci; + vorbis_info_psy *p=&ci->psy_param[block]; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + x[i]=va_arg(ap,double); + va_end(ap); + + if(iq==10){ + iq=9; + dq=1.; + }else{ + dq=q+10.-iq; + } + + /* interpolate the compander settings */ + for(i=0;i<NOISE_COMPAND_LEVELS;i++) + p->noisecompand[i]=in[iq][i]*(1.-dq)+in[iq+1][i]*dq; +} + +static int vorbis_encode_tonemask_init(vorbis_info *vi,double q,int block, + int ***in, ...){ + int i,j,iq=q*10; + double x[11],dq; + codec_setup_info *ci=vi->ci; + vorbis_info_psy *p=&ci->psy_param[block]; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + x[i]=va_arg(ap,double); + va_end(ap); + + if(iq==10){ + iq=9; + dq=1.; + }else{ + dq=q*10.-iq; + } + + for(i=0;i<P_BANDS;i++) + for(j=0;j<P_LEVELS;j++) + p->toneatt[i][j]=(j<4?4:j)*-10.+ + in[iq][i][j]*(1.-dq)+in[iq+1][i][j]*dq; +} + +static int vorbis_encode_peak_init(vorbis_info *vi,double q,int block, + int ***in, ...){ + int i,j,iq=q*10; + double x[11],dq; + codec_setup_info *ci=vi->ci; + vorbis_info_psy *p=&ci->psy_param[block]; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + x[i]=va_arg(ap,double); + va_end(ap); + + if(iq==10){ + iq=9; + dq=1.; + }else{ + dq=q*10.-iq; + } + + for(i=0;i<P_BANDS;i++) + for(j=0;j<P_LEVELS;j++) + p->peakatt[i][j]=(j<4?4:j)*-10.+ + in[iq][i][j]*(1.-dq)+in[iq+1][i][j]*dq; +} + +static int vorbis_encode_noisebias_init(vorbis_info *vi,double q,int block, + int **in, ...){ + int i,iq=q*10; + double x[11],dq; + codec_setup_info *ci=vi->ci; + vorbis_info_psy *p=&ci->psy_param[block]; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + x[i]=va_arg(ap,double); + va_end(ap); + + if(iq==10){ + iq=9; + dq=1.; + }else{ + dq=q*10.-iq; + } + + for(i=0;i<P_BANDS;i++) + p->noiseoff[i]=in[iq][i]*(1.-dq)+in[iq+1][i]*dq; +} + +static int vorbis_encode_ath_init(vorbis_info *vi,double q,int block, + float **in, ...){ + int i,iq=q*10; + double x[11],dq; + codec_setup_info *ci=vi->ci; + vorbis_info_psy *p=&ci->psy_param[block]; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + x[i]=va_arg(ap,double); + va_end(ap); + + if(iq==10){ + iq=9; + dq=1.; + }else{ + dq=q*10.-iq; + } + + for(i=0;i<P_BANDS;i++) + p->ath[i]=in[iq][i]*(1.-dq)+in[iq+1][i]*dq; +} + +static double stereo_threshholds[]={0.0, 2.5, 4.5, 7.5, 12.5, 22.5}; +static int vorbis_encode_residue_init(vorbis_info *vi,double q,int block, + vorbis_residue_template *in, ...){ + + int i,iq=q*10; + int t[11]; + int a[11]; + double c[11]; + double dq; + int coupled_p; + int stereo_backfill_p; + int residue_backfill_p; + int type; + int n; + int partition_position; + int res_position; + int iterations=1; + double amplitude; + int amplitude_select; + + codec_setup_info *ci=vi->ci; + vorbis_info_residue *r; + vorbis_info_psy *psy=ci->psys+block; + va_list ap; + + va_start(ap,in); + for(i=0;i<11;i++) + t[i]=va_arg(ap,int); + coupled_p=va_arg(ap,int); + stereo_backfill_p=va_arg(ap,int); + residue_backfill_p=va_arg(ap,int); + for(i=0;i<11;i++) + a[i]=va_arg(ap,int); + for(i=0;i<11;i++) + c[i]=va_arg(ap,double); + va_end(ap); + + /* may be re-called due to ctl */ + if(ci->residue_param[block]) + /* free preexisting instance */ + residue_free_info(ci->residue_param[block],ci->residue_type[block]); + + r=ci->residue_param[block]=malloc(sizeof(*r)); + memcpy(r,in[t[iq]],sizeof(*r)); + + n=r->end=ci->blocksizes[block?1:0]>>1; /* to be adjusted by lowpass later */ + + if(block){ + r->grouping=32; + }else{ + r->grouping=16; + } + + res_position=rint((double)c[iq]*1000/vi->rate*n); + partition_position=res_position/r->grouping; + for(i=0;i<r->partitions;i++) + if(r->blimit[i]<0)r->blimit[i]=partition_position; + + /* for uncoupled, we use type 1, else type 2 */ + if(coupled_p){ + ci->map_param[block].coupling_steps=1; + ci->map_param[block].coupling_mag[0]=0; + ci->map_param[block].coupling_ang[0]=1; + + ci->residue_type[block]=2; + + psy->couple_pass[0]={1.,1., {{-1, 1,9e10, 0},{9999, 1,9e10, -1}}}; + psy->couple_pass[0].couple_pass[0].limit=res_position; + ci->passlimit[0]=3; + amplitude_select=a[qi]; + amplitude=psy->couple_pass[0].couple_pass[1].limit=stereo_threshholds[a[qi]]; + + if(stereo_backfill_p && a[qi]){ + psy->couple_pass[1]={1.,1., {{-1, 1,9e10, 0},{9999, 1,9e10, -1}}}; + psy->couple_pass[1].couple_pass[0].limit=res_position; + amplitude_select=a[qi]-1; + amplitude=psy->couple_pass[1].couple_pass[1].limit=stereo_threshholds[a[qi]-1]; + psy->passlimit[1]=4; + for(i=0;i<r->partitions;i++) + if(in[qi].books_stereo_backfill[a[qi]-1][i]) + r->secondstages[i]|=8; + iterations++; + } + + if(residue_backfill_p){ + psy->couple_pass[iterations]={.33333333,3., {{-1, 1,1., 0},{9999, 1,9e10, -1}}}; + psy->couple_pass[iterations].couple_pass[0].limit=res_position; + psy->couple_pass[iterations].couple_pass[1].limit=amplitude; + ci->passlimit[iterations]=ci->passlimit[iterations-1]+1; + for(i=0;i<r->partitions;i++) + if(in[qi].books_residue_backfill[amplitude_select][i][0]) + r->secondstages[i]|=(1<<(iterations+2)); + iterations++; + psy->couple_pass[iterations]={.11111111,9., {{-1, 1,.3, 0},{9999, 1,9e10, -1}}}; + psy->couple_pass[iterations].couple_pass[0].limit=res_position; + psy->couple_pass[iterations].couple_pass[1].limit=amplitude; + ci->passlimit[iterations]=r->passlimit[iterations-1]+1; + for(i=0;i<r->partitions;i++) + if(in[qi].books_residue_backfill[amplitude_select][i][1]) + r->secondstages[i]|=(1<<(iterations+2)); + iterations++; + } + ci->coupling_passes=iterations; + + if(block) + memcpy(ci->psys+block+1,psy,sizeof(*psy)); + + }else{ + ci->residue_type[block]=1; + + ci->passlimit[0]=3; + + if(residue_backfill_p){ + for(i=0;i<r->partitions;i++){ + if(in[qi].books_residue_backfill[amplitude_select][i][0]) + r->secondstages[i]|=8; + if(in[qi].books_residue_backfill[amplitude_select][i][1]) + r->secondstages[i]|=16; + } + ci->passlimit[1]=4; + ci->passlimit[2]=5; + ci->coupling_passes=3; + }else + ci->coupling_passes=1; + } + + /* fill in all the books */ + { + int booklist=0; + r->groupbook=ci->books; + ci->book_param[ci->books++]=in[qi].book_aux[block]; + for(i=0;i<r->partitions;i++){ + for(k=0;k<3;k++){ + if(in[qi].books_base[a[qi]][i][k]){ + r->booklist[booklist++]=ci->books; + ci->book_param[ci->books++]=in[qi].books_base[a[qi]][i][k]); + } + if(coupled_p && stereo_backfill_p && a[qi] && + in[qi].books_stereo_backfill[a[qi]][i]){ + r->booklist[booklist++]=ci->books; + ci->book_param[ci->books++]=in[qi].books_stereo_backfill[a[qi]][i]; + } + if(residue_backfill_p) + for(k=0;k<2;k++){ + if(in[qi].books_residue_backfill[amplitude_select][i][k]){ + r->booklist[booklist++]=ci->books; + ci->book_param[ci->books++]=in[qi].books_residue_backfill[amplitude_select][i][k]; + } + } + } + } + + return(0); +} + +static int vorbis_encode_lowpass_init(vorbis_info *vi,double q,int block,...){ + int i,iq=q*10; + double x[11],dq; + double freq; + codec_setup_info *ci=vi->ci; + vorbis_info_floor1 *f=ci->floor_param+block; + vorbis_info_residue0 *r=ci->residue_param+block; + int blocksize=ci->blocksizes[block]>>1; + double nyq=vi->rate/2.; + va_list ap; + + va_start(ap,block); + for(i=0;i<11;i++) + x[i]=va_arg(ap,double); + va_end(ap); + + if(iq==10){ + iq=9; + dq=1.; + }else{ + dq=q*10.-iq; + } + + freq=x[iq]*(1.-dq)+x[iq+1]*dq; + + /* lowpass needs to be set in the floor and the residue. */ + + /* 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; + + /* 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[block]==2) + r->end=((freq/nyq*blocksize*2)/r->grouping+.9)* /* round up only if we're well past */ + r->grouping; + else + r->end=((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */ + r->grouping; + return(0); +} + +/* encoders will need to use vorbis_info_init beforehand and call + vorbis_info clear when all done */ + +int vorbis_encode_init_vbr(vorbis_info *vi, + long channels, + long rate, + + float base_quality /* 0. to 1. */ + ){ + int ret=0; + + if(rate>40000){ + ret|=vorbis_encode_toplevel_init(vi,256,2048,channels,rate); + ret|=vorbis_encode_floor_init(vi,base_quality,0,_floor_44_128_books,_floor_44_128, + 0,0,0,1,1,1,1,1,1,1,1); + ret|=vorbis_encode_floor_init(vi,base_quality,1,_floor_44_1024_books,_floor_44_1024, + 0,0,0,0,0,0,0,0,0,0,0); + + ret|=vorbis_encode_global_psych_init(vi,base_quality,_psy_global_44, + 0., 0., .5, 1., 1., 1., 1., 1., 1., 1., 1.); + + ret|=vorbis_encode_psyset_init(vi,base_quality,0,_psy_settings, + 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.); + ret|=vorbis_encode_psyset_init(vi,base_quality,1,_psy_settings, + 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.); + ret|=vorbis_encode_psyset_init(vi,base_quality,2,_psy_settings, + 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.); + + ret|=vorbis_encode_tonemask_init(vi,base_quality,0,_vp_tonemask_adj_otherblock, + 0., .5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5.); + ret|=vorbis_encode_tonemask_init(vi,base_quality,1,_vp_tonemask_adj_otherblock, + 0., .5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5.); + ret|=vorbis_encode_tonemask_init(vi,base_quality,2,_vp_tonemask_adj_longblock, + 0., .5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5.); + + ret|=vorbis_encode_compand_init(vi,base_quality,0,_psy_compand_44, + 1., 1., 1.3, 1.6, 2., 2., 2., 2., 2., 2., 2.); + ret|=vorbis_encode_compand_init(vi,base_quality,1,_psy_compand_44, + 1., 1., 1.3, 1.6, 2., 2., 2., 2., 2., 2., 2.); + ret|=vorbis_encode_compand_init(vi,base_quality,2,_psy_compand_44, + 1., 1., 1.3, 1.6, 2., 2., 2., 2., 2., 2., 2.); + + ret|=vorbis_encode_peak_init(vi,base_quality,0,_vp_peakguard, + 0., .5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5.); + ret|=vorbis_encode_peak_init(vi,base_quality,1,_vp_peakguard, + 0., .5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5.); + ret|=vorbis_encode_peak_init(vi,base_quality,2,_vp_peakguard, + 0., .5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5.); + + ret|=vorbis_encode_noisebias_init(vi,base_quality,0,_vp_noisebias_other, + 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.); + ret|=vorbis_encode_noisebias_init(vi,base_quality,1,_vp_noisebias_other, + 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.); + ret|=vorbis_encode_noisebias_init(vi,base_quality,2,_vp_noisebias_long, + 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.); + + ret|=vorbis_encode_ath_init(vi,base_quality,0,ATH_Bark_dB, + 0., 0., 0., 0., 0., .5, 1., 1., 1.5, 2., 2.); + ret|=vorbis_encode_ath_init(vi,base_quality,1,ATH_Bark_dB, + 0., 0., 0., 0., 0., .5, 1., 1., 1.5, 2., 2.); + ret|=vorbis_encode_ath_init(vi,base_quality,2,ATH_Bark_dB, + 0., 0., 0., 0., 0., .5, 1., 1., 1.5, 2., 2.); + + if(ret){ + vorbis_info_clear(vi); + return ret; + } + + switch(channels){ + case 2: + /* setup specific to stereo coupling */ + + /* unmanaged, one iteration residue setup */ + ret|=vorbis_encode_residue_init(vi,base_quality,0,_residue_template_44_stereo_temp, + 1, /* coupled */ + 0, /* no mid stereo backfill */ + 0, /* no residue backfill */ + 4, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, + 4., 4., 6., 6., 10., 4., 4., 4., 4., 4., 4.); + + ret|=vorbis_encode_residue_init(vi,base_quality,1,_residue_template_44_stereo_temp, + 1, /* coupled */ + 0, /* no mid stereo backfill */ + 0, /* no residue backfill */ + 4, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, + 4., 6., 6., 10., 10., 4., 4., 4., 4., 4., 4.); + + ret|=vorbis_encode_lowpass_init(vi,base_quality,0, + 15.1,15.9,16.9,17.9.,19.9., + 999.,999.,999.,999.,999.,999.); + ret|=vorbis_encode_lowpass_init(vi,base_quality,1, + 15.1,15.9,16.9,17.9.,19.9., + 999.,999.,999.,999.,999.,999.); + + return(ret); + + break; + default: + return(OV_EIMPL); + + break; + } + return(0); + }else + return(OV_EIMPL); + + if(ret) + vorbis_info_clear(vi); + return(ret); +} + + +int vorbis_encode_init(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate){ + return(OV_EIMPL); +} + +int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ + return(OV_EIMPL); +} + |