summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <xiphmont@xiph.org>2001-12-04 11:16:23 +0000
committerMonty <xiphmont@xiph.org>2001-12-04 11:16:23 +0000
commit7ed3a072522aa3879a130068db8f8cc7d3c0c376 (patch)
treefe5fa56a678cf9f749a75e57a94857a4fafbaf41
parentc6a4aa086365ea15177ba42511e2fd4f731d6c4c (diff)
downloadlibvorbis-git-7ed3a072522aa3879a130068db8f8cc7d3c0c376.tar.gz
Continued incremental work
svn path=/branches/branch_monty_20011009/vorbis/; revision=2419
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/bitrate.c118
-rw-r--r--lib/codec_internal.h6
-rw-r--r--lib/modes/Makefile.am5
-rw-r--r--lib/modes/mode_44c_A.h41
-rw-r--r--lib/psy.c9
-rw-r--r--lib/psy.h15
-rw-r--r--lib/registry-api.h23
-rw-r--r--lib/registry.c59
-rw-r--r--lib/vorbisenc.c663
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}}
},
diff --git a/lib/psy.c b/lib/psy.c
index 15ee8d88..9e57b4b1 100644
--- a/lib/psy.c
+++ b/lib/psy.c
@@ -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));
diff --git a/lib/psy.h b/lib/psy.h
index e286f5bf..018c345b 100644
--- a/lib/psy.h
+++ b/lib/psy.h
@@ -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);
+}
+