diff options
| author | jacqueline <me@jacqueline.id.au> | 2024-02-14 12:21:33 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2024-02-14 12:21:33 +1100 |
| commit | 7ec0ff2589ffd5774e78f9e6b436ea55be45deb1 (patch) | |
| tree | 4bc335bf6474bff2babbcbd4690231320b52520f /lib | |
| parent | b31bc07555fdd862181d8d6ed551163cea89bc62 (diff) | |
| download | tangara-fw-7ec0ff2589ffd5774e78f9e6b436ea55be45deb1.tar.gz | |
Switch to the lowmem tremor branch
in addition to using slightly less memory, this branch also doesn't seem
to have the same issues with `-O2` builds that the main branch has.
Diffstat (limited to 'lib')
49 files changed, 5676 insertions, 7099 deletions
diff --git a/lib/tremor/CMakeLists.txt b/lib/tremor/CMakeLists.txt index 1000fe5f..e44f9084 100644 --- a/lib/tremor/CMakeLists.txt +++ b/lib/tremor/CMakeLists.txt @@ -2,9 +2,7 @@ # # SPDX-License-Identifier: GPL-3.0-only idf_component_register( - SRCS block.c codebook.c floor0.c floor1.c info.c mapping0.c mdct.c registry.c - res012.c sharedbook.c synthesis.c vorbisfile.c window.c - INCLUDE_DIRS "." - REQUIRES "ogg") - -target_compile_options("${COMPONENT_LIB}" PRIVATE -Og) + SRCS bitwise.c codebook.c dsp.c floor0.c floor1.c floor_lookup.c framing.c + info.c mapping0.c mdct.c misc.c res012.c vorbisfile.c + INCLUDE_DIRS ".") +target_compile_options("${COMPONENT_LIB}" PRIVATE -Wno-error=misleading-indentation -Wno-error=maybe-uninitialized -Wno-error=char-subscripts -Wno-error=unused-label) diff --git a/lib/tremor/Makefile.am b/lib/tremor/Makefile.am index 0a4bb2c3..1d18b1a7 100644 --- a/lib/tremor/Makefile.am +++ b/lib/tremor/Makefile.am @@ -1,50 +1,43 @@ AUTOMAKE_OPTIONS = foreign -INCLUDES = -I./ @OGG_CFLAGS@ +INCLUDES = -I./ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = vorbisidec.pc lib_LTLIBRARIES = libvorbisidec.la -libvorbisidec_la_SOURCES = mdct.c block.c window.c \ - synthesis.c info.c \ +libvorbisidec_la_SOURCES = mdct.c dsp.c info.c misc.c \ floor1.c floor0.c vorbisfile.c \ - res012.c mapping0.c registry.c codebook.c \ - sharedbook.c \ + res012.c mapping0.c codebook.c \ + framing.c bitwise.c \ codebook.h misc.h mdct_lookup.h\ - os.h mdct.h block.h ivorbisfile.h lsp_lookup.h\ - registry.h window.h window_lookup.h\ - codec_internal.h backends.h \ + os.h mdct.h ivorbisfile.h lsp_lookup.h\ + window_lookup.h floor_lookup.c \ + codec_internal.h ogg.h \ asm_arm.h ivorbiscodec.h libvorbisidec_la_LDFLAGS = -version-info @V_LIB_CURRENT@:@V_LIB_REVISION@:@V_LIB_AGE@ -libvorbisidec_la_LIBADD = @OGG_LIBS@ -EXTRA_PROGRAMS = ivorbisfile_example iseeking_example +EXTRA_PROGRAMS = ivorbisfile_example CLEANFILES = $(EXTRA_PROGRAMS) $(lib_LTLIBRARIES) ivorbisfile_example_SOURCES = ivorbisfile_example.c ivorbisfile_example_LDFLAGS = -static -ivorbisfile_example_LDADD = libvorbisidec.la @OGG_LIBS@ - -iseeking_example_SOURCES = iseeking_example.c -iseeking_example_LDFLAGS = -static -iseeking_example_LDADD = libvorbisidec.la @OGG_LIBS@ +ivorbisfile_example_LDADD = libvorbisidec.la includedir = $(prefix)/include/tremor -include_HEADERS = ivorbiscodec.h ivorbisfile.h config_types.h +include_HEADERS = ivorbiscodec.h ivorbisfile.h ogg.h os_types.h config_types.h EXTRA_DIST = vorbisidec.pc.in \ - $(srcdir)/doc/*.html $(srcdir)/win32/VS*/libtremor/*.vcproj + $(srcdir)/doc/*.html example: -ln -fs . vorbis $(MAKE) ivorbisfile_example - $(MAKE) iseeking_example debug: - $(MAKE) all CFLAGS="@DEBUG@" + $(MAKE) all CFLAGS="@DEBUG@" profile: $(MAKE) all CFLAGS="@PROFILE@" diff --git a/lib/tremor/TODO b/lib/tremor/TODO new file mode 100644 index 00000000..0e542a37 --- /dev/null +++ b/lib/tremor/TODO @@ -0,0 +1,2 @@ +Add explicit 64 bit integer support rather than relying on compiler +Roll in optional use of bounded heap memory manager diff --git a/lib/tremor/Version_script.in b/lib/tremor/Version_script.in index cf05203c..85d76539 100644 --- a/lib/tremor/Version_script.in +++ b/lib/tremor/Version_script.in @@ -51,7 +51,6 @@ vorbis_synthesis_init; vorbis_synthesis_restart; vorbis_synthesis; - vorbis_synthesis_trackonly; vorbis_synthesis_blockin; vorbis_synthesis_pcmout; vorbis_synthesis_read; diff --git a/lib/tremor/asm_arm.h b/lib/tremor/asm_arm.h index c3bda005..ac2b6899 100644 --- a/lib/tremor/asm_arm.h +++ b/lib/tremor/asm_arm.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -20,7 +20,7 @@ #if !defined(_V_WIDE_MATH) && !defined(_LOW_ACCURACY_) #define _V_WIDE_MATH -static inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT32(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { int lo,hi; asm volatile("smull\t%0, %1, %2, %3" : "=&r"(lo),"=&r"(hi) @@ -29,11 +29,11 @@ static inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { return(hi); } -static inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT31(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { return MULT32(x,y)<<1; } -static inline ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT31_SHIFT15(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { int lo,hi; asm volatile("smull %0, %1, %2, %3\n\t" "movs %0, %0, lsr #15\n\t" @@ -46,9 +46,9 @@ static inline ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { #define MB() asm volatile ("" : : : "memory") -static inline void XPROD32(ogg_int32_t a, ogg_int32_t b, - ogg_int32_t t, ogg_int32_t v, - ogg_int32_t *x, ogg_int32_t *y) +static inline void XPROD32(tremor_ogg_int32_t a, tremor_ogg_int32_t b, + tremor_ogg_int32_t t, tremor_ogg_int32_t v, + tremor_ogg_int32_t *x, tremor_ogg_int32_t *y) { int x1, y1, l; asm( "smull %0, %1, %4, %6\n\t" @@ -64,9 +64,9 @@ static inline void XPROD32(ogg_int32_t a, ogg_int32_t b, *y = y1; } -static inline void XPROD31(ogg_int32_t a, ogg_int32_t b, - ogg_int32_t t, ogg_int32_t v, - ogg_int32_t *x, ogg_int32_t *y) +static inline void XPROD31(tremor_ogg_int32_t a, tremor_ogg_int32_t b, + tremor_ogg_int32_t t, tremor_ogg_int32_t v, + tremor_ogg_int32_t *x, tremor_ogg_int32_t *y) { int x1, y1, l; asm( "smull %0, %1, %4, %6\n\t" @@ -82,9 +82,9 @@ static inline void XPROD31(ogg_int32_t a, ogg_int32_t b, *y = y1 << 1; } -static inline void XNPROD31(ogg_int32_t a, ogg_int32_t b, - ogg_int32_t t, ogg_int32_t v, - ogg_int32_t *x, ogg_int32_t *y) +static inline void XNPROD31(tremor_ogg_int32_t a, tremor_ogg_int32_t b, + tremor_ogg_int32_t t, tremor_ogg_int32_t v, + tremor_ogg_int32_t *x, tremor_ogg_int32_t *y) { int x1, y1, l; asm( "rsb %2, %4, #0\n\t" @@ -105,7 +105,7 @@ static inline void XNPROD31(ogg_int32_t a, ogg_int32_t b, #ifndef _V_CLIP_MATH #define _V_CLIP_MATH -static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) { +static inline tremor_ogg_int32_t CLIP_TO_15(tremor_ogg_int32_t x) { int tmp; asm volatile("subs %1, %0, #32768\n\t" "movpl %0, #0x7f00\n\t" @@ -123,18 +123,17 @@ static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) { #ifndef _V_LSP_MATH_ASM #define _V_LSP_MATH_ASM -static inline void lsp_loop_asm(ogg_uint32_t *qip,ogg_uint32_t *pip, - ogg_int32_t *qexpp, - ogg_int32_t *ilsp,ogg_int32_t wi, - ogg_int32_t m){ +static inline void lsp_loop_asm(tremor_ogg_uint32_t *qip,tremor_ogg_uint32_t *pip, + tremor_ogg_int32_t *qexpp, + tremor_ogg_int32_t *ilsp,tremor_ogg_int32_t wi, + tremor_ogg_int32_t m){ - ogg_uint32_t qi=*qip,pi=*pip; - ogg_int32_t qexp=*qexpp; + tremor_ogg_uint32_t qi=*qip,pi=*pip; + tremor_ogg_int32_t qexp=*qexpp; asm("mov r0,%3;" - "movs r1,%5,asr#1;" + "mov r1,%5,asr#1;" "add r0,r0,r1,lsl#3;" - "beq 2f;\n" "1:" "ldmdb r0!,{r1,r3};" @@ -157,10 +156,9 @@ static inline void lsp_loop_asm(ogg_uint32_t *qip,ogg_uint32_t *pip, "cmp r0,%3;\n" "bhi 1b;\n" - "2:" // odd filter assymetry "ands r0,%5,#1;\n" - "beq 3f;\n" + "beq 2f;\n" "add r0,%3,%5,lsl#2;\n" "ldr r1,[r0,#-4];\n" @@ -172,7 +170,7 @@ static inline void lsp_loop_asm(ogg_uint32_t *qip,ogg_uint32_t *pip, "umull %1,r3,r0,%1;\n" //pi*=labs(ilsp[j+1]-wi) "cmn r2,r3;\n" // shift down 16? - "beq 3f;\n" + "beq 2f;\n" "add %2,%2,#16;\n" "mov %0,%0,lsr #16;\n" "orr %0,%0,r2,lsl #16;\n" @@ -186,7 +184,7 @@ static inline void lsp_loop_asm(ogg_uint32_t *qip,ogg_uint32_t *pip, //} /* normalize to max 16 sig figs */ - "3:" + "2:" "mov r2,#0;" "orr r1,%0,%1;" "tst r1,#0xff000000;" @@ -216,10 +214,10 @@ static inline void lsp_loop_asm(ogg_uint32_t *qip,ogg_uint32_t *pip, *qexpp=qexp; } -static inline void lsp_norm_asm(ogg_uint32_t *qip,ogg_int32_t *qexpp){ +static inline void lsp_norm_asm(tremor_ogg_uint32_t *qip,tremor_ogg_int32_t *qexpp){ - ogg_uint32_t qi=*qip; - ogg_int32_t qexp=*qexpp; + tremor_ogg_uint32_t qi=*qip; + tremor_ogg_int32_t qexp=*qexpp; asm("tst %0,#0x0000ff00;" "moveq %0,%0,lsl #8;" diff --git a/lib/tremor/autogen.sh b/lib/tremor/autogen.sh index 73c8fca8..e2e6f6b9 100755 --- a/lib/tremor/autogen.sh +++ b/lib/tremor/autogen.sh @@ -2,16 +2,14 @@ # Run this to set up the build system: configure, makefiles, etc. # (based on the version in enlightenment's cvs) -package="vorbisdec" +package="vorbisidec" -olddir=`pwd` srcdir=`dirname $0` test -z "$srcdir" && srcdir=. cd "$srcdir" DIE=0 -echo "checking for autoconf... " (autoconf --version) < /dev/null > /dev/null 2>&1 || { echo echo "You must have autoconf installed to compile $package." @@ -20,72 +18,16 @@ echo "checking for autoconf... " DIE=1 } -VERSIONGREP="sed -e s/.*[^0-9\.]\([0-9]\.[0-9]\).*/\1/" -VERSIONMKINT="sed -e s/[^0-9]//" - -# do we need automake? -if test -r Makefile.am; then - AM_OPTIONS=`fgrep AUTOMAKE_OPTIONS Makefile.am` - AM_NEEDED=`echo $AM_OPTIONS | $VERSIONGREP` - if test x"$AM_NEEDED" = "x$AM_OPTIONS"; then - AM_NEEDED="" - fi - if test -z $AM_NEEDED; then - echo -n "checking for automake... " - AUTOMAKE=automake - ACLOCAL=aclocal - if ($AUTOMAKE --version < /dev/null > /dev/null 2>&1); then - echo "yes" - else - echo "no" - AUTOMAKE= - fi - else - echo -n "checking for automake $AM_NEEDED or later... " - for am in automake-$AM_NEEDED automake$AM_NEEDED automake; do - ($am --version < /dev/null > /dev/null 2>&1) || continue - ver=`$am --version < /dev/null | head -n 1 | $VERSIONGREP | $VERSIONMKINT` - verneeded=`echo $AM_NEEDED | $VERSIONMKINT` - if test $ver -ge $verneeded; then - AUTOMAKE=$am - echo $AUTOMAKE - break - fi - done - test -z $AUTOMAKE && echo "no" - echo -n "checking for aclocal $AM_NEEDED or later... " - for ac in aclocal-$AM_NEEDED aclocal$AM_NEEDED aclocal; do - ($ac --version < /dev/null > /dev/null 2>&1) || continue - ver=`$ac --version < /dev/null | head -n 1 | $VERSIONGREP | $VERSIONMKINT` - verneeded=`echo $AM_NEEDED | $VERSIONMKINT` - if test $ver -ge $verneeded; then - ACLOCAL=$ac - echo $ACLOCAL - break - fi - done - test -z $ACLOCAL && echo "no" - fi - test -z $AUTOMAKE || test -z $ACLOCAL && { +(automake --version) < /dev/null > /dev/null 2>&1 || { echo echo "You must have automake installed to compile $package." - echo "Download the appropriate package for your distribution," - echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" - exit 1 - } -fi + echo "Download the appropriate package for your system," + echo "or get the source from one of the GNU ftp sites" + echo "listed in http://www.gnu.org/order/ftp.html" + DIE=1 +} -echo -n "checking for libtool... " -for LIBTOOLIZE in libtoolize glibtoolize nope; do - ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 && break -done -if test x$LIBTOOLIZE = xnope; then - echo "nope." - LIBTOOLIZE=libtoolize -else - echo $LIBTOOLIZE -fi -($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || { +(libtool --version) < /dev/null > /dev/null 2>&1 || { echo echo "You must have libtool installed to compile $package." echo "Download the appropriate package for your system," @@ -105,16 +47,15 @@ fi echo "Generating configuration files for $package, please wait...." -echo " $ACLOCAL $ACLOCAL_FLAGS" -$ACLOCAL $ACLOCAL_FLAGS || exit 1 -echo " $LIBTOOLIZE --automake" -$LIBTOOLIZE --automake || exit 1 +echo " aclocal $ACLOCAL_FLAGS" +aclocal $ACLOCAL_FLAGS || exit 1 echo " autoheader" autoheader || exit 1 -echo " $AUTOMAKE --add-missing $AUTOMAKE_FLAGS" -$AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1 +echo " libtoolize --automake" +libtoolize --automake || exit 1 +echo " automake --add-missing $AUTOMAKE_FLAGS" +automake --add-missing $AUTOMAKE_FLAGS || exit 1 echo " autoconf" autoconf || exit 1 -cd $olddir -$srcdir/configure --enable-maintainer-mode "$@" && echo +$srcdir/configure "$@" && echo diff --git a/lib/tremor/backends.h b/lib/tremor/backends.h deleted file mode 100644 index 52024219..00000000 --- a/lib/tremor/backends.h +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: backend and mapping structures - - ********************************************************************/ - -/* this is exposed up here because we need it for static modes. - Lookups for each backend aren't exposed because there's no reason - to do so */ - -#ifndef _vorbis_backend_h_ -#define _vorbis_backend_h_ - -#include "codec_internal.h" - -/* this would all be simpler/shorter with templates, but.... */ -/* Transform backend generic *************************************/ - -/* only mdct right now. Flesh it out more if we ever transcend mdct - in the transform domain */ - -/* Floor backend generic *****************************************/ -typedef struct{ - vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *); - vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_mode *, - vorbis_info_floor *); - void (*free_info) (vorbis_info_floor *); - void (*free_look) (vorbis_look_floor *); - void *(*inverse1) (struct vorbis_block *,vorbis_look_floor *); - int (*inverse2) (struct vorbis_block *,vorbis_look_floor *, - void *buffer,ogg_int32_t *); -} vorbis_func_floor; - -typedef struct{ - int order; - long rate; - long barkmap; - - int ampbits; - int ampdB; - - int numbooks; /* <= 16 */ - int books[16]; - -} vorbis_info_floor0; - -#define VIF_POSIT 63 -#define VIF_CLASS 16 -#define VIF_PARTS 31 -typedef struct{ - int partitions; /* 0 to 31 */ - int partitionclass[VIF_PARTS]; /* 0 to 15 */ - - int class_dim[VIF_CLASS]; /* 1 to 8 */ - int class_subs[VIF_CLASS]; /* 0,1,2,3 (bits: 1<<n poss) */ - int class_book[VIF_CLASS]; /* subs ^ dim entries */ - int class_subbook[VIF_CLASS][8]; /* [VIF_CLASS][subs] */ - - - int mult; /* 1 2 3 or 4 */ - int postlist[VIF_POSIT+2]; /* first two implicit */ - -} vorbis_info_floor1; - -/* Residue backend generic *****************************************/ -typedef struct{ - vorbis_info_residue *(*unpack)(vorbis_info *,oggpack_buffer *); - vorbis_look_residue *(*look) (vorbis_dsp_state *,vorbis_info_mode *, - vorbis_info_residue *); - void (*free_info) (vorbis_info_residue *); - void (*free_look) (vorbis_look_residue *); - int (*inverse) (struct vorbis_block *,vorbis_look_residue *, - ogg_int32_t **,int *,int); -} vorbis_func_residue; - -typedef struct vorbis_info_residue0{ -/* block-partitioned VQ coded straight residue */ - long begin; - long end; - - /* first stage (lossless partitioning) */ - int grouping; /* group n vectors per partition */ - int partitions; /* possible codebooks for a partition */ - int partvals; /* partitions ^ groupbook dim */ - int groupbook; /* huffbook for partitioning */ - int secondstages[64]; /* expanded out to pointers in lookup */ - int booklist[512]; /* list of second stage books */ -} vorbis_info_residue0; - -/* Mapping backend generic *****************************************/ -typedef struct{ - vorbis_info_mapping *(*unpack)(vorbis_info *,oggpack_buffer *); - vorbis_look_mapping *(*look) (vorbis_dsp_state *,vorbis_info_mode *, - vorbis_info_mapping *); - void (*free_info) (vorbis_info_mapping *); - void (*free_look) (vorbis_look_mapping *); - int (*inverse) (struct vorbis_block *vb,vorbis_look_mapping *); -} vorbis_func_mapping; - -typedef struct vorbis_info_mapping0{ - int submaps; /* <= 16 */ - int chmuxlist[256]; /* up to 256 channels in a Vorbis stream */ - - int floorsubmap[16]; /* [mux] submap to floors */ - int residuesubmap[16]; /* [mux] submap to residue */ - - int psy[2]; /* by blocktype; impulse/padding for short, - transition/normal for long */ - - int coupling_steps; - int coupling_mag[256]; - int coupling_ang[256]; -} vorbis_info_mapping0; - -#endif - - - - - diff --git a/lib/tremor/bitwise.c b/lib/tremor/bitwise.c new file mode 100644 index 00000000..402b6156 --- /dev/null +++ b/lib/tremor/bitwise.c @@ -0,0 +1,675 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: packing variable sized words into an octet stream + + ********************************************************************/ + +/* We're 'LSb' endian; if we write a word but read individual bits, + then we'll read the lsb first */ + +#include <string.h> +#include <stdlib.h> +#include "misc.h" +#include "tremor_ogg.h" + +static unsigned long mask[]= +{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, + 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, + 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, + 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, + 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, + 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, + 0x3fffffff,0x7fffffff,0xffffffff }; + +/* spans forward, skipping as many bytes as headend is negative; if + headend is zero, simply finds next byte. If we're up to the end + of the buffer, leaves headend at zero. If we've read past the end, + halt the decode process. */ + +static void _span(tremor_oggpack_buffer *b){ + while(b->headend-(b->headbit>>3)<1){ + b->headend-=b->headbit>>3; + b->headbit&=0x7; + + if(b->head->next){ + b->count+=b->head->length; + b->head=b->head->next; + + if(b->headend+b->head->length>0) + b->headptr=b->head->buffer->data+b->head->begin-b->headend; + + b->headend+=b->head->length; + }else{ + /* we've either met the end of decode, or gone past it. halt + only if we're past */ + if(b->headend*8<b->headbit) + /* read has fallen off the end */ + b->headend=-1; + break; + } + } +} + +void tremor_oggpack_readinit(tremor_oggpack_buffer *b,tremor_ogg_reference *r){ + memset(b,0,sizeof(*b)); + + b->tail=b->head=r; + b->count=0; + b->headptr=b->head->buffer->data+b->head->begin; + b->headend=b->head->length; + _span(b); +} + +#define _lookspan() while(!end){\ + head=head->next;\ + if(!head) return -1;\ + ptr=head->buffer->data + head->begin;\ + end=head->length;\ + } + +/* Read in bits without advancing the bitptr; bits <= 32 */ +long tremor_oggpack_look(tremor_oggpack_buffer *b,int bits){ + unsigned long m=mask[bits]; + unsigned long ret; + + bits+=b->headbit; + + if(bits >= b->headend<<3){ + int end=b->headend; + unsigned char *ptr=b->headptr; + tremor_ogg_reference *head=b->head; + + if(end<0)return -1; + + if(bits){ + _lookspan(); + ret=*ptr++>>b->headbit; + if(bits>8){ + --end; + _lookspan(); + ret|=*ptr++<<(8-b->headbit); + if(bits>16){ + --end; + _lookspan(); + ret|=*ptr++<<(16-b->headbit); + if(bits>24){ + --end; + _lookspan(); + ret|=*ptr++<<(24-b->headbit); + if(bits>32 && b->headbit){ + --end; + _lookspan(); + ret|=*ptr<<(32-b->headbit); + } + } + } + } + } + + }else{ + + /* make this a switch jump-table */ + ret=b->headptr[0]>>b->headbit; + if(bits>8){ + ret|=b->headptr[1]<<(8-b->headbit); + if(bits>16){ + ret|=b->headptr[2]<<(16-b->headbit); + if(bits>24){ + ret|=b->headptr[3]<<(24-b->headbit); + if(bits>32 && b->headbit) + ret|=b->headptr[4]<<(32-b->headbit); + } + } + } + } + + ret&=m; + return ret; +} + +/* limited to 32 at a time */ +void tremor_oggpack_adv(tremor_oggpack_buffer *b,int bits){ + bits+=b->headbit; + b->headbit=bits&7; + b->headend-=(bits>>3); + b->headptr+=(bits>>3); + if(b->headend<1)_span(b); +} + +int tremor_oggpack_eop(tremor_oggpack_buffer *b){ + if(b->headend<0)return -1; + return 0; +} + +/* bits <= 32 */ +long tremor_oggpack_read(tremor_oggpack_buffer *b,int bits){ + long ret=tremor_oggpack_look(b,bits); + tremor_oggpack_adv(b,bits); + return(ret); +} + +long tremor_oggpack_bytes(tremor_oggpack_buffer *b){ + if(b->headend<0)return b->count+b->head->length; + return b->count + b->head->length-b->headend + + (b->headbit+7)/8; +} + +long tremor_oggpack_bits(tremor_oggpack_buffer *b){ + if(b->headend<0)return (b->count+b->head->length)*8; + return (b->count + b->head->length-b->headend)*8 + + b->headbit; +} + +/* Self test of the bitwise routines; everything else is based on + them, so they damned well better be solid. */ + +#ifdef _V_BIT_TEST +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "framing.c" + +static int ilog(unsigned long v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +tremor_oggpack_buffer r; +tremor_oggpack_buffer o; +tremor_ogg_buffer_state *bs; +tremor_ogg_reference *or; +#define TESTWORDS 256 + +void report(char *in){ + fprintf(stderr,"%s",in); + exit(1); +} + +int getbyte(tremor_ogg_reference *or,int position){ + while(or && position>=or->length){ + position-=or->length; + or=or->next; + if(or==NULL){ + fprintf(stderr,"\n\tERROR: getbyte ran off end of buffer.\n"); + exit(1); + } + } + + if((position+or->begin)&1) + return (or->buffer->data[(position+or->begin)>>1])&0xff; + else + return (or->buffer->data[(position+or->begin)>>1]>>8)&0xff; +} + +void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){ + long i,bitcount=0; + tremor_ogg_reference *or=tremor_ogg_buffer_alloc(bs,64); + for(i=0;i<compsize;i++) + or->buffer->data[i]= comp[i]; + or->length=i; + + tremor_oggpack_readinit(&r,or); + for(i=0;i<vals;i++){ + unsigned long test; + int tbit=bits?bits:ilog(b[i]); + if((test=tremor_oggpack_look(&r,tbit))==0xffffffff) + report("out of data!\n"); + if(test!=(b[i]&mask[tbit])){ + fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test); + report("looked at incorrect value!\n"); + } + if((test=tremor_oggpack_read(&r,tbit))==0xffffffff){ + report("premature end of data when reading!\n"); + } + if(test!=(b[i]&mask[tbit])){ + fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test); + report("read incorrect value!\n"); + } + bitcount+=tbit; + + if(bitcount!=tremor_oggpack_bits(&r)) + report("wrong number of bits while reading!\n"); + if((bitcount+7)/8!=tremor_oggpack_bytes(&r)) + report("wrong number of bytes while reading!\n"); + + } + if(tremor_oggpack_bytes(&r)!=(bitcount+7)/8)report("leftover bytes after read!\n"); + tremor_ogg_buffer_release(or); +} + +void _end_verify(int count){ + int i; + + /* are the proper number of bits left over? */ + int leftover=count*8-tremor_oggpack_bits(&o); + if(leftover>7) + report("\nERROR: too many bits reported left over.\n"); + + /* does reading to exactly byte alignment *not* trip EOF? */ + if(tremor_oggpack_read(&o,leftover)==-1) + report("\nERROR: read to but not past exact end tripped EOF.\n"); + if(tremor_oggpack_bits(&o)!=count*8) + report("\nERROR: read to but not past exact end reported bad bitcount.\n"); + + /* does EOF trip properly after a single additional bit? */ + if(tremor_oggpack_read(&o,1)!=-1) + report("\nERROR: read past exact end did not trip EOF.\n"); + if(tremor_oggpack_bits(&o)!=count*8) + report("\nERROR: read past exact end reported bad bitcount.\n"); + + /* does EOF stay set over additional bit reads? */ + for(i=0;i<=32;i++){ + if(tremor_oggpack_read(&o,i)!=-1) + report("\nERROR: EOF did not stay set on stream.\n"); + if(tremor_oggpack_bits(&o)!=count*8) + report("\nERROR: read past exact end reported bad bitcount.\n"); + } +} + +void _end_verify2(int count){ + int i; + + /* are the proper number of bits left over? */ + int leftover=count*8-tremor_oggpack_bits(&o); + if(leftover>7) + report("\nERROR: too many bits reported left over.\n"); + + /* does reading to exactly byte alignment *not* trip EOF? */ + tremor_oggpack_adv(&o,leftover); + if(o.headend!=0) + report("\nERROR: read to but not past exact end tripped EOF.\n"); + if(tremor_oggpack_bits(&o)!=count*8) + report("\nERROR: read to but not past exact end reported bad bitcount.\n"); + + /* does EOF trip properly after a single additional bit? */ + tremor_oggpack_adv(&o,1); + if(o.headend>=0) + report("\nERROR: read past exact end did not trip EOF.\n"); + if(tremor_oggpack_bits(&o)!=count*8) + report("\nERROR: read past exact end reported bad bitcount.\n"); + + /* does EOF stay set over additional bit reads? */ + for(i=0;i<=32;i++){ + tremor_oggpack_adv(&o,i); + if(o.headend>=0) + report("\nERROR: EOF did not stay set on stream.\n"); + if(tremor_oggpack_bits(&o)!=count*8) + report("\nERROR: read past exact end reported bad bitcount.\n"); + } +} + +long tremor_ogg_buffer_length(tremor_ogg_reference *or){ + int count=0; + while(or){ + count+=or->length; + or=or->next; + } + return count; +} + +tremor_ogg_reference *tremor_ogg_buffer_extend(tremor_ogg_reference *or,long bytes){ + if(or){ + while(or->next){ + or=or->next; + } + or->next=tremor_ogg_buffer_alloc(or->buffer->ptr.owner,bytes); + return(or->next); + } + return 0; +} + +void tremor_ogg_buffer_posttruncate(tremor_ogg_reference *or,long pos){ + /* walk to the point where we want to begin truncate */ + while(or && pos>or->length){ + pos-=or->length; + or=or->next; + } + if(or){ + tremor_ogg_buffer_release(or->next); + or->next=0; + or->length=pos; + } +} + +int main(void){ + long i; + static unsigned long testbuffer1[]= + {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7, + 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4}; + int test1size=43; + + static unsigned long testbuffer2[]= + {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212, + 1233432,534,5,346435231,14436467,7869299,76326614,167548585, + 85525151,0,12321,1,349528352}; + int test2size=21; + + static unsigned long testbuffer3[]= + {1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1, + 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1}; + int test3size=56; + + static unsigned long large[]= + {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212, + 1233432,534,5,2146435231,14436467,7869299,76326614,167548585, + 85525151,0,12321,1,2146528352}; + + int onesize=33; + static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40, + 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172, + 223,4}; + + int twosize=6; + static int two[6]={61,255,255,251,231,29}; + + int threesize=54; + static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254, + 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83, + 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10, + 100,52,4,14,18,86,77,1}; + + int foursize=38; + static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72, + 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169, + 28,2,133,0,1}; + + int fivesize=45; + static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62, + 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169, + 84,75,159,2,1,0,132,192,8,0,0,18,22}; + + int sixsize=7; + static int six[7]={17,177,170,242,169,19,148}; + + /* Test read/write together */ + /* Later we test against pregenerated bitstreams */ + bs=tremor_ogg_buffer_create(); + + fprintf(stderr,"\nSmall preclipped packing (LSb): "); + cliptest(testbuffer1,test1size,0,one,onesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nNull bit call (LSb): "); + cliptest(testbuffer3,test3size,0,two,twosize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nLarge preclipped packing (LSb): "); + cliptest(testbuffer2,test2size,0,three,threesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\n32 bit preclipped packing (LSb): "); + + or=tremor_ogg_buffer_alloc(bs,128); + for(i=0;i<test2size;i++){ + or->buffer->data[i*4] = large[i]&0xff; + or->buffer->data[i*4+1] = (large[i]>>8)&0xff; + or->buffer->data[i*4+2] = (large[i]>>16)&0xff; + or->buffer->data[i*4+3] = (large[i]>>24)&0xff; + } + or->length=test2size*4; + tremor_oggpack_readinit(&r,or); + for(i=0;i<test2size;i++){ + unsigned long test; + if((test=tremor_oggpack_look(&r,32))==0xffffffffUL)report("out of data. failed!"); + if(test!=large[i]){ + fprintf(stderr,"%ld != %ld (%lx!=%lx):",test,large[i], + test,large[i]); + report("read incorrect value!\n"); + } + tremor_oggpack_adv(&r,32); + } + tremor_ogg_buffer_release(or); + if(tremor_oggpack_bytes(&r)!=test2size*4)report("leftover bytes after read!\n"); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nSmall unclipped packing (LSb): "); + cliptest(testbuffer1,test1size,7,four,foursize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nLarge unclipped packing (LSb): "); + cliptest(testbuffer2,test2size,17,five,fivesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nSingle bit unclipped packing (LSb): "); + cliptest(testbuffer3,test3size,1,six,sixsize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nTesting read past end (LSb): "); + { + unsigned char dda[]={0,0,0,0}; + tremor_ogg_buffer lob={dda,8,0,{0}}; + tremor_ogg_reference lor={&lob,0,8,0}; + + tremor_oggpack_readinit(&r,&lor); + for(i=0;i<64;i++){ + if(tremor_oggpack_read(&r,1)<0){ + fprintf(stderr,"failed; got -1 prematurely.\n"); + exit(1); + } + } + if(tremor_oggpack_look(&r,1)!=-1 || + tremor_oggpack_read(&r,1)!=-1){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + } + { + unsigned char dda[]={0,0,0,0}; + tremor_ogg_buffer lob={dda,8,0,{0}}; + tremor_ogg_reference lor={&lob,0,8,0}; + unsigned long test; + + tremor_oggpack_readinit(&r,&lor); + if((test=tremor_oggpack_read(&r,30))==0xffffffffUL || + (test=tremor_oggpack_read(&r,16))==0xffffffffUL){ + fprintf(stderr,"failed 2; got -1 prematurely.\n"); + exit(1); + } + + if((test=tremor_oggpack_look(&r,18))==0xffffffffUL){ + fprintf(stderr,"failed 3; got -1 prematurely.\n"); + exit(1); + } + if((test=tremor_oggpack_look(&r,19))!=0xffffffffUL){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + if((test=tremor_oggpack_look(&r,32))!=0xffffffffUL){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + } + fprintf(stderr,"ok.\n"); + + /* now the scary shit: randomized testing */ + + for(i=0;i<10000;i++){ + long j,count=0,count2=0,bitcount=0; + unsigned long values[TESTWORDS]; + int len[TESTWORDS]; + unsigned char flat[4*TESTWORDS]; /* max possible needed size */ + + memset(flat,0,sizeof(flat)); + fprintf(stderr,"\rRandomized testing (LSb)... (%ld) ",10000-i); + + /* generate a list of words and lengths */ + /* write the required number of bits out to packbuffer */ + { + long word=0; + long bit=0; + int k; + + for(j=0;j<TESTWORDS;j++){ + values[j]=rand(); + len[j]=(rand()%33); + + for(k=0;k<len[j];k++){ + flat[word] |= ((values[j]>>k)&0x1)<<bit; + bit++; + bitcount++; + if(bit>7){ + bit=0; + word++; + } + } + } + } + count2=(bitcount+7)>>3; + + /* construct random-length buffer chain from flat vector; random + byte starting offset within the length of the vector */ + { + tremor_ogg_reference *or=NULL,*orl=NULL; + long pos=0; + + /* build buffer chain */ + while(count2){ + int ilen=(rand()%32),k; + int ibegin=(rand()%32); + + + if(ilen>count2)ilen=count2; + + if(or) + orl=tremor_ogg_buffer_extend(orl,64); + else + or=orl=tremor_ogg_buffer_alloc(bs,64); + + orl->length=ilen; + orl->begin=ibegin; + + for(k=0;k<ilen;k++) + orl->buffer->data[ibegin++]= flat[pos++]; + + count2-=ilen; + } + + if(tremor_ogg_buffer_length(or)!=(bitcount+7)/8){ + fprintf(stderr,"\nERROR: buffer length incorrect after build.\n"); + exit(1); + } + + + { + int begin=0; //=(rand()%TESTWORDS); + int ilen=(rand()%(TESTWORDS-begin)); + int bitoffset,bitcount=0; + unsigned long temp; + + for(j=0;j<begin;j++) + bitcount+=len[j]; + or=tremor_ogg_buffer_pretruncate(or,bitcount/8); + bitoffset=bitcount%=8; + for(;j<begin+ilen;j++) + bitcount+=len[j]; + tremor_ogg_buffer_posttruncate(or,((bitcount+7)/8)); + + if((count=tremor_ogg_buffer_length(or))!=(bitcount+7)/8){ + fprintf(stderr,"\nERROR: buffer length incorrect after truncate.\n"); + exit(1); + } + + tremor_oggpack_readinit(&o,or); + + /* verify bit count */ + if(tremor_oggpack_bits(&o)!=0){ + fprintf(stderr,"\nERROR: Read bitcounter not zero!\n"); + exit(1); + } + if(tremor_oggpack_bytes(&o)!=0){ + fprintf(stderr,"\nERROR: Read bytecounter not zero!\n"); + exit(1); + } + + bitcount=bitoffset; + tremor_oggpack_read(&o,bitoffset); + + /* read and compare to original list */ + for(j=begin;j<begin+ilen;j++){ + temp=tremor_oggpack_read(&o,len[j]); + if(temp==0xffffffffUL){ + fprintf(stderr,"\nERROR: End of stream too soon! word: %ld,%d\n", + j-begin,ilen); + exit(1); + } + if(temp!=(values[j]&mask[len[j]])){ + fprintf(stderr,"\nERROR: Incorrect read %lx != %lx, word %ld, len %d\n" +, + values[j]&mask[len[j]],temp,j-begin,len[j]); + exit(1); + } + bitcount+=len[j]; + if(tremor_oggpack_bits(&o)!=bitcount){ + fprintf(stderr,"\nERROR: Read bitcounter %d != %ld!\n", + bitcount,tremor_oggpack_bits(&o)); + exit(1); + } + if(tremor_oggpack_bytes(&o)!=(bitcount+7)/8){ + fprintf(stderr,"\nERROR: Read bytecounter %d != %ld!\n", + (bitcount+7)/8,tremor_oggpack_bytes(&o)); + exit(1); + } + + } + _end_verify(count); + + /* look/adv version */ + tremor_oggpack_readinit(&o,or); + bitcount=bitoffset; + tremor_oggpack_adv(&o,bitoffset); + + /* read and compare to original list */ + for(j=begin;j<begin+ilen;j++){ + temp=tremor_oggpack_look(&o,len[j]); + + if(temp==0xffffffffUL){ + fprintf(stderr,"\nERROR: End of stream too soon! word: %ld\n", + j-begin); + exit(1); + } + if(temp!=(values[j]&mask[len[j]])){ + fprintf(stderr,"\nERROR: Incorrect look %lx != %lx, word %ld, len %d\n" +, + values[j]&mask[len[j]],temp,j-begin,len[j]); + exit(1); + } + tremor_oggpack_adv(&o,len[j]); + bitcount+=len[j]; + if(tremor_oggpack_bits(&o)!=bitcount){ + fprintf(stderr,"\nERROR: Look/Adv bitcounter %d != %ld!\n", + bitcount,tremor_oggpack_bits(&o)); + exit(1); + } + if(tremor_oggpack_bytes(&o)!=(bitcount+7)/8){ + fprintf(stderr,"\nERROR: Look/Adv bytecounter %d != %ld!\n", + (bitcount+7)/8,tremor_oggpack_bytes(&o)); + exit(1); + } + + } + _end_verify2(count); + + } + tremor_ogg_buffer_release(or); + } + } + fprintf(stderr,"\rRandomized testing (LSb)... ok. \n"); + + return(0); +} +#endif diff --git a/lib/tremor/block.c b/lib/tremor/block.c deleted file mode 100644 index 666bc51a..00000000 --- a/lib/tremor/block.c +++ /dev/null @@ -1,497 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: PCM data vector blocking, windowing and dis/reassembly - - ********************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ogg/ogg.h> -#include "ivorbiscodec.h" -#include "codec_internal.h" - -#include "window.h" -#include "registry.h" -#include "misc.h" - -static int ilog(unsigned int v){ - int ret=0; - if(v)--v; - while(v){ - ret++; - v>>=1; - } - return(ret); -} - -/* pcm accumulator examples (not exhaustive): - - <-------------- lW ----------------> - <--------------- W ----------------> -: .....|..... _______________ | -: .''' | '''_--- | |\ | -:.....''' |_____--- '''......| | \_______| -:.................|__________________|_______|__|______| - |<------ Sl ------>| > Sr < |endW - |beginSl |endSl | |endSr - |beginW |endlW |beginSr - - - |< lW >| - <--------------- W ----------------> - | | .. ______________ | - | | ' `/ | ---_ | - |___.'___/`. | ---_____| - |_______|__|_______|_________________| - | >|Sl|< |<------ Sr ----->|endW - | | |endSl |beginSr |endSr - |beginW | |endlW - mult[0] |beginSl mult[n] - - <-------------- lW -----------------> - |<--W-->| -: .............. ___ | | -: .''' |`/ \ | | -:.....''' |/`....\|...| -:.........................|___|___|___| - |Sl |Sr |endW - | | |endSr - | |beginSr - | |endSl - |beginSl - |beginW -*/ - -/* block abstraction setup *********************************************/ - -#ifndef WORD_ALIGN -#define WORD_ALIGN 8 -#endif - -int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ - memset(vb,0,sizeof(*vb)); - vb->vd=v; - vb->localalloc=0; - vb->localstore=NULL; - - return(0); -} - -void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ - bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); - if(bytes+vb->localtop>vb->localalloc){ - /* can't just _ogg_realloc... there are outstanding pointers */ - if(vb->localstore){ - struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link)); - vb->totaluse+=vb->localtop; - link->next=vb->reap; - link->ptr=vb->localstore; - vb->reap=link; - } - /* highly conservative */ - vb->localalloc=bytes; - vb->localstore=_ogg_malloc(vb->localalloc); - vb->localtop=0; - } - { - void *ret=(void *)(((char *)vb->localstore)+vb->localtop); - vb->localtop+=bytes; - return ret; - } -} - -/* reap the chain, pull the ripcord */ -void _vorbis_block_ripcord(vorbis_block *vb){ - /* reap the chain */ - struct alloc_chain *reap=vb->reap; - while(reap){ - struct alloc_chain *next=reap->next; - _ogg_free(reap->ptr); - memset(reap,0,sizeof(*reap)); - _ogg_free(reap); - reap=next; - } - /* consolidate storage */ - if(vb->totaluse){ - vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); - vb->localalloc+=vb->totaluse; - vb->totaluse=0; - } - - /* pull the ripcord */ - vb->localtop=0; - vb->reap=NULL; -} - -int vorbis_block_clear(vorbis_block *vb){ - _vorbis_block_ripcord(vb); - if(vb->localstore)_ogg_free(vb->localstore); - - memset(vb,0,sizeof(*vb)); - return(0); -} - -static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){ - int i; - codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; - private_state *b=NULL; - - if(ci==NULL) return 1; - - memset(v,0,sizeof(*v)); - b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b))); - - v->vi=vi; - b->modebits=ilog(ci->modes); - - /* Vorbis I uses only window type 0 */ - b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2); - b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2); - - /* finish the codebooks */ - if(!ci->fullbooks){ - ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); - for(i=0;i<ci->books;i++){ - if(ci->book_param[i]==NULL) - goto abort_books; - if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])) - goto abort_books; - /* decode codebooks are now standalone after init */ - vorbis_staticbook_destroy(ci->book_param[i]); - ci->book_param[i]=NULL; - } - } - - v->pcm_storage=ci->blocksizes[1]; - v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm)); - v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret)); - for(i=0;i<vi->channels;i++) - v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); - - /* all 1 (large block) or 0 (small block) */ - /* explicitly set for the sake of clarity */ - v->lW=0; /* previous window size */ - v->W=0; /* current window size */ - - /* initialize all the mapping/backend lookups */ - b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode)); - for(i=0;i<ci->modes;i++){ - int mapnum=ci->mode_param[i]->mapping; - int maptype=ci->map_type[mapnum]; - b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i], - ci->map_param[mapnum]); - } - return 0; -abort_books: - for(i=0;i<ci->books;i++){ - if(ci->book_param[i]!=NULL){ - vorbis_staticbook_destroy(ci->book_param[i]); - ci->book_param[i]=NULL; - } - } - vorbis_dsp_clear(v); - return -1; -} - -int vorbis_synthesis_restart(vorbis_dsp_state *v){ - vorbis_info *vi=v->vi; - codec_setup_info *ci; - - if(!v->backend_state)return -1; - if(!vi)return -1; - ci=vi->codec_setup; - if(!ci)return -1; - - v->centerW=ci->blocksizes[1]/2; - v->pcm_current=v->centerW; - - v->pcm_returned=-1; - v->granulepos=-1; - v->sequence=-1; - ((private_state *)(v->backend_state))->sample_count=-1; - - return(0); -} - -int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ - if(_vds_init(v,vi))return 1; - vorbis_synthesis_restart(v); - - return 0; -} - -void vorbis_dsp_clear(vorbis_dsp_state *v){ - int i; - if(v){ - vorbis_info *vi=v->vi; - codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL); - private_state *b=(private_state *)v->backend_state; - - if(v->pcm){ - for(i=0;i<vi->channels;i++) - if(v->pcm[i])_ogg_free(v->pcm[i]); - _ogg_free(v->pcm); - if(v->pcmret)_ogg_free(v->pcmret); - } - - /* free mode lookups; these are actually vorbis_look_mapping structs */ - if(ci){ - for(i=0;i<ci->modes;i++){ - int mapnum=ci->mode_param[i]->mapping; - int maptype=ci->map_type[mapnum]; - if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]); - } - } - - if(b){ - if(b->mode)_ogg_free(b->mode); - _ogg_free(b); - } - - memset(v,0,sizeof(*v)); - } -} - -/* Unlike in analysis, the window is only partially applied for each - block. The time domain envelope is not yet handled at the point of - calling (as it relies on the previous block). */ - -int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ - vorbis_info *vi=v->vi; - codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; - private_state *b=v->backend_state; - int i,j; - - if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); - - v->lW=v->W; - v->W=vb->W; - v->nW=-1; - - if((v->sequence==-1)|| - (v->sequence+1 != vb->sequence)){ - v->granulepos=-1; /* out of sequence; lose count */ - b->sample_count=-1; - } - - v->sequence=vb->sequence; - - if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly - was called on block */ - int n=ci->blocksizes[v->W]/2; - int n0=ci->blocksizes[0]/2; - int n1=ci->blocksizes[1]/2; - - int thisCenter; - int prevCenter; - - if(v->centerW){ - thisCenter=n1; - prevCenter=0; - }else{ - thisCenter=0; - prevCenter=n1; - } - - /* v->pcm is now used like a two-stage double buffer. We don't want - to have to constantly shift *or* adjust memory usage. Don't - accept a new block until the old is shifted out */ - - /* overlap/add PCM */ - - for(j=0;j<vi->channels;j++){ - /* the overlap/add section */ - if(v->lW){ - if(v->W){ - /* large/large */ - ogg_int32_t *pcm=v->pcm[j]+prevCenter; - ogg_int32_t *p=vb->pcm[j]; - for(i=0;i<n1;i++) - pcm[i]+=p[i]; - }else{ - /* large/small */ - ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; - ogg_int32_t *p=vb->pcm[j]; - for(i=0;i<n0;i++) - pcm[i]+=p[i]; - } - }else{ - if(v->W){ - /* small/large */ - ogg_int32_t *pcm=v->pcm[j]+prevCenter; - ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2; - for(i=0;i<n0;i++) - pcm[i]+=p[i]; - for(;i<n1/2+n0/2;i++) - pcm[i]=p[i]; - }else{ - /* small/small */ - ogg_int32_t *pcm=v->pcm[j]+prevCenter; - ogg_int32_t *p=vb->pcm[j]; - for(i=0;i<n0;i++) - pcm[i]+=p[i]; - } - } - - /* the copy section */ - { - ogg_int32_t *pcm=v->pcm[j]+thisCenter; - ogg_int32_t *p=vb->pcm[j]+n; - for(i=0;i<n;i++) - pcm[i]=p[i]; - } - } - - if(v->centerW) - v->centerW=0; - else - v->centerW=n1; - - /* deal with initial packet state; we do this using the explicit - pcm_returned==-1 flag otherwise we're sensitive to first block - being short or long */ - - if(v->pcm_returned==-1){ - v->pcm_returned=thisCenter; - v->pcm_current=thisCenter; - }else{ - v->pcm_returned=prevCenter; - v->pcm_current=prevCenter+ - ci->blocksizes[v->lW]/4+ - ci->blocksizes[v->W]/4; - } - - } - - /* track the frame number... This is for convenience, but also - making sure our last packet doesn't end with added padding. If - the last packet is partial, the number of samples we'll have to - return will be past the vb->granulepos. - - This is not foolproof! It will be confused if we begin - decoding at the last page after a seek or hole. In that case, - we don't have a starting point to judge where the last frame - is. For this reason, vorbisfile will always try to make sure - it reads the last two marked pages in proper sequence */ - - if(b->sample_count==-1){ - b->sample_count=0; - }else{ - b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; - } - - if(v->granulepos==-1){ - if(vb->granulepos!=-1){ /* only set if we have a position to set to */ - - v->granulepos=vb->granulepos; - - /* is this a short page? */ - if(b->sample_count>v->granulepos){ - /* corner case; if this is both the first and last audio page, - then spec says the end is cut, not beginning */ - long extra=b->sample_count-vb->granulepos; - - /* we use ogg_int64_t for granule positions because a - uint64 isn't universally available. Unfortunately, - that means granposes can be 'negative' and result in - extra being negative */ - if(extra<0) - extra=0; - - if(vb->eofflag){ - /* trim the end */ - /* no preceeding granulepos; assume we started at zero (we'd - have to in a short single-page stream) */ - /* granulepos could be -1 due to a seek, but that would result - in a long coun`t, not short count */ - - /* Guard against corrupt/malicious frames that set EOP and - a backdated granpos; don't rewind more samples than we - actually have */ - if(extra > v->pcm_current - v->pcm_returned) - extra = v->pcm_current - v->pcm_returned; - - v->pcm_current-=extra; - }else{ - /* trim the beginning */ - v->pcm_returned+=extra; - if(v->pcm_returned>v->pcm_current) - v->pcm_returned=v->pcm_current; - } - - } - - } - }else{ - v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; - if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ - - if(v->granulepos>vb->granulepos){ - long extra=v->granulepos-vb->granulepos; - - if(extra) - if(vb->eofflag){ - /* partial last frame. Strip the extra samples off */ - - /* Guard against corrupt/malicious frames that set EOP and - a backdated granpos; don't rewind more samples than we - actually have */ - if(extra > v->pcm_current - v->pcm_returned) - extra = v->pcm_current - v->pcm_returned; - - /* we use ogg_int64_t for granule positions because a - uint64 isn't universally available. Unfortunately, - that means granposes can be 'negative' and result in - extra being negative */ - if(extra<0) - extra=0; - - v->pcm_current-=extra; - - } /* else {Shouldn't happen *unless* the bitstream is out of - spec. Either way, believe the bitstream } */ - } /* else {Shouldn't happen *unless* the bitstream is out of - spec. Either way, believe the bitstream } */ - v->granulepos=vb->granulepos; - } - } - - /* Update, cleanup */ - - if(vb->eofflag)v->eofflag=1; - return(0); -} - -/* pcm==NULL indicates we just want the pending samples, no more */ -int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){ - vorbis_info *vi=v->vi; - if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){ - if(pcm){ - int i; - for(i=0;i<vi->channels;i++) - v->pcmret[i]=v->pcm[i]+v->pcm_returned; - *pcm=v->pcmret; - } - return(v->pcm_current-v->pcm_returned); - } - return(0); -} - -int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){ - if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL); - v->pcm_returned+=bytes; - return(0); -} - diff --git a/lib/tremor/block.h b/lib/tremor/block.h deleted file mode 100644 index 5e193543..00000000 --- a/lib/tremor/block.h +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2008 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: shared block functions - - ********************************************************************/ - -#ifndef _V_BLOCK_ -#define _V_BLOCK_ - -extern void _vorbis_block_ripcord(vorbis_block *vb); -extern void *_vorbis_block_alloc(vorbis_block *vb,long bytes); - -#endif diff --git a/lib/tremor/codebook.c b/lib/tremor/codebook.c index 1e1ae8a9..85a46eb2 100644 --- a/lib/tremor/codebook.c +++ b/lib/tremor/codebook.c @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,77 +18,385 @@ #include <stdlib.h> #include <string.h> #include <math.h> -#include <ogg/ogg.h> +#include "tremor_ogg.h" #include "ivorbiscodec.h" #include "codebook.h" #include "misc.h" +#include "os.h" -/* unpacks a codebook from the packet buffer into the codebook struct, - readies the codebook auxiliary structures for decode *************/ -static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){ - long i,j; - static_codebook *s=_ogg_calloc(1,sizeof(*s)); + +/**** pack/unpack helpers ******************************************/ +int _ilog(unsigned int v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +static tremor_ogg_uint32_t decpack(long entry,long used_entry,long quantvals, + codebook *b,tremor_oggpack_buffer *opb,int maptype){ + tremor_ogg_uint32_t ret=0; + int j; + + switch(b->dec_type){ + + case 0: + return (tremor_ogg_uint32_t)entry; + + case 1: + if(maptype==1){ + /* vals are already read into temporary column vector here */ + for(j=0;j<b->dim;j++){ + tremor_ogg_uint32_t off=entry%quantvals; + entry/=quantvals; + ret|=((tremor_ogg_uint16_t *)(b->q_val))[off]<<(b->q_bits*j); + } + }else{ + for(j=0;j<b->dim;j++) + ret|=tremor_oggpack_read(opb,b->q_bits)<<(b->q_bits*j); + } + return ret; + + case 2: + for(j=0;j<b->dim;j++){ + tremor_ogg_uint32_t off=entry%quantvals; + entry/=quantvals; + ret|=off<<(b->q_pack*j); + } + return ret; + + case 3: + return (tremor_ogg_uint32_t)used_entry; + + } + return 0; /* silence compiler */ +} + +/* 32 bit float (not IEEE; nonnormalized mantissa + + biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm + Why not IEEE? It's just not that important here. */ + +static tremor_ogg_int32_t _float32_unpack(long val,int *point){ + long mant=val&0x1fffff; + int sign=val&0x80000000; + + *point=((val&0x7fe00000L)>>21)-788; + + if(mant){ + while(!(mant&0x40000000)){ + mant<<=1; + *point-=1; + } + if(sign)mant= -mant; + }else{ + *point=-9999; + } + return mant; +} + +/* choose the smallest supported node size that fits our decode table. + Legal bytewidths are 1/1 1/2 2/2 2/4 4/4 */ +static int _determine_node_bytes(long used, int leafwidth){ + + /* special case small books to size 4 to avoid multiple special + cases in repack */ + if(used<2) + return 4; + + if(leafwidth==3)leafwidth=4; + if(_ilog(3*used-6)+1 <= leafwidth*4) + return leafwidth/2?leafwidth/2:1; + return leafwidth; +} + +/* convenience/clarity; leaves are specified as multiple of node word + size (1 or 2) */ +static int _determine_leaf_words(int nodeb, int leafwidth){ + if(leafwidth>nodeb)return 2; + return 1; +} + +/* given a list of word lengths, number of used entries, and byte + width of a leaf, generate the decode table */ +static int _make_words(char *l,long n,tremor_ogg_uint32_t *r,long quantvals, + codebook *b, tremor_oggpack_buffer *opb,int maptype){ + long i,j,count=0; + long top=0; + tremor_ogg_uint32_t marker[33]; + + if(n<2){ + r[0]=0x80000000; + }else{ + memset(marker,0,sizeof(marker)); + + for(i=0;i<n;i++){ + long length=l[i]; + if(length){ + tremor_ogg_uint32_t entry=marker[length]; + long chase=0; + if(count && !entry)return -1; /* overpopulated tree! */ + + /* chase the tree as far as it's already populated, fill in past */ + for(j=0;j<length-1;j++){ + int bit=(entry>>(length-j-1))&1; + if(chase>=top){ + top++; + r[chase*2]=top; + r[chase*2+1]=0; + }else + if(!r[chase*2+bit]) + r[chase*2+bit]=top; + chase=r[chase*2+bit]; + } + { + int bit=(entry>>(length-j-1))&1; + if(chase>=top){ + top++; + r[chase*2+1]=0; + } + r[chase*2+bit]= decpack(i,count++,quantvals,b,opb,maptype) | + 0x80000000; + } + + /* Look to see if the next shorter marker points to the node + above. if so, update it and repeat. */ + for(j=length;j>0;j--){ + if(marker[j]&1){ + marker[j]=marker[j-1]<<1; + break; + } + marker[j]++; + } + + /* prune the tree; the implicit invariant says all the longer + markers were dangling from our just-taken node. Dangle them + from our *new* node. */ + for(j=length+1;j<33;j++) + if((marker[j]>>1) == entry){ + entry=marker[j]; + marker[j]=marker[j-1]<<1; + }else + break; + } + } + } + + return 0; +} + +static int _make_decode_table(codebook *s,char *lengthlist,long quantvals, + tremor_oggpack_buffer *opb,int maptype){ + int i; + tremor_ogg_uint32_t *work; + + if(s->dec_nodeb==4){ + s->dec_table=_tremor_ogg_malloc((s->used_entries*2+1)*sizeof(*work)); + /* +1 (rather than -2) is to accommodate 0 and 1 sized books, + which are specialcased to nodeb==4 */ + if(_make_words(lengthlist,s->entries, + s->dec_table,quantvals,s,opb,maptype))return 1; + + return 0; + } + + work=alloca((s->used_entries*2-2)*sizeof(*work)); + if(_make_words(lengthlist,s->entries,work,quantvals,s,opb,maptype))return 1; + s->dec_table=_tremor_ogg_malloc((s->used_entries*(s->dec_leafw+1)-2)* + s->dec_nodeb); + + if(s->dec_leafw==1){ + switch(s->dec_nodeb){ + case 1: + for(i=0;i<s->used_entries*2-2;i++) + ((unsigned char *)s->dec_table)[i]= + ((work[i] & 0x80000000UL) >> 24) | work[i]; + break; + case 2: + for(i=0;i<s->used_entries*2-2;i++) + ((tremor_ogg_uint16_t *)s->dec_table)[i]= + ((work[i] & 0x80000000UL) >> 16) | work[i]; + break; + } + + }else{ + /* more complex; we have to do a two-pass repack that updates the + node indexing. */ + long top=s->used_entries*3-2; + if(s->dec_nodeb==1){ + unsigned char *out=(unsigned char *)s->dec_table; + + for(i=s->used_entries*2-4;i>=0;i-=2){ + if(work[i]&0x80000000UL){ + if(work[i+1]&0x80000000UL){ + top-=4; + out[top]=(work[i]>>8 & 0x7f)|0x80; + out[top+1]=(work[i+1]>>8 & 0x7f)|0x80; + out[top+2]=work[i] & 0xff; + out[top+3]=work[i+1] & 0xff; + }else{ + top-=3; + out[top]=(work[i]>>8 & 0x7f)|0x80; + out[top+1]=work[work[i+1]*2]; + out[top+2]=work[i] & 0xff; + } + }else{ + if(work[i+1]&0x80000000UL){ + top-=3; + out[top]=work[work[i]*2]; + out[top+1]=(work[i+1]>>8 & 0x7f)|0x80; + out[top+2]=work[i+1] & 0xff; + }else{ + top-=2; + out[top]=work[work[i]*2]; + out[top+1]=work[work[i+1]*2]; + } + } + work[i]=top; + } + }else{ + tremor_ogg_uint16_t *out=(tremor_ogg_uint16_t *)s->dec_table; + for(i=s->used_entries*2-4;i>=0;i-=2){ + if(work[i]&0x80000000UL){ + if(work[i+1]&0x80000000UL){ + top-=4; + out[top]=(work[i]>>16 & 0x7fff)|0x8000; + out[top+1]=(work[i+1]>>16 & 0x7fff)|0x8000; + out[top+2]=work[i] & 0xffff; + out[top+3]=work[i+1] & 0xffff; + }else{ + top-=3; + out[top]=(work[i]>>16 & 0x7fff)|0x8000; + out[top+1]=work[work[i+1]*2]; + out[top+2]=work[i] & 0xffff; + } + }else{ + if(work[i+1]&0x80000000UL){ + top-=3; + out[top]=work[work[i]*2]; + out[top+1]=(work[i+1]>>16 & 0x7fff)|0x8000; + out[top+2]=work[i+1] & 0xffff; + }else{ + top-=2; + out[top]=work[work[i]*2]; + out[top+1]=work[work[i+1]*2]; + } + } + work[i]=top; + } + } + } + + return 0; +} + +/* most of the time, entries%dimensions == 0, but we need to be + well defined. We define that the possible vales at each + scalar is values == entries/dim. If entries%dim != 0, we'll + have 'too few' values (values*dim<entries), which means that + we'll have 'left over' entries; left over entries use zeroed + values (and are wasted). So don't generate codebooks like + that */ +/* there might be a straightforward one-line way to do the below + that's portable and totally safe against roundoff, but I haven't + thought of it. Therefore, we opt on the side of caution */ +long _book_maptype1_quantvals(codebook *b){ + /* get us a starting hint, we'll polish it below */ + int bits=_ilog(b->entries); + int vals=b->entries>>((bits-1)*(b->dim-1)/b->dim); + + while(1){ + long acc=1; + long acc1=1; + int i; + for(i=0;i<b->dim;i++){ + acc*=vals; + acc1*=vals+1; + } + if(acc<=b->entries && acc1>b->entries){ + return(vals); + }else{ + if(acc>b->entries){ + vals--; + }else{ + vals++; + } + } + } +} + +void vorbis_book_clear(codebook *b){ + /* static book is not cleared; we're likely called on the lookup and + the static codebook belongs to the info struct */ + if(b->q_val)_tremor_ogg_free(b->q_val); + if(b->dec_table)_tremor_ogg_free(b->dec_table); + + memset(b,0,sizeof(*b)); +} + +int vorbis_book_unpack(tremor_oggpack_buffer *opb,codebook *s){ + char *lengthlist=NULL; + int quantvals=0; + long i,j; + int maptype; + + memset(s,0,sizeof(*s)); /* make sure alignment is correct */ - if(oggpack_read(opb,24)!=0x564342)goto _eofout; + if(tremor_oggpack_read(opb,24)!=0x564342)goto _eofout; /* first the basic parameters */ - s->dim=oggpack_read(opb,16); - s->entries=oggpack_read(opb,24); + s->dim=tremor_oggpack_read(opb,16); + s->entries=tremor_oggpack_read(opb,24); if(s->entries==-1)goto _eofout; - if(_ilog(s->dim)+_ilog(s->entries)>24)goto _eofout; - /* codeword ordering.... length ordered or unordered? */ - switch((int)oggpack_read(opb,1)){ - case 0:{ - long unused; - /* allocated but unused entries? */ - unused=oggpack_read(opb,1); - if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb)) - goto _eofout; + switch((int)tremor_oggpack_read(opb,1)){ + case 0: /* unordered */ - s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); + lengthlist=(char *)alloca(sizeof(*lengthlist)*s->entries); /* allocated but unused entries? */ - if(unused){ + if(tremor_oggpack_read(opb,1)){ /* yes, unused entries */ for(i=0;i<s->entries;i++){ - if(oggpack_read(opb,1)){ - long num=oggpack_read(opb,5); + if(tremor_oggpack_read(opb,1)){ + long num=tremor_oggpack_read(opb,5); if(num==-1)goto _eofout; - s->lengthlist[i]=num+1; + lengthlist[i]=num+1; + s->used_entries++; + if(num+1>s->dec_maxlength)s->dec_maxlength=num+1; }else - s->lengthlist[i]=0; + lengthlist[i]=0; } }else{ /* all entries used; no tagging */ + s->used_entries=s->entries; for(i=0;i<s->entries;i++){ - long num=oggpack_read(opb,5); + long num=tremor_oggpack_read(opb,5); if(num==-1)goto _eofout; - s->lengthlist[i]=num+1; + lengthlist[i]=num+1; + if(num+1>s->dec_maxlength)s->dec_maxlength=num+1; } } break; - } case 1: /* ordered */ { - long length=oggpack_read(opb,5)+1; - if(length==0)goto _eofout; - s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); + long length=tremor_oggpack_read(opb,5)+1; + s->used_entries=s->entries; + lengthlist=(char *)alloca(sizeof(*lengthlist)*s->entries); + for(i=0;i<s->entries;){ - long num=oggpack_read(opb,_ilog(s->entries-i)); + long num=tremor_oggpack_read(opb,_ilog(s->entries-i)); if(num==-1)goto _eofout; - if(length>32 || num>s->entries-i || - (num>0 && (num-1)>>(length>>1)>>((length+1)>>1))>0){ - goto _errout; - } - for(j=0;j<num;j++,i++) - s->lengthlist[i]=length; + for(j=0;j<num && i<s->entries;j++,i++) + lengthlist[i]=length; + s->dec_maxlength=length; length++; } } @@ -97,295 +405,393 @@ static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){ /* EOF */ goto _eofout; } - + + /* Do we have a mapping to unpack? */ - switch((s->maptype=oggpack_read(opb,4))){ + + if((maptype=tremor_oggpack_read(opb,4))>0){ + s->q_min=_float32_unpack(tremor_oggpack_read(opb,32),&s->q_minp); + s->q_del=_float32_unpack(tremor_oggpack_read(opb,32),&s->q_delp); + s->q_bits=tremor_oggpack_read(opb,4)+1; + s->q_seq=tremor_oggpack_read(opb,1); + + s->q_del>>=s->q_bits; + s->q_delp+=s->q_bits; + } + + switch(maptype){ case 0: - /* no mapping */ + + /* no mapping; decode type 0 */ + + /* how many bytes for the indexing? */ + /* this is the correct boundary here; we lose one bit to + node/leaf mark */ + s->dec_nodeb=_determine_node_bytes(s->used_entries,_ilog(s->entries)/8+1); + s->dec_leafw=_determine_leaf_words(s->dec_nodeb,_ilog(s->entries)/8+1); + s->dec_type=0; + + if(_make_decode_table(s,lengthlist,quantvals,opb,maptype)) goto _errout; break; - case 1: case 2: - /* implicitly populated value mapping */ - /* explicitly populated value mapping */ - s->q_min=oggpack_read(opb,32); - s->q_delta=oggpack_read(opb,32); - s->q_quant=oggpack_read(opb,4)+1; - s->q_sequencep=oggpack_read(opb,1); - if(s->q_sequencep==-1)goto _eofout; + case 1: + /* mapping type 1; implicit values by lattice position */ + quantvals=_book_maptype1_quantvals(s); + + /* dec_type choices here are 1,2; 3 doesn't make sense */ { - int quantvals=0; - switch(s->maptype){ - case 1: - quantvals=(s->dim==0?0:_book_maptype1_quantvals(s)); - break; - case 2: - quantvals=s->entries*s->dim; - break; - } + /* packed values */ + long total1=(s->q_bits*s->dim+8)/8; /* remember flag bit */ + /* vector of column offsets; remember flag bit */ + long total2=(_ilog(quantvals-1)*s->dim+8)/8+(s->q_bits+7)/8; + - /* quantized values */ - if((quantvals*s->q_quant+7)>>3>opb->storage-oggpack_bytes(opb)) - goto _eofout; - s->quantlist=(long *)_ogg_malloc(sizeof(*s->quantlist)*quantvals); - for(i=0;i<quantvals;i++) - s->quantlist[i]=oggpack_read(opb,s->q_quant); + if(total1<=4 && total1<=total2){ + /* use dec_type 1: vector of packed values */ + + /* need quantized values before */ + s->q_val=alloca(sizeof(tremor_ogg_uint16_t)*quantvals); + for(i=0;i<quantvals;i++) + ((tremor_ogg_uint16_t *)s->q_val)[i]=tremor_oggpack_read(opb,s->q_bits); + + if(tremor_oggpack_eop(opb)){ + s->q_val=0; /* cleanup must not free alloca memory */ + goto _eofout; + } + + s->dec_type=1; + s->dec_nodeb=_determine_node_bytes(s->used_entries, + (s->q_bits*s->dim+8)/8); + s->dec_leafw=_determine_leaf_words(s->dec_nodeb, + (s->q_bits*s->dim+8)/8); + if(_make_decode_table(s,lengthlist,quantvals,opb,maptype)){ + s->q_val=0; /* cleanup must not free alloca memory */ + goto _errout; + } + + s->q_val=0; /* about to go out of scope; _make_decode_table + was using it */ + + }else{ + /* use dec_type 2: packed vector of column offsets */ + + /* need quantized values before */ + if(s->q_bits<=8){ + s->q_val=_tremor_ogg_malloc(quantvals); + for(i=0;i<quantvals;i++) + ((unsigned char *)s->q_val)[i]=tremor_oggpack_read(opb,s->q_bits); + }else{ + s->q_val=_tremor_ogg_malloc(quantvals*2); + for(i=0;i<quantvals;i++) + ((tremor_ogg_uint16_t *)s->q_val)[i]=tremor_oggpack_read(opb,s->q_bits); + } + + if(tremor_oggpack_eop(opb))goto _eofout; + + s->q_pack=_ilog(quantvals-1); + s->dec_type=2; + s->dec_nodeb=_determine_node_bytes(s->used_entries, + (_ilog(quantvals-1)*s->dim+8)/8); + s->dec_leafw=_determine_leaf_words(s->dec_nodeb, + (_ilog(quantvals-1)*s->dim+8)/8); + if(_make_decode_table(s,lengthlist,quantvals,opb,maptype))goto _errout; + + } + } + break; + case 2: + + /* mapping type 2; explicit array of values */ + quantvals=s->entries*s->dim; + /* dec_type choices here are 1,3; 2 is not possible */ + + if( (s->q_bits*s->dim+8)/8 <=4){ /* remember flag bit */ + /* use dec_type 1: vector of packed values */ + + s->dec_type=1; + s->dec_nodeb=_determine_node_bytes(s->used_entries,(s->q_bits*s->dim+8)/8); + s->dec_leafw=_determine_leaf_words(s->dec_nodeb,(s->q_bits*s->dim+8)/8); + if(_make_decode_table(s,lengthlist,quantvals,opb,maptype))goto _errout; - if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; + }else{ + /* use dec_type 3: scalar offset into packed value array */ + + s->dec_type=3; + s->dec_nodeb=_determine_node_bytes(s->used_entries,_ilog(s->used_entries-1)/8+1); + s->dec_leafw=_determine_leaf_words(s->dec_nodeb,_ilog(s->used_entries-1)/8+1); + if(_make_decode_table(s,lengthlist,quantvals,opb,maptype))goto _errout; + + /* get the vals & pack them */ + s->q_pack=(s->q_bits+7)/8*s->dim; + s->q_val=_tremor_ogg_malloc(s->q_pack*s->used_entries); + + if(s->q_bits<=8){ + for(i=0;i<s->used_entries*s->dim;i++) + ((unsigned char *)(s->q_val))[i]=tremor_oggpack_read(opb,s->q_bits); + }else{ + for(i=0;i<s->used_entries*s->dim;i++) + ((tremor_ogg_uint16_t *)(s->q_val))[i]=tremor_oggpack_read(opb,s->q_bits); + } } break; default: goto _errout; } - /* all set */ - return(s); - + if(tremor_oggpack_eop(opb))goto _eofout; + + return 0; _errout: _eofout: - vorbis_staticbook_destroy(s); - return(NULL); + vorbis_book_clear(s); + return -1; } -/* the 'eliminate the decode tree' optimization actually requires the - codewords to be MSb first, not LSb. This is an annoying inelegancy - (and one of the first places where carefully thought out design - turned out to be wrong; Vorbis II and future Ogg codecs should go - to an MSb bitpacker), but not actually the huge hit it appears to - be. The first-stage decode table catches most words so that - bitreverse is not in the main execution path. */ - -static ogg_uint32_t bitreverse(ogg_uint32_t x){ - x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000); - x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00); - x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0); - x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc); - return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa); -} - -STIN long decode_packed_entry_number(codebook *book, - oggpack_buffer *b){ +static inline tremor_ogg_uint32_t decode_packed_entry_number(codebook *book, + tremor_oggpack_buffer *b){ + tremor_ogg_uint32_t chase=0; int read=book->dec_maxlength; - long lo,hi; - long lok = oggpack_look(b,book->dec_firsttablen); - - if (lok >= 0) { - long entry = book->dec_firsttable[lok]; - if(entry&0x80000000UL){ - lo=(entry>>15)&0x7fff; - hi=book->used_entries-(entry&0x7fff); - }else{ - oggpack_adv(b, book->dec_codelengths[entry-1]); - return(entry-1); - } - }else{ - lo=0; - hi=book->used_entries; - } - - lok = oggpack_look(b, read); - + long lok = tremor_oggpack_look(b,read),i; + while(lok<0 && read>1) - lok = oggpack_look(b, --read); + lok = tremor_oggpack_look(b, --read); if(lok<0){ - oggpack_adv(b,1); /* force eop */ + tremor_oggpack_adv(b,1); /* force eop */ return -1; } - /* bisect search for the codeword in the ordered list */ - { - ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok); + /* chase the tree with the bits we got */ + if(book->dec_nodeb==1){ + if(book->dec_leafw==1){ + + /* 8/8 */ + unsigned char *t=(unsigned char *)book->dec_table; + for(i=0;i<read;i++){ + chase=t[chase*2+((lok>>i)&1)]; + if(chase&0x80UL)break; + } + chase&=0x7fUL; - while(hi-lo>1){ - long p=(hi-lo)>>1; - long test=book->codelist[lo+p]>testword; - lo+=p&(test-1); - hi-=p&(-test); + }else{ + + /* 8/16 */ + unsigned char *t=(unsigned char *)book->dec_table; + for(i=0;i<read;i++){ + int bit=(lok>>i)&1; + int next=t[chase+bit]; + if(next&0x80){ + chase= (next<<8) | t[chase+bit+1+(!bit || t[chase]&0x80)]; + break; + } + chase=next; + } + chase&=0x7fffUL; } - if(book->dec_codelengths[lo]<=read){ - oggpack_adv(b, book->dec_codelengths[lo]); - return(lo); + }else{ + if(book->dec_nodeb==2){ + if(book->dec_leafw==1){ + + /* 16/16 */ + for(i=0;i<read;i++){ + chase=((tremor_ogg_uint16_t *)(book->dec_table))[chase*2+((lok>>i)&1)]; + if(chase&0x8000UL)break; + } + chase&=0x7fffUL; + + }else{ + + /* 16/32 */ + tremor_ogg_uint16_t *t=(tremor_ogg_uint16_t *)book->dec_table; + for(i=0;i<read;i++){ + int bit=(lok>>i)&1; + int next=t[chase+bit]; + if(next&0x8000){ + chase= (next<<16) | t[chase+bit+1+(!bit || t[chase]&0x8000)]; + break; + } + chase=next; + } + chase&=0x7fffffffUL; + } + + }else{ + + for(i=0;i<read;i++){ + chase=((tremor_ogg_uint32_t *)(book->dec_table))[chase*2+((lok>>i)&1)]; + if(chase&0x80000000UL)break; + } + chase&=0x7fffffffUL; + } } - oggpack_adv(b, read+1); + if(i<read){ + tremor_oggpack_adv(b,i+1); + return chase; + } + tremor_oggpack_adv(b,read+1); return(-1); } -/* Decode side is specced and easier, because we don't need to find - matches using different criteria; we simply read and map. There are - two things we need to do 'depending': - - We may need to support interleave. We don't really, but it's - convenient to do it here rather than rebuild the vector later. +/* returns the [original, not compacted] entry number or -1 on eof *********/ +long vorbis_book_decode(codebook *book, tremor_oggpack_buffer *b){ + if(book->dec_type)return -1; + return decode_packed_entry_number(book,b); +} + +int decode_map(codebook *s, tremor_oggpack_buffer *b, tremor_ogg_int32_t *v, int point){ + tremor_ogg_uint32_t entry = decode_packed_entry_number(s,b); + int i; + if(tremor_oggpack_eop(b))return(-1); + + /* according to decode type */ + switch(s->dec_type){ + case 1:{ + /* packed vector of values */ + int mask=(1<<s->q_bits)-1; + for(i=0;i<s->dim;i++){ + v[i]=entry&mask; + entry>>=s->q_bits; + } + break; + } + case 2:{ + /* packed vector of column offsets */ + int mask=(1<<s->q_pack)-1; + for(i=0;i<s->dim;i++){ + if(s->q_bits<=8) + v[i]=((unsigned char *)(s->q_val))[entry&mask]; + else + v[i]=((tremor_ogg_uint16_t *)(s->q_val))[entry&mask]; + entry>>=s->q_pack; + } + break; + } + case 3:{ + /* offset into array */ + void *ptr=s->q_val+entry*s->q_pack; - Cascades may be additive or multiplicitive; this is not inherent in - the codebook, but set in the code using the codebook. Like - interleaving, it's easiest to do it here. - addmul==0 -> declarative (set the value) - addmul==1 -> additive - addmul==2 -> multiplicitive */ + if(s->q_bits<=8){ + for(i=0;i<s->dim;i++) + v[i]=((unsigned char *)ptr)[i]; + }else{ + for(i=0;i<s->dim;i++) + v[i]=((tremor_ogg_uint16_t *)ptr)[i]; + } + break; + } + default: + return -1; + } -/* returns the [original, not compacted] entry number or -1 on eof *********/ -long vorbis_book_decode(codebook *book, oggpack_buffer *b){ - if(book->used_entries>0){ - long packed_entry=decode_packed_entry_number(book,b); - if(packed_entry>=0) - return(book->dec_index[packed_entry]); + /* we have the unpacked multiplicands; compute final vals */ + { + int shiftM=point-s->q_delp; + tremor_ogg_int32_t add=point-s->q_minp; + if(add>0) + add= s->q_min >> add; + else + add= s->q_min << -add; + + if(shiftM>0) + for(i=0;i<s->dim;i++) + v[i]= add + ((v[i] * s->q_del) >> shiftM); + else + for(i=0;i<s->dim;i++) + v[i]= add + ((v[i] * s->q_del) << -shiftM); + + if(s->q_seq) + for(i=1;i<s->dim;i++) + v[i]+=v[i-1]; } - /* if there's no dec_index, the codebook unpacking isn't collapsed */ - return(-1); + return 0; } /* returns 0 on OK or -1 on eof *************************************/ -/* decode vector / dim granularity gaurding is done in the upper layer */ -long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a, - oggpack_buffer *b,int n,int point){ - if(book->used_entries>0){ +/* decode vector / dim granularity guarding is done in the upper layer */ +long vorbis_book_decodevs_add(codebook *book,tremor_ogg_int32_t *a, + tremor_oggpack_buffer *b,int n,int point){ + if(book->used_entries>0){ int step=n/book->dim; - long *entry = (long *)alloca(sizeof(*entry)*step); - ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step); + tremor_ogg_int32_t *v = (tremor_ogg_int32_t *)alloca(sizeof(*v)*book->dim); int i,j,o; - int shift=point-book->binarypoint; - if(shift>=0){ - for (i = 0; i < step; i++) { - entry[i]=decode_packed_entry_number(book,b); - if(entry[i]==-1)return(-1); - t[i] = book->valuelist+entry[i]*book->dim; - } - for(i=0,o=0;i<book->dim;i++,o+=step) - for (j=0;o+j<n && j<step;j++) - a[o+j]+=t[j][i]>>shift; - }else{ - for (i = 0; i < step; i++) { - entry[i]=decode_packed_entry_number(book,b); - if(entry[i]==-1)return(-1); - t[i] = book->valuelist+entry[i]*book->dim; - } - for(i=0,o=0;i<book->dim;i++,o+=step) - for (j=0;o+j<n && j<step;j++) - a[o+j]+=t[j][i]<<-shift; + for (j=0;j<step;j++){ + if(decode_map(book,b,v,point))return -1; + for(i=0,o=j;i<book->dim;i++,o+=step) + a[o]+=v[i]; } } - return(0); + return 0; } -/* decode vector / dim granularity gaurding is done in the upper layer */ -long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a, - oggpack_buffer *b,int n,int point){ +/* decode vector / dim granularity guarding is done in the upper layer */ +long vorbis_book_decodev_add(codebook *book,tremor_ogg_int32_t *a, + tremor_oggpack_buffer *b,int n,int point){ if(book->used_entries>0){ - int i,j,entry; - ogg_int32_t *t; - int shift=point-book->binarypoint; + tremor_ogg_int32_t *v = (tremor_ogg_int32_t *)alloca(sizeof(*v)*book->dim); + int i,j; - if(shift>=0){ - for(i=0;i<n;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - t = book->valuelist+entry*book->dim; - for (j=0;i<n && j<book->dim;) - a[i++]+=t[j++]>>shift; - } - }else{ - for(i=0;i<n;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - t = book->valuelist+entry*book->dim; - for (j=0;i<n && j<book->dim;) - a[i++]+=t[j++]<<-shift; - } + for(i=0;i<n;){ + if(decode_map(book,b,v,point))return -1; + for (j=0;i<n && j<book->dim;j++) + a[i++]+=v[j]; } } - return(0); + return 0; } /* unlike the others, we guard against n not being an integer number - of <dim> internally rather than in the upper layer (called only by - floor0) */ -long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a, - oggpack_buffer *b,int n,int point){ + * of <dim> internally rather than in the upper layer (called only by + * floor0) */ +long vorbis_book_decodev_set(codebook *book,tremor_ogg_int32_t *a, + tremor_oggpack_buffer *b,int n,int point){ if(book->used_entries>0){ - int i,j,entry; - ogg_int32_t *t; - int shift=point-book->binarypoint; + tremor_ogg_int32_t *v = (tremor_ogg_int32_t *)alloca(sizeof(*v)*book->dim); + int i,j; - if(shift>=0){ - - for(i=0;i<n;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - t = book->valuelist+entry*book->dim; - for (j=0;i<n && j<book->dim;){ - a[i++]=t[j++]>>shift; - } - } - }else{ - - for(i=0;i<n;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - t = book->valuelist+entry*book->dim; - for (j=0;i<n && j<book->dim;){ - a[i++]=t[j++]<<-shift; - } - } + for(i=0;i<n;){ + if(decode_map(book,b,v,point))return -1; + for (j=0;i<n && j<book->dim;j++) + a[i++]=v[j]; } }else{ - - int i,j; + int i; + for(i=0;i<n;){ a[i++]=0; } } - return(0); + + return 0; } -/* decode vector / dim granularity gaurding is done in the upper layer */ -long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,\ +/* decode vector / dim granularity guarding is done in the upper layer */ +long vorbis_book_decodevv_add(codebook *book,tremor_ogg_int32_t **a, long offset,int ch, - oggpack_buffer *b,int n,int point){ + tremor_oggpack_buffer *b,int n,int point){ if(book->used_entries>0){ - long i,j,entry; + + tremor_ogg_int32_t *v = (tremor_ogg_int32_t *)alloca(sizeof(*v)*book->dim); + long i,j; int chptr=0; - int shift=point-book->binarypoint; - int m=offset+n; - if(shift>=0){ - - for(i=offset;i<m;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - { - const ogg_int32_t *t = book->valuelist+entry*book->dim; - for (j=0;i<m && j<book->dim;j++){ - a[chptr++][i]+=t[j]>>shift; - if(chptr==ch){ - chptr=0; - i++; - } - } - } - } - }else{ - - for(i=offset;i<m;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - { - const ogg_int32_t *t = book->valuelist+entry*book->dim; - for (j=0;i<m && j<book->dim;j++){ - a[chptr++][i]+=t[j]<<-shift; - if(chptr==ch){ - chptr=0; - i++; - } - } + long m=offset+n; + + for(i=offset;i<m;){ + if(decode_map(book,b,v,point))return -1; + for (j=0;i<m && j<book->dim;j++){ + a[chptr++][i]+=v[j]; + if(chptr==ch){ + chptr=0; + i++; } } } } - return(0); + + return 0; } diff --git a/lib/tremor/codebook.h b/lib/tremor/codebook.h index bb139426..a32f0f7a 100644 --- a/lib/tremor/codebook.h +++ b/lib/tremor/codebook.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,82 +18,46 @@ #ifndef _V_CODEBOOK_H_ #define _V_CODEBOOK_H_ -#include <ogg/ogg.h> - -/* This structure encapsulates huffman and VQ style encoding books; it - doesn't do anything specific to either. - - valuelist/quantlist are nonNULL (and q_* significant) only if - there's entry->value mapping to be done. - - If encode-side mapping must be done (and thus the entry needs to be - hunted), the auxiliary encode pointer will point to a decision - tree. This is true of both VQ and huffman, but is mostly useful - with VQ. - -*/ - -typedef struct static_codebook{ - long dim; /* codebook dimensions (elements per vector) */ - long entries; /* codebook entries */ - long *lengthlist; /* codeword lengths in bits */ - - /* mapping ***************************************************************/ - int maptype; /* 0=none - 1=implicitly populated values from map column - 2=listed arbitrary values */ - - /* The below does a linear, single monotonic sequence mapping. */ - long q_min; /* packed 32 bit float; quant value 0 maps to minval */ - long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */ - int q_quant; /* bits: 0 < quant <= 16 */ - int q_sequencep; /* bitflag */ - - long *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map - map == 2: list of dim*entries quantized entry vals - */ -} static_codebook; +#include "tremor_ogg.h" typedef struct codebook{ - long dim; /* codebook dimensions (elements per vector) */ - long entries; /* codebook entries */ - long used_entries; /* populated codebook entries */ - - /* the below are ordered by bitreversed codeword and only used - entries are populated */ - int binarypoint; - ogg_int32_t *valuelist; /* list of dim*entries actual entry values */ - ogg_uint32_t *codelist; /* list of bitstream codewords for each entry */ - - int *dec_index; - char *dec_codelengths; - ogg_uint32_t *dec_firsttable; - int dec_firsttablen; - int dec_maxlength; - - long q_min; /* packed 32 bit float; quant value 0 maps to minval */ - long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */ + long dim; /* codebook dimensions (elements per vector) */ + long entries; /* codebook entries */ + long used_entries; /* populated codebook entries */ + + int dec_maxlength; + void *dec_table; + int dec_nodeb; + int dec_leafw; + int dec_type; /* 0 = entry number + 1 = packed vector of values + 2 = packed vector of column offsets, maptype 1 + 3 = scalar offset into value array, maptype 2 */ + + tremor_ogg_int32_t q_min; + int q_minp; + tremor_ogg_int32_t q_del; + int q_delp; + int q_seq; + int q_bits; + int q_pack; + void *q_val; } codebook; -extern void vorbis_staticbook_destroy(static_codebook *b); -extern int vorbis_book_init_decode(codebook *dest,const static_codebook *source); - extern void vorbis_book_clear(codebook *b); -extern long _book_maptype1_quantvals(const static_codebook *b); - -extern static_codebook *vorbis_staticbook_unpack(oggpack_buffer *b); - -extern long vorbis_book_decode(codebook *book, oggpack_buffer *b); -extern long vorbis_book_decodevs_add(codebook *book, ogg_int32_t *a, - oggpack_buffer *b,int n,int point); -extern long vorbis_book_decodev_set(codebook *book, ogg_int32_t *a, - oggpack_buffer *b,int n,int point); -extern long vorbis_book_decodev_add(codebook *book, ogg_int32_t *a, - oggpack_buffer *b,int n,int point); -extern long vorbis_book_decodevv_add(codebook *book, ogg_int32_t **a, +extern int vorbis_book_unpack(tremor_oggpack_buffer *b,codebook *c); + +extern long vorbis_book_decode(codebook *book, tremor_oggpack_buffer *b); +extern long vorbis_book_decodevs_add(codebook *book, tremor_ogg_int32_t *a, + tremor_oggpack_buffer *b,int n,int point); +extern long vorbis_book_decodev_set(codebook *book, tremor_ogg_int32_t *a, + tremor_oggpack_buffer *b,int n,int point); +extern long vorbis_book_decodev_add(codebook *book, tremor_ogg_int32_t *a, + tremor_oggpack_buffer *b,int n,int point); +extern long vorbis_book_decodevv_add(codebook *book, tremor_ogg_int32_t **a, long off,int ch, - oggpack_buffer *b,int n,int point); + tremor_oggpack_buffer *b,int n,int point); extern int _ilog(unsigned int v); diff --git a/lib/tremor/codec_internal.h b/lib/tremor/codec_internal.h index 3ca7f547..f9a768bb 100644 --- a/lib/tremor/codec_internal.h +++ b/lib/tremor/codec_internal.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,36 +18,149 @@ #ifndef _V_CODECI_H_ #define _V_CODECI_H_ +#define CHUNKSIZE 1024 + #include "codebook.h" +#include "ivorbiscodec.h" + +#define VI_TRANSFORMB 1 +#define VI_WINDOWB 1 +#define VI_TIMEB 1 +#define VI_FLOORB 2 +#define VI_RESB 3 +#define VI_MAPB 1 -typedef void vorbis_look_mapping; -typedef void vorbis_look_floor; -typedef void vorbis_look_residue; -typedef void vorbis_look_transform; +typedef void vorbis_info_floor; + +/* vorbis_dsp_state buffers the current vorbis audio + analysis/synthesis state. The DSP state belongs to a specific + logical bitstream ****************************************************/ +struct vorbis_dsp_state{ + vorbis_info *vi; + tremor_oggpack_buffer opb; + + tremor_ogg_int32_t **work; + tremor_ogg_int32_t **mdctright; + int out_begin; + int out_end; + + long lW; + long W; + + tremor_ogg_int64_t granulepos; + tremor_ogg_int64_t sequence; + tremor_ogg_int64_t sample_count; + +}; + + +/* Floor backend generic *****************************************/ + +extern vorbis_info_floor *floor0_info_unpack(vorbis_info *,tremor_oggpack_buffer *); +extern void floor0_free_info(vorbis_info_floor *); +extern int floor0_memosize(vorbis_info_floor *); +extern tremor_ogg_int32_t *floor0_inverse1(struct vorbis_dsp_state *, + vorbis_info_floor *,tremor_ogg_int32_t *); +extern int floor0_inverse2 (struct vorbis_dsp_state *,vorbis_info_floor *, + tremor_ogg_int32_t *buffer,tremor_ogg_int32_t *); + +extern vorbis_info_floor *floor1_info_unpack(vorbis_info *,tremor_oggpack_buffer *); +extern void floor1_free_info(vorbis_info_floor *); +extern int floor1_memosize(vorbis_info_floor *); +extern tremor_ogg_int32_t *floor1_inverse1(struct vorbis_dsp_state *, + vorbis_info_floor *,tremor_ogg_int32_t *); +extern int floor1_inverse2 (struct vorbis_dsp_state *,vorbis_info_floor *, + tremor_ogg_int32_t *buffer,tremor_ogg_int32_t *); + +typedef struct{ + int order; + long rate; + long barkmap; + + int ampbits; + int ampdB; + + int numbooks; /* <= 16 */ + char books[16]; + +} vorbis_info_floor0; + +typedef struct{ + char class_dim; /* 1 to 8 */ + char class_subs; /* 0,1,2,3 (bits: 1<<n poss) */ + unsigned char class_book; /* subs ^ dim entries */ + unsigned char class_subbook[8]; /* [VIF_CLASS][subs] */ +} floor1class; + +typedef struct{ + floor1class *class; /* [VIF_CLASS] */ + char *partitionclass; /* [VIF_PARTS]; 0 to 15 */ + tremor_ogg_uint16_t *postlist; /* [VIF_POSIT+2]; first two implicit */ + char *forward_index; /* [VIF_POSIT+2]; */ + char *hineighbor; /* [VIF_POSIT]; */ + char *loneighbor; /* [VIF_POSIT]; */ + + int partitions; /* 0 to 31 */ + int posts; + int mult; /* 1 2 3 or 4 */ + +} vorbis_info_floor1; + +/* Residue backend generic *****************************************/ + +typedef struct vorbis_info_residue{ + int type; + unsigned char *stagemasks; + unsigned char *stagebooks; + +/* block-partitioned VQ coded straight residue */ + long begin; + long end; + + /* first stage (lossless partitioning) */ + int grouping; /* group n vectors per partition */ + char partitions; /* possible codebooks for a partition */ + unsigned char groupbook; /* huffbook for partitioning */ + char stages; +} vorbis_info_residue; + +extern void res_clear_info(vorbis_info_residue *info); +extern int res_unpack(vorbis_info_residue *info, + vorbis_info *vi,tremor_oggpack_buffer *opb); +extern int res_inverse(vorbis_dsp_state *,vorbis_info_residue *info, + tremor_ogg_int32_t **in,int *nonzero,int ch); /* mode ************************************************************/ typedef struct { - int blockflag; - int windowtype; - int transformtype; - int mapping; + unsigned char blockflag; + unsigned char mapping; } vorbis_info_mode; -typedef void vorbis_info_floor; -typedef void vorbis_info_residue; -typedef void vorbis_info_mapping; +/* Mapping backend generic *****************************************/ +typedef struct coupling_step{ + unsigned char mag; + unsigned char ang; +} coupling_step; -typedef struct private_state { - /* local lookup storage */ - const void *window[2]; +typedef struct submap{ + char floor; + char residue; +} submap; - /* backend lookups are tied to the mode, not the backend or naked mapping */ - int modebits; - vorbis_look_mapping **mode; +typedef struct vorbis_info_mapping{ + int submaps; + + unsigned char *chmuxlist; + submap *submaplist; - ogg_int64_t sample_count; + int coupling_steps; + coupling_step *coupling; +} vorbis_info_mapping; -} private_state; +extern int mapping_info_unpack(vorbis_info_mapping *,vorbis_info *, + tremor_oggpack_buffer *); +extern void mapping_clear_info(vorbis_info_mapping *); +extern int mapping_inverse(struct vorbis_dsp_state *,vorbis_info_mapping *); /* codec_setup_info contains all the setup information specific to the specific compression/decompression mode in progress (eg, @@ -69,24 +182,32 @@ typedef struct codec_setup_info { int modes; int maps; - int times; int floors; int residues; int books; - vorbis_info_mode *mode_param[64]; - int map_type[64]; - vorbis_info_mapping *map_param[64]; - int time_type[64]; - int floor_type[64]; - vorbis_info_floor *floor_param[64]; - int residue_type[64]; - vorbis_info_residue *residue_param[64]; - static_codebook *book_param[256]; - codebook *fullbooks; - - int passlimit[32]; /* iteration limit per couple/quant pass */ - int coupling_passes; + vorbis_info_mode *mode_param; + vorbis_info_mapping *map_param; + char *floor_type; + vorbis_info_floor **floor_param; + vorbis_info_residue *residue_param; + codebook *book_param; + } codec_setup_info; +extern vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi); +extern void vorbis_dsp_destroy(vorbis_dsp_state *v); +extern int vorbis_dsp_headerin(vorbis_info *vi,vorbis_comment *vc, + tremor_ogg_packet *op); + +extern int vorbis_dsp_restart(vorbis_dsp_state *v); +extern int vorbis_dsp_synthesis(vorbis_dsp_state *vd, + tremor_ogg_packet *op,int decodep); +extern int vorbis_dsp_pcmout(vorbis_dsp_state *v, + tremor_ogg_int16_t *pcm,int samples); +extern int vorbis_dsp_read(vorbis_dsp_state *v,int samples); +extern long vorbis_packet_blocksize(vorbis_info *vi,tremor_ogg_packet *op); + + + #endif diff --git a/lib/tremor/config_types.h b/lib/tremor/config_types.h index 1fdcb27f..a8873564 100644 --- a/lib/tremor/config_types.h +++ b/lib/tremor/config_types.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -17,9 +17,10 @@ #ifndef _OS_CVTYPES_H #define _OS_CVTYPES_H -typedef long long ogg_int64_t; -typedef int ogg_int32_t; -typedef unsigned int ogg_uint32_t; -typedef short ogg_int16_t; +typedef long long tremor_ogg_int64_t; +typedef int tremor_ogg_int32_t; +typedef unsigned int tremor_ogg_uint32_t; +typedef short tremor_ogg_int16_t; +typedef unsigned short tremor_ogg_uint16_t; #endif diff --git a/lib/tremor/configure.in b/lib/tremor/configure.in index e7f56900..a247f79c 100644 --- a/lib/tremor/configure.in +++ b/lib/tremor/configure.in @@ -51,7 +51,7 @@ if test -z "$GCC"; then arm-*-*) DEBUG="-g -D_ARM_ASSEM_" CFLAGS="-O -D_ARM_ASSEM_" - PROFILE="-p -g -O -D_ARM_ASSEM_" ;; + PROFILE="-p -g -O -D_ARM_ASSEM" ;; *) DEBUG="-g" CFLAGS="-O" @@ -61,12 +61,12 @@ else case $host in arm-*-*) - DEBUG="-g -Wall -D__NO_MATH_INLINES -fsigned-char -D_ARM_ASSEM_" - CFLAGS="-O2 -D_ARM_ASSEM_ -fsigned-char" - PROFILE="-W -pg -g -O2 -D_ARM_ASSEM_ -fsigned-char -fno-inline-functions";; + DEBUG="-g -Wall -W -D__NO_MATH_INLINES -fsigned-char -D_ARM_ASSEM_" + CFLAGS="-O2 -Wall -D_ARM_ASSEM_ -fsigned-char" + PROFILE="-Wall -pg -g -O2 -D_ARM_ASSEM_ -fsigned-char -fno-inline-functions";; *) - DEBUG="-g -Wall -D__NO_MATH_INLINES -fsigned-char" + DEBUG="-g -Wall -W -D__NO_MATH_INLINES -fsigned-char" CFLAGS="-O2 -Wall -fsigned-char" PROFILE="-Wall -pg -g -O2 -fsigned-char -fno-inline-functions";; esac @@ -93,6 +93,12 @@ AC_ARG_ENABLE( CFLAGS="$CFLAGS -D_LOW_ACCURACY_" ) +AC_ARG_ENABLE( + 64kHz-limit, + [ --enable-64kHz-limit limit playback ability to <64kHz files], + CFLAGS="$CFLAGS -DLIMIT_TO_64kHz" +) + dnl -------------------------------------------------- dnl Check for headers dnl -------------------------------------------------- @@ -106,27 +112,6 @@ dnl -------------------------------------------------- dnl none dnl -------------------------------------------------- -dnl Check for libraries -dnl -------------------------------------------------- - -PKG_PROG_PKG_CONFIG - -HAVE_OGG=no -if test "x$PKG_CONFIG" != "x" -then - PKG_CHECK_MODULES(OGG, ogg >= 1.0, HAVE_OGG=yes, HAVE_OGG=no) -fi -if test "x$HAVE_OGG" = "xno" -then - dnl fall back to the old school test - XIPH_PATH_OGG(, AC_MSG_ERROR(must have Ogg installed!)) - libs_save=$LIBS - LIBS="$OGG_LIBS" - AC_CHECK_FUNC(oggpack_writealign, , AC_MSG_ERROR(Ogg >= 1.0 required !)) - LIBS=$libs_save -fi - -dnl -------------------------------------------------- dnl Check for library functions dnl -------------------------------------------------- diff --git a/lib/tremor/dsp.c b/lib/tremor/dsp.c new file mode 100644 index 00000000..35a82d66 --- /dev/null +++ b/lib/tremor/dsp.c @@ -0,0 +1,298 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: PCM data vector blocking, windowing and dis/reassembly + + ********************************************************************/ + +#include <stdlib.h> +#include "tremor_ogg.h" +#include "mdct.h" +#include "ivorbiscodec.h" +#include "codec_internal.h" +#include "misc.h" +#include "window_lookup.h" + +int vorbis_dsp_restart(vorbis_dsp_state *v){ + if(!v)return -1; + { + vorbis_info *vi=v->vi; + codec_setup_info *ci; + + if(!vi)return -1; + ci=vi->codec_setup; + if(!ci)return -1; + + v->out_end=-1; + v->out_begin=-1; + + v->granulepos=-1; + v->sequence=-1; + v->sample_count=-1; + } + return 0; +} + +vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){ + int i; + + vorbis_dsp_state *v=_tremor_ogg_calloc(1,sizeof(*v)); + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; + + v->vi=vi; + + v->work=(tremor_ogg_int32_t **)_tremor_ogg_malloc(vi->channels*sizeof(*v->work)); + v->mdctright=(tremor_ogg_int32_t **)_tremor_ogg_malloc(vi->channels*sizeof(*v->mdctright)); + for(i=0;i<vi->channels;i++){ + v->work[i]=(tremor_ogg_int32_t *)_tremor_ogg_calloc(1,(ci->blocksizes[1]>>1)* + sizeof(*v->work[i])); + v->mdctright[i]=(tremor_ogg_int32_t *)_tremor_ogg_calloc(1,(ci->blocksizes[1]>>2)* + sizeof(*v->mdctright[i])); + } + + v->lW=0; /* previous window size */ + v->W=0; /* current window size */ + + vorbis_dsp_restart(v); + return v; +} + +void vorbis_dsp_destroy(vorbis_dsp_state *v){ + int i; + if(v){ + vorbis_info *vi=v->vi; + + if(v->work){ + for(i=0;i<vi->channels;i++) + if(v->work[i])_tremor_ogg_free(v->work[i]); + _tremor_ogg_free(v->work); + } + if(v->mdctright){ + for(i=0;i<vi->channels;i++) + if(v->mdctright[i])_tremor_ogg_free(v->mdctright[i]); + _tremor_ogg_free(v->mdctright); + } + + _tremor_ogg_free(v); + } +} + +static LOOKUP_T *_vorbis_window(int left){ + switch(left){ + case 32: + return vwin64; + case 64: + return vwin128; + case 128: + return vwin256; + case 256: + return vwin512; + case 512: + return vwin1024; + case 1024: + return vwin2048; + case 2048: + return vwin4096; +#ifndef LIMIT_TO_64kHz + case 4096: + return vwin8192; +#endif + default: + return(0); + } +} + +/* pcm==0 indicates we just want the pending samples, no more */ +int vorbis_dsp_pcmout(vorbis_dsp_state *v,tremor_ogg_int16_t *pcm,int samples){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; + if(v->out_begin>-1 && v->out_begin<v->out_end){ + int n=v->out_end-v->out_begin; + if(pcm){ + int i; + if(n>samples)n=samples; + for(i=0;i<vi->channels;i++) + mdct_unroll_lap(ci->blocksizes[0],ci->blocksizes[1], + v->lW,v->W,v->work[i],v->mdctright[i], + _vorbis_window(ci->blocksizes[0]>>1), + _vorbis_window(ci->blocksizes[1]>>1), + pcm+i,vi->channels, + v->out_begin,v->out_begin+n); + } + return(n); + } + return(0); +} + +int vorbis_dsp_read(vorbis_dsp_state *v,int s){ + if(s && v->out_begin+s>v->out_end)return(OV_EINVAL); + v->out_begin+=s; + return(0); +} + +long vorbis_packet_blocksize(vorbis_info *vi,tremor_ogg_packet *op){ + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; + tremor_oggpack_buffer opb; + int mode; + int modebits=0; + int v=ci->modes; + + tremor_oggpack_readinit(&opb,op->packet); + + /* Check the packet type */ + if(tremor_oggpack_read(&opb,1)!=0){ + /* Oops. This is not an audio data packet */ + return(OV_ENOTAUDIO); + } + + while(v>1){ + modebits++; + v>>=1; + } + + /* read our mode and pre/post windowsize */ + mode=tremor_oggpack_read(&opb,modebits); + if(mode==-1)return(OV_EBADPACKET); + return(ci->blocksizes[ci->mode_param[mode].blockflag]); +} + + +static int ilog(tremor_ogg_uint32_t v){ + int ret=0; + if(v)--v; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +int vorbis_dsp_synthesis(vorbis_dsp_state *vd,tremor_ogg_packet *op,int decodep){ + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; + int mode,i; + + tremor_oggpack_readinit(&vd->opb,op->packet); + + /* Check the packet type */ + if(tremor_oggpack_read(&vd->opb,1)!=0){ + /* Oops. This is not an audio data packet */ + return OV_ENOTAUDIO ; + } + + /* read our mode and pre/post windowsize */ + mode=tremor_oggpack_read(&vd->opb,ilog(ci->modes)); + if(mode==-1 || mode>=ci->modes) return OV_EBADPACKET; + + /* shift information we still need from last window */ + vd->lW=vd->W; + vd->W=ci->mode_param[mode].blockflag; + for(i=0;i<vi->channels;i++) + mdct_shift_right(ci->blocksizes[vd->lW],vd->work[i],vd->mdctright[i]); + + if(vd->W){ + int temp; + tremor_oggpack_read(&vd->opb,1); + temp=tremor_oggpack_read(&vd->opb,1); + if(temp==-1) return OV_EBADPACKET; + } + + /* packet decode and portions of synthesis that rely on only this block */ + if(decodep){ + mapping_inverse(vd,ci->map_param+ci->mode_param[mode].mapping); + + if(vd->out_begin==-1){ + vd->out_begin=0; + vd->out_end=0; + }else{ + vd->out_begin=0; + vd->out_end=ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4; + } + } + + /* track the frame number... This is for convenience, but also + making sure our last packet doesn't end with added padding. + + This is not foolproof! It will be confused if we begin + decoding at the last page after a seek or hole. In that case, + we don't have a starting point to judge where the last frame + is. For this reason, vorbisfile will always try to make sure + it reads the last two marked pages in proper sequence */ + + /* if we're out of sequence, dump granpos tracking until we sync back up */ + if(vd->sequence==-1 || vd->sequence+1 != op->packetno-3){ + /* out of sequence; lose count */ + vd->granulepos=-1; + vd->sample_count=-1; + } + + vd->sequence=op->packetno; + vd->sequence=vd->sequence-3; + + if(vd->sample_count==-1){ + vd->sample_count=0; + }else{ + vd->sample_count+= + ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4; + } + + if(vd->granulepos==-1){ + if(op->granulepos!=-1){ /* only set if we have a + position to set to */ + + vd->granulepos=op->granulepos; + + /* is this a short page? */ + if(vd->sample_count>vd->granulepos){ + /* corner case; if this is both the first and last audio page, + then spec says the end is cut, not beginning */ + if(op->e_o_s){ + /* trim the end */ + /* no preceeding granulepos; assume we started at zero (we'd + have to in a short single-page stream) */ + /* granulepos could be -1 due to a seek, but that would result + in a long coun t, not short count */ + + vd->out_end-=vd->sample_count-vd->granulepos; + }else{ + /* trim the beginning */ + vd->out_begin+=vd->sample_count-vd->granulepos; + if(vd->out_begin>vd->out_end) + vd->out_begin=vd->out_end; + } + + } + + } + }else{ + vd->granulepos+= + ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4; + if(op->granulepos!=-1 && vd->granulepos!=op->granulepos){ + + if(vd->granulepos>op->granulepos){ + long extra=vd->granulepos-op->granulepos; + + if(extra) + if(op->e_o_s){ + /* partial last frame. Strip the extra samples off */ + vd->out_end-=extra; + } /* else {Shouldn't happen *unless* the bitstream is out of + spec. Either way, believe the bitstream } */ + } /* else {Shouldn't happen *unless* the bitstream is out of + spec. Either way, believe the bitstream } */ + vd->granulepos=op->granulepos; + } + } + + return(0); +} diff --git a/lib/tremor/floor0.c b/lib/tremor/floor0.c index 964383ef..9e4a1a30 100644 --- a/lib/tremor/floor0.c +++ b/lib/tremor/floor0.c @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,26 +18,15 @@ #include <stdlib.h> #include <string.h> #include <math.h> -#include <ogg/ogg.h> +#include "tremor_ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" -#include "registry.h" #include "codebook.h" #include "misc.h" -#include "block.h" +#include "os.h" #define LSP_FRACBITS 14 - -typedef struct { - long n; - int ln; - int m; - int *linearmap; - - vorbis_info_floor0 *vi; - ogg_int32_t *lsp_look; - -} vorbis_look_floor0; +extern const tremor_ogg_int32_t FLOOR_fromdB_LOOKUP[]; /*************** LSP decode ********************/ @@ -48,7 +37,7 @@ typedef struct { returns in m.8 format */ static long ADJUST_SQRT2[2]={8192,5792}; -STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){ +static inline tremor_ogg_int32_t vorbis_invsqlook_i(long a,long e){ long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); long d=a&INVSQ_LOOKUP_I_MASK; /* 0.10 */ long val=INVSQ_LOOKUP_I[i]- /* 1.16 */ @@ -60,60 +49,60 @@ STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){ /* interpolated lookup based fromdB function, domain -140dB to 0dB only */ /* a is in n.12 format */ -STIN ogg_int32_t vorbis_fromdBlook_i(long a){ - int i=(-a)>>(12-FROMdB2_SHIFT); - if(i<0) return 0x7fffffff; - if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0; - - return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK]; +#ifdef _LOW_ACCURACY_ +static inline tremor_ogg_int32_t vorbis_fromdBlook_i(long a){ + if(a>0) return 0x7fffffff; + if(a<(-140<<12)) return 0; + return FLOOR_fromdB_LOOKUP[((a+140)*467)>>20]<<9; +} +#else +static inline tremor_ogg_int32_t vorbis_fromdBlook_i(long a){ + if(a>0) return 0x7fffffff; + if(a<(-140<<12)) return 0; + return FLOOR_fromdB_LOOKUP[((a+(140<<12))*467)>>20]; } +#endif /* interpolated lookup based cos function, domain 0 to PI only */ /* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */ -STIN ogg_int32_t vorbis_coslook_i(long a){ +static inline tremor_ogg_int32_t vorbis_coslook_i(long a){ int i=a>>COS_LOOKUP_I_SHIFT; int d=a&COS_LOOKUP_I_MASK; return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>> COS_LOOKUP_I_SHIFT); } -/* interpolated lookup based cos function */ +/* interpolated half-wave lookup based cos function */ /* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */ -STIN ogg_int32_t vorbis_coslook2_i(long a){ - a=a&0x1ffff; - - if(a>0x10000)a=0x20000-a; - { - int i=a>>COS_LOOKUP_I_SHIFT; - int d=a&COS_LOOKUP_I_MASK; - a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)- - d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>> - (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14); - } - - return(a); +static inline tremor_ogg_int32_t vorbis_coslook2_i(long a){ + int i=a>>COS_LOOKUP_I_SHIFT; + int d=a&COS_LOOKUP_I_MASK; + return ((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)- + d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>> + (COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14); } -static const int barklook[28]={ - 0,100,200,301, 405,516,635,766, - 912,1077,1263,1476, 1720,2003,2333,2721, - 3184,3742,4428,5285, 6376,7791,9662,12181, - 15624,20397,27087,36554 +static const tremor_ogg_uint16_t barklook[54]={ + 0,51,102,154, 206,258,311,365, + 420,477,535,594, 656,719,785,854, + 926,1002,1082,1166, 1256,1352,1454,1564, + 1683,1812,1953,2107, 2276,2463,2670,2900, + 3155,3440,3756,4106, 4493,4919,5387,5901, + 6466,7094,7798,8599, 9528,10623,11935,13524, + 15453,17775,20517,23667, 27183,31004 }; /* used in init only; interpolate the long way */ -STIN ogg_int32_t toBARK(int n){ +static inline tremor_ogg_int32_t toBARK(int n){ int i; - for(i=0;i<27;i++) + for(i=0;i<54;i++) if(n>=barklook[i] && n<barklook[i+1])break; - if(i==27){ - return 27<<15; + if(i==54){ + return 54<<14; }else{ - int gap=barklook[i+1]-barklook[i]; - int del=n-barklook[i]; - - return((i<<15)+((del<<15)/gap)); + return (i<<14)+(((n-barklook[i])* + ((1UL<<31)/(barklook[i+1]-barklook[i])))>>17); } } @@ -133,11 +122,11 @@ static const unsigned char MLOOP_2[64]={ static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3}; -void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln, - ogg_int32_t *lsp,int m, - ogg_int32_t amp, - ogg_int32_t ampoffset, - ogg_int32_t *icos){ +void vorbis_lsp_to_curve(tremor_ogg_int32_t *curve,int n,int ln, + tremor_ogg_int32_t *lsp,int m, + tremor_ogg_int32_t amp, + tremor_ogg_int32_t ampoffset, + tremor_ogg_int32_t nyq){ /* 0 <= m < 256 */ @@ -145,13 +134,34 @@ void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln, int i; int ampoffseti=ampoffset*4096; int ampi=amp; - ogg_int32_t *ilsp=(ogg_int32_t *)alloca(m*sizeof(*ilsp)); + tremor_ogg_int32_t *ilsp=(tremor_ogg_int32_t *)alloca(m*sizeof(*ilsp)); + + tremor_ogg_uint32_t inyq= (1UL<<31) / toBARK(nyq); + tremor_ogg_uint32_t imap= (1UL<<31) / ln; + tremor_ogg_uint32_t tBnyq1 = toBARK(nyq)<<1; + + /* Besenham for frequency scale to avoid a division */ + int f=0; + int fdx=n; + int fbase=nyq/fdx; + int ferr=0; + int fdy=nyq-fbase*fdx; + int map=0; + +#ifdef _LOW_ACCURACY_ + tremor_ogg_uint32_t nextbark=((tBnyq1<<11)/ln)>>12; +#else + tremor_ogg_uint32_t nextbark=MULT31(imap>>1,tBnyq1); +#endif + int nextf=barklook[nextbark>>14]+(((nextbark&0x3fff)* + (barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14); + /* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/ for(i=0;i<m;i++){ #ifndef _LOW_ACCURACY_ - ogg_int32_t val=MULT32(lsp[i],0x517cc2); + tremor_ogg_int32_t val=MULT32(lsp[i],0x517cc2); #else - ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14; + tremor_ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14; #endif /* safeguard against a malicious stream */ @@ -165,11 +175,14 @@ void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln, i=0; while(i<n){ - int j,k=map[i]; - ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */ - ogg_uint32_t qi=46341; - ogg_int32_t qexp=0,shift; - ogg_int32_t wi=icos[k]; + int j; + tremor_ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */ + tremor_ogg_uint32_t qi=46341; + tremor_ogg_int32_t qexp=0,shift; + tremor_ogg_int32_t wi; + + wi=vorbis_coslook2_i((map*imap)>>15); + #ifdef _V_LSP_MATH_ASM lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m); @@ -197,24 +210,22 @@ void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln, #else - j=1; - if(m>1){ - qi*=labs(ilsp[0]-wi); - pi*=labs(ilsp[1]-wi); - - for(j+=2;j<m;j+=2){ - if(!(shift=MLOOP_1[(pi|qi)>>25])) - if(!(shift=MLOOP_2[(pi|qi)>>19])) - shift=MLOOP_3[(pi|qi)>>16]; - qi=(qi>>shift)*labs(ilsp[j-1]-wi); - pi=(pi>>shift)*labs(ilsp[j]-wi); - qexp+=shift; - } + qi*=labs(ilsp[0]-wi); + pi*=labs(ilsp[1]-wi); + + for(j=3;j<m;j+=2){ + if(!(shift=MLOOP_1[(pi|qi)>>25])) + if(!(shift=MLOOP_2[(pi|qi)>>19])) + shift=MLOOP_3[(pi|qi)>>16]; + + qi=(qi>>shift)*labs(ilsp[j-1]-wi); + pi=(pi>>shift)*labs(ilsp[j]-wi); + qexp+=shift; } if(!(shift=MLOOP_1[(pi|qi)>>25])) if(!(shift=MLOOP_2[(pi|qi)>>19])) shift=MLOOP_3[(pi|qi)>>16]; - + /* pi,qi normalized collectively, both tracked using qexp */ if(m&1){ @@ -282,54 +293,78 @@ void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln, amp>>=9; #endif curve[i]= MULT31_SHIFT15(curve[i],amp); - while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp); - } -} -/*************** vorbis decode glue ************/ + while(++i<n){ + + /* line plot to get new f */ + ferr+=fdy; + if(ferr>=fdx){ + ferr-=fdx; + f++; + } + f+=fbase; + + if(f>=nextf)break; -static void floor0_free_info(vorbis_info_floor *i){ - vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; - if(info){ - memset(info,0,sizeof(*info)); - _ogg_free(info); + curve[i]= MULT31_SHIFT15(curve[i],amp); + } + + while(1){ + map++; + + if(map+1<ln){ + +#ifdef _LOW_ACCURACY_ + nextbark=((tBnyq1<<11)/ln*(map+1))>>12; +#else + nextbark=MULT31((map+1)*(imap>>1),tBnyq1); +#endif + nextf=barklook[nextbark>>14]+ + (((nextbark&0x3fff)* + (barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14); + if(f<=nextf)break; + + }else{ + nextf=9999999; + break; + } + } + if(map>=ln){ + map=ln-1; /* guard against the approximation */ + nextf=9999999; + } } } -static void floor0_free_look(vorbis_look_floor *i){ - vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; - if(look){ +/*************** vorbis decode glue ************/ - if(look->linearmap)_ogg_free(look->linearmap); - if(look->lsp_look)_ogg_free(look->lsp_look); - memset(look,0,sizeof(*look)); - _ogg_free(look); - } +void floor0_free_info(vorbis_info_floor *i){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + if(info)_tremor_ogg_free(info); } -static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ +vorbis_info_floor *floor0_info_unpack (vorbis_info *vi,tremor_oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int j; - vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info)); - info->order=oggpack_read(opb,8); - info->rate=oggpack_read(opb,16); - info->barkmap=oggpack_read(opb,16); - info->ampbits=oggpack_read(opb,6); - info->ampdB=oggpack_read(opb,8); - info->numbooks=oggpack_read(opb,4)+1; + vorbis_info_floor0 *info=(vorbis_info_floor0 *)_tremor_ogg_malloc(sizeof(*info)); + info->order=tremor_oggpack_read(opb,8); + info->rate=tremor_oggpack_read(opb,16); + info->barkmap=tremor_oggpack_read(opb,16); + info->ampbits=tremor_oggpack_read(opb,6); + info->ampdB=tremor_oggpack_read(opb,8); + info->numbooks=tremor_oggpack_read(opb,4)+1; if(info->order<1)goto err_out; if(info->rate<1)goto err_out; if(info->barkmap<1)goto err_out; - if(info->numbooks<1)goto err_out; for(j=0;j<info->numbooks;j++){ - info->books[j]=oggpack_read(opb,8); - if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; - if(ci->book_param[info->books[j]]->maptype==0)goto err_out; - if(ci->book_param[info->books[j]]->dim<1)goto err_out; + info->books[j]=tremor_oggpack_read(opb,8); + if(info->books[j]>=ci->books)goto err_out; } + + if(tremor_oggpack_eop(opb))goto err_out; return(info); err_out: @@ -337,74 +372,34 @@ static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ return(NULL); } -/* initialize Bark scale and normalization lookups. We could do this - with static tables, but Vorbis allows a number of possible - combinations, so it's best to do it computationally. - - The below is authoritative in terms of defining scale mapping. - Note that the scale depends on the sampling rate as well as the - linear block and mapping sizes */ - -static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi, - vorbis_info_floor *i){ - int j; - vorbis_info *vi=vd->vi; - codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; +int floor0_memosize(vorbis_info_floor *i){ vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; - vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look)); - look->m=info->order; - look->n=ci->blocksizes[mi->blockflag]/2; - look->ln=info->barkmap; - look->vi=info; - - /* the mapping from a linear scale to a smaller bark scale is - straightforward. We do *not* make sure that the linear mapping - does not skip bark-scale bins; the decoder simply skips them and - the encoder may do what it wishes in filling them. They're - necessary in some mapping combinations to keep the scale spacing - accurate */ - look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap)); - for(j=0;j<look->n;j++){ - - int val=(look->ln* - ((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11; - - if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ - look->linearmap[j]=val; - } - look->linearmap[j]=-1; - - look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look)); - for(j=0;j<look->ln;j++) - look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln); - - return look; + return info->order+1; } -static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ - vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; - vorbis_info_floor0 *info=look->vi; +tremor_ogg_int32_t *floor0_inverse1(vorbis_dsp_state *vd,vorbis_info_floor *i, + tremor_ogg_int32_t *lsp){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; int j,k; - int ampraw=oggpack_read(&vb->opb,info->ampbits); + int ampraw=tremor_oggpack_read(&vd->opb,info->ampbits); if(ampraw>0){ /* also handles the -1 out of data case */ long maxval=(1<<info->ampbits)-1; int amp=((ampraw*info->ampdB)<<4)/maxval; - int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); + int booknum=tremor_oggpack_read(&vd->opb,_ilog(info->numbooks)); if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */ - codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; - codebook *b=ci->fullbooks+info->books[booknum]; - ogg_int32_t last=0; - ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1)); + codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; + codebook *b=ci->book_param+info->books[booknum]; + tremor_ogg_int32_t last=0; - if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m,-24)==-1)goto eop; - for(j=0;j<look->m;){ - for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last; + if(vorbis_book_decodev_set(b,lsp,&vd->opb,info->order,-24)==-1)goto eop; + for(j=0;j<info->order;){ + for(k=0;j<info->order && k<b->dim;k++,j++)lsp[j]+=last; last=lsp[j-1]; } - lsp[look->m]=amp; + lsp[info->order]=amp; return(lsp); } } @@ -412,28 +407,21 @@ static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ return(NULL); } -static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, - void *memo,ogg_int32_t *out){ - vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; - vorbis_info_floor0 *info=look->vi; +int floor0_inverse2(vorbis_dsp_state *vd,vorbis_info_floor *i, + tremor_ogg_int32_t *lsp,tremor_ogg_int32_t *out){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; - if(memo){ - ogg_int32_t *lsp=(ogg_int32_t *)memo; - ogg_int32_t amp=lsp[look->m]; + if(lsp){ + tremor_ogg_int32_t amp=lsp[info->order]; /* take the coefficients back to a spectral envelope curve */ - vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln, - lsp,look->m,amp,info->ampdB,look->lsp_look); + vorbis_lsp_to_curve(out,ci->blocksizes[vd->W]/2,info->barkmap, + lsp,info->order,amp,info->ampdB, + info->rate>>1); return(1); } - memset(out,0,sizeof(*out)*look->n); + memset(out,0,sizeof(*out)*ci->blocksizes[vd->W]/2); return(0); } -/* export hooks */ -vorbis_func_floor floor0_exportbundle={ - &floor0_unpack,&floor0_look,&floor0_free_info, - &floor0_free_look,&floor0_inverse1,&floor0_inverse2 -}; - - diff --git a/lib/tremor/floor1.c b/lib/tremor/floor1.c index e63ae9fb..1dc5f357 100644 --- a/lib/tremor/floor1.c +++ b/lib/tremor/floor1.c @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,44 +18,29 @@ #include <stdlib.h> #include <string.h> #include <math.h> -#include <ogg/ogg.h> +#include "tremor_ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" -#include "registry.h" #include "codebook.h" #include "misc.h" -#include "block.h" +extern const tremor_ogg_int32_t FLOOR_fromdB_LOOKUP[]; #define floor1_rangedB 140 /* floor 1 fixed at -140dB to 0dB range */ - -typedef struct { - int forward_index[VIF_POSIT+2]; - - int hineighbor[VIF_POSIT]; - int loneighbor[VIF_POSIT]; - int posts; - - int n; - int quant_q; - vorbis_info_floor1 *vi; - -} vorbis_look_floor1; +#define VIF_POSIT 63 /***********************************************/ -static void floor1_free_info(vorbis_info_floor *i){ +void floor1_free_info(vorbis_info_floor *i){ vorbis_info_floor1 *info=(vorbis_info_floor1 *)i; if(info){ + if(info->class)_tremor_ogg_free(info->class); + if(info->partitionclass)_tremor_ogg_free(info->partitionclass); + if(info->postlist)_tremor_ogg_free(info->postlist); + if(info->forward_index)_tremor_ogg_free(info->forward_index); + if(info->hineighbor)_tremor_ogg_free(info->hineighbor); + if(info->loneighbor)_tremor_ogg_free(info->loneighbor); memset(info,0,sizeof(*info)); - _ogg_free(info); - } -} - -static void floor1_free_look(vorbis_look_floor *i){ - vorbis_look_floor1 *look=(vorbis_look_floor1 *)i; - if(look){ - memset(look,0,sizeof(*look)); - _ogg_free(look); + _tremor_ogg_free(info); } } @@ -68,143 +53,131 @@ static int ilog(unsigned int v){ return(ret); } -static int icomp(const void *a,const void *b){ - return(**(int **)a-**(int **)b); +static void vorbis_mergesort(char *index,tremor_ogg_uint16_t *vals,tremor_ogg_uint16_t n){ + tremor_ogg_uint16_t i,j; + char *temp,*A=index,*B=_tremor_ogg_malloc(n*sizeof(*B)); + + for(i=1;i<n;i<<=1){ + for(j=0;j+i<n;){ + int k1=j; + int mid=j+i; + int k2=mid; + int end=(j+i*2<n?j+i*2:n); + while(k1<mid && k2<end){ + if(vals[A[k1]]<vals[A[k2]]) + B[j++]=A[k1++]; + else + B[j++]=A[k2++]; + } + while(k1<mid) B[j++]=A[k1++]; + while(k2<end) B[j++]=A[k2++]; + } + for(;j<n;j++)B[j]=A[j]; + temp=A;A=B;B=temp; + } + + if(B==index){ + for(j=0;j<n;j++)B[j]=A[j]; + _tremor_ogg_free(A); + }else + _tremor_ogg_free(B); } -static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){ + +vorbis_info_floor *floor1_info_unpack (vorbis_info *vi,tremor_oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int j,k,count=0,maxclass=-1,rangebits; - - vorbis_info_floor1 *info=(vorbis_info_floor1 *)_ogg_calloc(1,sizeof(*info)); + + vorbis_info_floor1 *info=(vorbis_info_floor1 *)_tremor_ogg_calloc(1,sizeof(*info)); /* read partitions */ - info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */ + info->partitions=tremor_oggpack_read(opb,5); /* only 0 to 31 legal */ + info->partitionclass= + (char *)_tremor_ogg_malloc(info->partitions*sizeof(*info->partitionclass)); for(j=0;j<info->partitions;j++){ - info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */ - if(info->partitionclass[j]<0)goto err_out; + info->partitionclass[j]=tremor_oggpack_read(opb,4); /* only 0 to 15 legal */ if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j]; } /* read partition classes */ + info->class= + (floor1class *)_tremor_ogg_malloc((maxclass+1)*sizeof(*info->class)); for(j=0;j<maxclass+1;j++){ - info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */ - info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */ - if(info->class_subs[j]<0) - goto err_out; - if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); - if(info->class_book[j]<0 || info->class_book[j]>=ci->books) - goto err_out; - for(k=0;k<(1<<info->class_subs[j]);k++){ - info->class_subbook[j][k]=oggpack_read(opb,8)-1; - if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) - goto err_out; + info->class[j].class_dim=tremor_oggpack_read(opb,3)+1; /* 1 to 8 */ + info->class[j].class_subs=tremor_oggpack_read(opb,2); /* 0,1,2,3 bits */ + if(tremor_oggpack_eop(opb)<0) goto err_out; + if(info->class[j].class_subs) + info->class[j].class_book=tremor_oggpack_read(opb,8); + else + info->class[j].class_book=0; + if(info->class[j].class_book>=ci->books)goto err_out; + for(k=0;k<(1<<info->class[j].class_subs);k++){ + info->class[j].class_subbook[k]=tremor_oggpack_read(opb,8)-1; + if(info->class[j].class_subbook[k]>=ci->books && + info->class[j].class_subbook[k]!=0xff)goto err_out; } } /* read the post list */ - info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ - rangebits=oggpack_read(opb,4); - if(rangebits<0)goto err_out; - + info->mult=tremor_oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ + rangebits=tremor_oggpack_read(opb,4); + + for(j=0,k=0;j<info->partitions;j++) + count+=info->class[info->partitionclass[j]].class_dim; + info->postlist= + (tremor_ogg_uint16_t *)_tremor_ogg_malloc((count+2)*sizeof(*info->postlist)); + info->forward_index= + (char *)_tremor_ogg_malloc((count+2)*sizeof(*info->forward_index)); + info->loneighbor= + (char *)_tremor_ogg_malloc(count*sizeof(*info->loneighbor)); + info->hineighbor= + (char *)_tremor_ogg_malloc(count*sizeof(*info->hineighbor)); + + count=0; for(j=0,k=0;j<info->partitions;j++){ - count+=info->class_dim[info->partitionclass[j]]; + count+=info->class[info->partitionclass[j]].class_dim; if(count>VIF_POSIT)goto err_out; for(;k<count;k++){ - int t=info->postlist[k+2]=oggpack_read(opb,rangebits); - if(t<0 || t>=(1<<rangebits)) - goto err_out; + int t=info->postlist[k+2]=tremor_oggpack_read(opb,rangebits); + if(t>=(1<<rangebits))goto err_out; } } + if(tremor_oggpack_eop(opb))goto err_out; info->postlist[0]=0; info->postlist[1]=1<<rangebits; - - /* don't allow repeated values in post list as they'd result in - zero-length segments */ - { - int *sortpointer[VIF_POSIT+2]; - for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j; - qsort(sortpointer,count+2,sizeof(*sortpointer),icomp); - - for(j=1;j<count+2;j++) - if(*sortpointer[j-1]==*sortpointer[j])goto err_out; - } - - return(info); - - err_out: - floor1_free_info(info); - return(NULL); -} - -static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd,vorbis_info_mode *mi, - vorbis_info_floor *in){ - - int *sortpointer[VIF_POSIT+2]; - vorbis_info_floor1 *info=(vorbis_info_floor1 *)in; - vorbis_look_floor1 *look=(vorbis_look_floor1 *)_ogg_calloc(1,sizeof(*look)); - int i,j,n=0; - - look->vi=info; - look->n=info->postlist[1]; - - /* we drop each position value in-between already decoded values, - and use linear interpolation to predict each new value past the - edges. The positions are read in the order of the position - list... we precompute the bounding positions in the lookup. Of - course, the neighbors can change (if a position is declined), but - this is an initial mapping */ - - for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]]; - n+=2; - look->posts=n; + info->posts=count+2; /* also store a sorted position index */ - for(i=0;i<n;i++)sortpointer[i]=info->postlist+i; - qsort(sortpointer,n,sizeof(*sortpointer),icomp); - - /* points from sort order back to range number */ - for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist; + for(j=0;j<info->posts;j++)info->forward_index[j]=j; + vorbis_mergesort(info->forward_index,info->postlist,info->posts); - /* quantize values to multiplier spec */ - switch(info->mult){ - case 1: /* 1024 -> 256 */ - look->quant_q=256; - break; - case 2: /* 1024 -> 128 */ - look->quant_q=128; - break; - case 3: /* 1024 -> 86 */ - look->quant_q=86; - break; - case 4: /* 1024 -> 64 */ - look->quant_q=64; - break; - } - /* discover our neighbors for decode where we don't use fit flags (that would push the neighbors outward) */ - for(i=0;i<n-2;i++){ + for(j=0;j<info->posts-2;j++){ int lo=0; int hi=1; int lx=0; - int hx=look->n; - int currentx=info->postlist[i+2]; - for(j=0;j<i+2;j++){ - int x=info->postlist[j]; + int hx=info->postlist[1]; + int currentx=info->postlist[j+2]; + for(k=0;k<j+2;k++){ + int x=info->postlist[k]; if(x>lx && x<currentx){ - lo=j; + lo=k; lx=x; } if(x<hx && x>currentx){ - hi=j; + hi=k; hx=x; } } - look->loneighbor[i]=lo; - look->hineighbor[i]=hi; + info->loneighbor[j]=lo; + info->hineighbor[j]=hi; } - return(look); + return(info); + + err_out: + floor1_free_info(info); + return(NULL); } static int render_point(int x0,int x1,int y0,int y1,int x){ @@ -223,80 +196,7 @@ static int render_point(int x0,int x1,int y0,int y1,int x){ } } -#ifdef _LOW_ACCURACY_ -# define XdB(n) ((((n)>>8)+1)>>1) -#else -# define XdB(n) (n) -#endif - -static const ogg_int32_t FLOOR_fromdB_LOOKUP[256]={ - XdB(0x000000e5), XdB(0x000000f4), XdB(0x00000103), XdB(0x00000114), - XdB(0x00000126), XdB(0x00000139), XdB(0x0000014e), XdB(0x00000163), - XdB(0x0000017a), XdB(0x00000193), XdB(0x000001ad), XdB(0x000001c9), - XdB(0x000001e7), XdB(0x00000206), XdB(0x00000228), XdB(0x0000024c), - XdB(0x00000272), XdB(0x0000029b), XdB(0x000002c6), XdB(0x000002f4), - XdB(0x00000326), XdB(0x0000035a), XdB(0x00000392), XdB(0x000003cd), - XdB(0x0000040c), XdB(0x00000450), XdB(0x00000497), XdB(0x000004e4), - XdB(0x00000535), XdB(0x0000058c), XdB(0x000005e8), XdB(0x0000064a), - XdB(0x000006b3), XdB(0x00000722), XdB(0x00000799), XdB(0x00000818), - XdB(0x0000089e), XdB(0x0000092e), XdB(0x000009c6), XdB(0x00000a69), - XdB(0x00000b16), XdB(0x00000bcf), XdB(0x00000c93), XdB(0x00000d64), - XdB(0x00000e43), XdB(0x00000f30), XdB(0x0000102d), XdB(0x0000113a), - XdB(0x00001258), XdB(0x0000138a), XdB(0x000014cf), XdB(0x00001629), - XdB(0x0000179a), XdB(0x00001922), XdB(0x00001ac4), XdB(0x00001c82), - XdB(0x00001e5c), XdB(0x00002055), XdB(0x0000226f), XdB(0x000024ac), - XdB(0x0000270e), XdB(0x00002997), XdB(0x00002c4b), XdB(0x00002f2c), - XdB(0x0000323d), XdB(0x00003581), XdB(0x000038fb), XdB(0x00003caf), - XdB(0x000040a0), XdB(0x000044d3), XdB(0x0000494c), XdB(0x00004e10), - XdB(0x00005323), XdB(0x0000588a), XdB(0x00005e4b), XdB(0x0000646b), - XdB(0x00006af2), XdB(0x000071e5), XdB(0x0000794c), XdB(0x0000812e), - XdB(0x00008993), XdB(0x00009283), XdB(0x00009c09), XdB(0x0000a62d), - XdB(0x0000b0f9), XdB(0x0000bc79), XdB(0x0000c8b9), XdB(0x0000d5c4), - XdB(0x0000e3a9), XdB(0x0000f274), XdB(0x00010235), XdB(0x000112fd), - XdB(0x000124dc), XdB(0x000137e4), XdB(0x00014c29), XdB(0x000161bf), - XdB(0x000178bc), XdB(0x00019137), XdB(0x0001ab4a), XdB(0x0001c70e), - XdB(0x0001e4a1), XdB(0x0002041f), XdB(0x000225aa), XdB(0x00024962), - XdB(0x00026f6d), XdB(0x000297f0), XdB(0x0002c316), XdB(0x0002f109), - XdB(0x000321f9), XdB(0x00035616), XdB(0x00038d97), XdB(0x0003c8b4), - XdB(0x000407a7), XdB(0x00044ab2), XdB(0x00049218), XdB(0x0004de23), - XdB(0x00052f1e), XdB(0x0005855c), XdB(0x0005e135), XdB(0x00064306), - XdB(0x0006ab33), XdB(0x00071a24), XdB(0x0007904b), XdB(0x00080e20), - XdB(0x00089422), XdB(0x000922da), XdB(0x0009bad8), XdB(0x000a5cb6), - XdB(0x000b091a), XdB(0x000bc0b1), XdB(0x000c8436), XdB(0x000d5471), - XdB(0x000e3233), XdB(0x000f1e5f), XdB(0x001019e4), XdB(0x001125c1), - XdB(0x00124306), XdB(0x001372d5), XdB(0x0014b663), XdB(0x00160ef7), - XdB(0x00177df0), XdB(0x001904c1), XdB(0x001aa4f9), XdB(0x001c603d), - XdB(0x001e384f), XdB(0x00202f0f), XdB(0x0022467a), XdB(0x002480b1), - XdB(0x0026dff7), XdB(0x002966b3), XdB(0x002c1776), XdB(0x002ef4fc), - XdB(0x0032022d), XdB(0x00354222), XdB(0x0038b828), XdB(0x003c67c2), - XdB(0x004054ae), XdB(0x004482e8), XdB(0x0048f6af), XdB(0x004db488), - XdB(0x0052c142), XdB(0x005821ff), XdB(0x005ddc33), XdB(0x0063f5b0), - XdB(0x006a74a7), XdB(0x00715faf), XdB(0x0078bdce), XdB(0x0080967f), - XdB(0x0088f1ba), XdB(0x0091d7f9), XdB(0x009b5247), XdB(0x00a56a41), - XdB(0x00b02a27), XdB(0x00bb9ce2), XdB(0x00c7ce12), XdB(0x00d4ca17), - XdB(0x00e29e20), XdB(0x00f15835), XdB(0x0101074b), XdB(0x0111bb4e), - XdB(0x01238531), XdB(0x01367704), XdB(0x014aa402), XdB(0x016020a7), - XdB(0x017702c3), XdB(0x018f6190), XdB(0x01a955cb), XdB(0x01c4f9cf), - XdB(0x01e269a8), XdB(0x0201c33b), XdB(0x0223265a), XdB(0x0246b4ea), - XdB(0x026c9302), XdB(0x0294e716), XdB(0x02bfda13), XdB(0x02ed9793), - XdB(0x031e4e09), XdB(0x03522ee4), XdB(0x03896ed0), XdB(0x03c445e2), - XdB(0x0402efd6), XdB(0x0445ac4b), XdB(0x048cbefc), XdB(0x04d87013), - XdB(0x05290c67), XdB(0x057ee5ca), XdB(0x05da5364), XdB(0x063bb204), - XdB(0x06a36485), XdB(0x0711d42b), XdB(0x0787710e), XdB(0x0804b299), - XdB(0x088a17ef), XdB(0x0918287e), XdB(0x09af747c), XdB(0x0a50957e), - XdB(0x0afc2f19), XdB(0x0bb2ef7f), XdB(0x0c759034), XdB(0x0d44d6ca), - XdB(0x0e2195bc), XdB(0x0f0cad0d), XdB(0x10070b62), XdB(0x1111aeea), - XdB(0x122da66c), XdB(0x135c120f), XdB(0x149e24d9), XdB(0x15f525b1), - XdB(0x176270e3), XdB(0x18e7794b), XdB(0x1a85c9ae), XdB(0x1c3f06d1), - XdB(0x1e14f07d), XdB(0x200963d7), XdB(0x221e5ccd), XdB(0x2455f870), - XdB(0x26b2770b), XdB(0x29363e2b), XdB(0x2be3db5c), XdB(0x2ebe06b6), - XdB(0x31c7a55b), XdB(0x3503ccd4), XdB(0x3875c5aa), XdB(0x3c210f44), - XdB(0x4009632b), XdB(0x4432b8cf), XdB(0x48a149bc), XdB(0x4d59959e), - XdB(0x52606733), XdB(0x57bad899), XdB(0x5d6e593a), XdB(0x6380b298), - XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff), -}; - -static void render_line(int n, int x0,int x1,int y0,int y1,ogg_int32_t *d){ +static void render_line(int n,int x0,int x1,int y0,int y1,tremor_ogg_int32_t *d){ int dy=y1-y0; int adx=x1-x0; int ady=abs(dy); @@ -324,42 +224,48 @@ static void render_line(int n, int x0,int x1,int y0,int y1,ogg_int32_t *d){ } } -static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ - vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; - vorbis_info_floor1 *info=look->vi; - codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; +int floor1_memosize(vorbis_info_floor *i){ + vorbis_info_floor1 *info=(vorbis_info_floor1 *)i; + return info->posts; +} + +static int quant_look[4]={256,128,86,64}; + +tremor_ogg_int32_t *floor1_inverse1(vorbis_dsp_state *vd,vorbis_info_floor *in, + tremor_ogg_int32_t *fit_value){ + vorbis_info_floor1 *info=(vorbis_info_floor1 *)in; + codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; int i,j,k; - codebook *books=ci->fullbooks; - + codebook *books=ci->book_param; + int quant_q=quant_look[info->mult-1]; + /* unpack wrapped/predicted values from stream */ - if(oggpack_read(&vb->opb,1)==1){ - int *fit_value=(int *)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value)); - - fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); - fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); + if(tremor_oggpack_read(&vd->opb,1)==1){ + fit_value[0]=tremor_oggpack_read(&vd->opb,ilog(quant_q-1)); + fit_value[1]=tremor_oggpack_read(&vd->opb,ilog(quant_q-1)); /* partition by partition */ /* partition by partition */ for(i=0,j=2;i<info->partitions;i++){ int classv=info->partitionclass[i]; - int cdim=info->class_dim[classv]; - int csubbits=info->class_subs[classv]; + int cdim=info->class[classv].class_dim; + int csubbits=info->class[classv].class_subs; int csub=1<<csubbits; int cval=0; /* decode the partition's first stage cascade value */ if(csubbits){ - cval=vorbis_book_decode(books+info->class_book[classv],&vb->opb); + cval=vorbis_book_decode(books+info->class[classv].class_book,&vd->opb); if(cval==-1)goto eop; } for(k=0;k<cdim;k++){ - int book=info->class_subbook[classv][cval&(csub-1)]; + int book=info->class[classv].class_subbook[cval&(csub-1)]; cval>>=csubbits; - if(book>=0){ - if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) + if(book!=0xff){ + if((fit_value[j+k]=vorbis_book_decode(books+book,&vd->opb))==-1) goto eop; }else{ fit_value[j+k]=0; @@ -369,13 +275,13 @@ static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ } /* unwrap positive values and reconsitute via linear interpolation */ - for(i=2;i<look->posts;i++){ - int predicted=render_point(info->postlist[look->loneighbor[i-2]], - info->postlist[look->hineighbor[i-2]], - fit_value[look->loneighbor[i-2]], - fit_value[look->hineighbor[i-2]], + for(i=2;i<info->posts;i++){ + int predicted=render_point(info->postlist[info->loneighbor[i-2]], + info->postlist[info->hineighbor[i-2]], + fit_value[info->loneighbor[i-2]], + fit_value[info->hineighbor[i-2]], info->postlist[i]); - int hiroom=look->quant_q-predicted; + int hiroom=quant_q-predicted; int loroom=predicted; int room=(hiroom<loroom?hiroom:loroom)<<1; int val=fit_value[i]; @@ -395,9 +301,9 @@ static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ } } - fit_value[i]=(val+predicted)&0x7fff;; - fit_value[look->loneighbor[i-2]]&=0x7fff; - fit_value[look->hineighbor[i-2]]&=0x7fff; + fit_value[i]=val+predicted; + fit_value[info->loneighbor[i-2]]&=0x7fff; + fit_value[info->hineighbor[i-2]]&=0x7fff; }else{ fit_value[i]=predicted|0x8000; @@ -411,34 +317,27 @@ static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ return(NULL); } -static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo, - ogg_int32_t *out){ - vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; - vorbis_info_floor1 *info=look->vi; +int floor1_inverse2(vorbis_dsp_state *vd,vorbis_info_floor *in, + tremor_ogg_int32_t *fit_value,tremor_ogg_int32_t *out){ + vorbis_info_floor1 *info=(vorbis_info_floor1 *)in; - codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; - int n=ci->blocksizes[vb->W]/2; + codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; + int n=ci->blocksizes[vd->W]/2; int j; - if(memo){ + if(fit_value){ /* render the lines */ - int *fit_value=(int *)memo; int hx=0; int lx=0; int ly=fit_value[0]*info->mult; - /* guard lookup against out-of-range values */ - ly=(ly<0?0:ly>255?255:ly); - - for(j=1;j<look->posts;j++){ - int current=look->forward_index[j]; + for(j=1;j<info->posts;j++){ + int current=info->forward_index[j]; int hy=fit_value[current]&0x7fff; if(hy==fit_value[current]){ - hx=info->postlist[current]; hy*=info->mult; - /* guard lookup against out-of-range values */ - hy=(hy<0?0:hy>255?255:hy); - + hx=info->postlist[current]; + render_line(n,lx,hx,ly,hy,out); lx=hx; @@ -451,10 +350,3 @@ static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo, memset(out,0,sizeof(*out)*n); return(0); } - -/* export hooks */ -vorbis_func_floor floor1_exportbundle={ - &floor1_unpack,&floor1_look,&floor1_free_info, - &floor1_free_look,&floor1_inverse1,&floor1_inverse2 -}; - diff --git a/lib/tremor/floor_lookup.c b/lib/tremor/floor_lookup.c new file mode 100644 index 00000000..a7140a14 --- /dev/null +++ b/lib/tremor/floor_lookup.c @@ -0,0 +1,92 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: floor dB lookup + + ********************************************************************/ + +#include "os.h" + +#ifdef _LOW_ACCURACY_ +# define XdB(n) ((((n)>>8)+1)>>1) +#else +# define XdB(n) (n) +#endif + +const tremor_ogg_int32_t FLOOR_fromdB_LOOKUP[256]={ + XdB(0x000000e5), XdB(0x000000f4), XdB(0x00000103), XdB(0x00000114), + XdB(0x00000126), XdB(0x00000139), XdB(0x0000014e), XdB(0x00000163), + XdB(0x0000017a), XdB(0x00000193), XdB(0x000001ad), XdB(0x000001c9), + XdB(0x000001e7), XdB(0x00000206), XdB(0x00000228), XdB(0x0000024c), + XdB(0x00000272), XdB(0x0000029b), XdB(0x000002c6), XdB(0x000002f4), + XdB(0x00000326), XdB(0x0000035a), XdB(0x00000392), XdB(0x000003cd), + XdB(0x0000040c), XdB(0x00000450), XdB(0x00000497), XdB(0x000004e4), + XdB(0x00000535), XdB(0x0000058c), XdB(0x000005e8), XdB(0x0000064a), + XdB(0x000006b3), XdB(0x00000722), XdB(0x00000799), XdB(0x00000818), + XdB(0x0000089e), XdB(0x0000092e), XdB(0x000009c6), XdB(0x00000a69), + XdB(0x00000b16), XdB(0x00000bcf), XdB(0x00000c93), XdB(0x00000d64), + XdB(0x00000e43), XdB(0x00000f30), XdB(0x0000102d), XdB(0x0000113a), + XdB(0x00001258), XdB(0x0000138a), XdB(0x000014cf), XdB(0x00001629), + XdB(0x0000179a), XdB(0x00001922), XdB(0x00001ac4), XdB(0x00001c82), + XdB(0x00001e5c), XdB(0x00002055), XdB(0x0000226f), XdB(0x000024ac), + XdB(0x0000270e), XdB(0x00002997), XdB(0x00002c4b), XdB(0x00002f2c), + XdB(0x0000323d), XdB(0x00003581), XdB(0x000038fb), XdB(0x00003caf), + XdB(0x000040a0), XdB(0x000044d3), XdB(0x0000494c), XdB(0x00004e10), + XdB(0x00005323), XdB(0x0000588a), XdB(0x00005e4b), XdB(0x0000646b), + XdB(0x00006af2), XdB(0x000071e5), XdB(0x0000794c), XdB(0x0000812e), + XdB(0x00008993), XdB(0x00009283), XdB(0x00009c09), XdB(0x0000a62d), + XdB(0x0000b0f9), XdB(0x0000bc79), XdB(0x0000c8b9), XdB(0x0000d5c4), + XdB(0x0000e3a9), XdB(0x0000f274), XdB(0x00010235), XdB(0x000112fd), + XdB(0x000124dc), XdB(0x000137e4), XdB(0x00014c29), XdB(0x000161bf), + XdB(0x000178bc), XdB(0x00019137), XdB(0x0001ab4a), XdB(0x0001c70e), + XdB(0x0001e4a1), XdB(0x0002041f), XdB(0x000225aa), XdB(0x00024962), + XdB(0x00026f6d), XdB(0x000297f0), XdB(0x0002c316), XdB(0x0002f109), + XdB(0x000321f9), XdB(0x00035616), XdB(0x00038d97), XdB(0x0003c8b4), + XdB(0x000407a7), XdB(0x00044ab2), XdB(0x00049218), XdB(0x0004de23), + XdB(0x00052f1e), XdB(0x0005855c), XdB(0x0005e135), XdB(0x00064306), + XdB(0x0006ab33), XdB(0x00071a24), XdB(0x0007904b), XdB(0x00080e20), + XdB(0x00089422), XdB(0x000922da), XdB(0x0009bad8), XdB(0x000a5cb6), + XdB(0x000b091a), XdB(0x000bc0b1), XdB(0x000c8436), XdB(0x000d5471), + XdB(0x000e3233), XdB(0x000f1e5f), XdB(0x001019e4), XdB(0x001125c1), + XdB(0x00124306), XdB(0x001372d5), XdB(0x0014b663), XdB(0x00160ef7), + XdB(0x00177df0), XdB(0x001904c1), XdB(0x001aa4f9), XdB(0x001c603d), + XdB(0x001e384f), XdB(0x00202f0f), XdB(0x0022467a), XdB(0x002480b1), + XdB(0x0026dff7), XdB(0x002966b3), XdB(0x002c1776), XdB(0x002ef4fc), + XdB(0x0032022d), XdB(0x00354222), XdB(0x0038b828), XdB(0x003c67c2), + XdB(0x004054ae), XdB(0x004482e8), XdB(0x0048f6af), XdB(0x004db488), + XdB(0x0052c142), XdB(0x005821ff), XdB(0x005ddc33), XdB(0x0063f5b0), + XdB(0x006a74a7), XdB(0x00715faf), XdB(0x0078bdce), XdB(0x0080967f), + XdB(0x0088f1ba), XdB(0x0091d7f9), XdB(0x009b5247), XdB(0x00a56a41), + XdB(0x00b02a27), XdB(0x00bb9ce2), XdB(0x00c7ce12), XdB(0x00d4ca17), + XdB(0x00e29e20), XdB(0x00f15835), XdB(0x0101074b), XdB(0x0111bb4e), + XdB(0x01238531), XdB(0x01367704), XdB(0x014aa402), XdB(0x016020a7), + XdB(0x017702c3), XdB(0x018f6190), XdB(0x01a955cb), XdB(0x01c4f9cf), + XdB(0x01e269a8), XdB(0x0201c33b), XdB(0x0223265a), XdB(0x0246b4ea), + XdB(0x026c9302), XdB(0x0294e716), XdB(0x02bfda13), XdB(0x02ed9793), + XdB(0x031e4e09), XdB(0x03522ee4), XdB(0x03896ed0), XdB(0x03c445e2), + XdB(0x0402efd6), XdB(0x0445ac4b), XdB(0x048cbefc), XdB(0x04d87013), + XdB(0x05290c67), XdB(0x057ee5ca), XdB(0x05da5364), XdB(0x063bb204), + XdB(0x06a36485), XdB(0x0711d42b), XdB(0x0787710e), XdB(0x0804b299), + XdB(0x088a17ef), XdB(0x0918287e), XdB(0x09af747c), XdB(0x0a50957e), + XdB(0x0afc2f19), XdB(0x0bb2ef7f), XdB(0x0c759034), XdB(0x0d44d6ca), + XdB(0x0e2195bc), XdB(0x0f0cad0d), XdB(0x10070b62), XdB(0x1111aeea), + XdB(0x122da66c), XdB(0x135c120f), XdB(0x149e24d9), XdB(0x15f525b1), + XdB(0x176270e3), XdB(0x18e7794b), XdB(0x1a85c9ae), XdB(0x1c3f06d1), + XdB(0x1e14f07d), XdB(0x200963d7), XdB(0x221e5ccd), XdB(0x2455f870), + XdB(0x26b2770b), XdB(0x29363e2b), XdB(0x2be3db5c), XdB(0x2ebe06b6), + XdB(0x31c7a55b), XdB(0x3503ccd4), XdB(0x3875c5aa), XdB(0x3c210f44), + XdB(0x4009632b), XdB(0x4432b8cf), XdB(0x48a149bc), XdB(0x4d59959e), + XdB(0x52606733), XdB(0x57bad899), XdB(0x5d6e593a), XdB(0x6380b298), + XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff), +}; + diff --git a/lib/tremor/framing.c b/lib/tremor/framing.c new file mode 100644 index 00000000..e2321ae4 --- /dev/null +++ b/lib/tremor/framing.c @@ -0,0 +1,1117 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: decode Ogg streams back into raw packets + + note: The CRC code is directly derived from public domain code by + Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html + for details. + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include "tremor_ogg.h" +#include "misc.h" + + +/* A complete description of Ogg framing exists in docs/framing.html */ + +/* basic, centralized Ogg memory management based on linked lists of + references to refcounted memory buffers. References and buffers + are both recycled. Buffers are passed around and consumed in + reference form. */ + +static tremor_ogg_buffer_state *tremor_ogg_buffer_create(void){ + tremor_ogg_buffer_state *bs=_tremor_ogg_calloc(1,sizeof(*bs)); + return bs; +} + +/* destruction is 'lazy'; there may be memory references outstanding, + and yanking the buffer state out from underneath would be + antisocial. Dealloc what is currently unused and have + _release_one watch for the stragglers to come in. When they do, + finish destruction. */ + +/* call the helper while holding lock */ +static void _tremor_ogg_buffer_destroy(tremor_ogg_buffer_state *bs){ + tremor_ogg_buffer *bt; + tremor_ogg_reference *rt; + + if(bs->shutdown){ + + bt=bs->unused_buffers; + rt=bs->unused_references; + + while(bt){ + tremor_ogg_buffer *b=bt; + bt=b->ptr.next; + if(b->data)_tremor_ogg_free(b->data); + _tremor_ogg_free(b); + } + bs->unused_buffers=0; + while(rt){ + tremor_ogg_reference *r=rt; + rt=r->next; + _tremor_ogg_free(r); + } + bs->unused_references=0; + + if(!bs->outstanding) + _tremor_ogg_free(bs); + + } +} + +static void tremor_ogg_buffer_destroy(tremor_ogg_buffer_state *bs){ + bs->shutdown=1; + _tremor_ogg_buffer_destroy(bs); +} + +static tremor_ogg_buffer *_fetch_buffer(tremor_ogg_buffer_state *bs,long bytes){ + tremor_ogg_buffer *ob; + bs->outstanding++; + + /* do we have an unused buffer sitting in the pool? */ + if(bs->unused_buffers){ + ob=bs->unused_buffers; + bs->unused_buffers=ob->ptr.next; + + /* if the unused buffer is too small, grow it */ + if(ob->size<bytes){ + ob->data=_tremor_ogg_realloc(ob->data,bytes); + ob->size=bytes; + } + }else{ + /* allocate a new buffer */ + ob=_tremor_ogg_malloc(sizeof(*ob)); + ob->data=_tremor_ogg_malloc(bytes<16?16:bytes); + ob->size=bytes; + } + + ob->refcount=1; + ob->ptr.owner=bs; + return ob; +} + +static tremor_ogg_reference *_fetch_ref(tremor_ogg_buffer_state *bs){ + tremor_ogg_reference *or; + bs->outstanding++; + + /* do we have an unused reference sitting in the pool? */ + if(bs->unused_references){ + or=bs->unused_references; + bs->unused_references=or->next; + }else{ + /* allocate a new reference */ + or=_tremor_ogg_malloc(sizeof(*or)); + } + + or->begin=0; + or->length=0; + or->next=0; + return or; +} + +/* fetch a reference pointing to a fresh, initially continguous buffer + of at least [bytes] length */ +static tremor_ogg_reference *tremor_ogg_buffer_alloc(tremor_ogg_buffer_state *bs,long bytes){ + tremor_ogg_buffer *ob=_fetch_buffer(bs,bytes); + tremor_ogg_reference *or=_fetch_ref(bs); + or->buffer=ob; + return or; +} + +/* enlarge the data buffer in the current link */ +static void tremor_ogg_buffer_realloc(tremor_ogg_reference *or,long bytes){ + tremor_ogg_buffer *ob=or->buffer; + + /* if the unused buffer is too small, grow it */ + if(ob->size<bytes){ + ob->data=_tremor_ogg_realloc(ob->data,bytes); + ob->size=bytes; + } +} + +static void _tremor_ogg_buffer_mark_one(tremor_ogg_reference *or){ + or->buffer->refcount++; +} + +/* increase the refcount of the buffers to which the reference points */ +static void tremor_ogg_buffer_mark(tremor_ogg_reference *or){ + while(or){ + _tremor_ogg_buffer_mark_one(or); + or=or->next; + } +} + +/* duplicate a reference (pointing to the same actual buffer memory) + and increment buffer refcount. If the desired segment is zero + length, a zero length ref is returned. */ +static tremor_ogg_reference *tremor_ogg_buffer_sub(tremor_ogg_reference *or,long length){ + tremor_ogg_reference *ret=0,*head=0; + + /* duplicate the reference chain; increment refcounts */ + while(or && length){ + tremor_ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner); + if(head) + head->next=temp; + else + ret=temp; + head=temp; + head->buffer=or->buffer; + head->begin=or->begin; + head->length=length; + if(head->length>or->length) + head->length=or->length; + + length-=head->length; + or=or->next; + } + + tremor_ogg_buffer_mark(ret); + return ret; +} + +tremor_ogg_reference *tremor_ogg_buffer_dup(tremor_ogg_reference *or){ + tremor_ogg_reference *ret=0,*head=0; + /* duplicate the reference chain; increment refcounts */ + while(or){ + tremor_ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner); + if(head) + head->next=temp; + else + ret=temp; + head=temp; + head->buffer=or->buffer; + head->begin=or->begin; + head->length=or->length; + or=or->next; + } + + tremor_ogg_buffer_mark(ret); + return ret; +} + +/* split a reference into two references; 'return' is a reference to + the buffer preceeding pos and 'head'/'tail' are the buffer past the + split. If pos is at or past the end of the passed in segment, + 'head/tail' are NULL */ +static tremor_ogg_reference *tremor_ogg_buffer_split(tremor_ogg_reference **tail, + tremor_ogg_reference **head,long pos){ + + /* walk past any preceeding fragments to one of: + a) the exact boundary that seps two fragments + b) the fragment that needs split somewhere in the middle */ + tremor_ogg_reference *ret=*tail; + tremor_ogg_reference *or=*tail; + + while(or && pos>or->length){ + pos-=or->length; + or=or->next; + } + + if(!or || pos==0){ + + return 0; + + }else{ + + if(pos>=or->length){ + /* exact split, or off the end? */ + if(or->next){ + + /* a split */ + *tail=or->next; + or->next=0; + + }else{ + + /* off or at the end */ + *tail=*head=0; + + } + }else{ + + /* split within a fragment */ + long lengthA=pos; + long beginB=or->begin+pos; + long lengthB=or->length-pos; + + /* make a new reference to tail the second piece */ + *tail=_fetch_ref(or->buffer->ptr.owner); + + (*tail)->buffer=or->buffer; + (*tail)->begin=beginB; + (*tail)->length=lengthB; + (*tail)->next=or->next; + _tremor_ogg_buffer_mark_one(*tail); + if(head && or==*head)*head=*tail; + + /* update the first piece */ + or->next=0; + or->length=lengthA; + + } + } + return ret; +} + +static void tremor_ogg_buffer_release_one(tremor_ogg_reference *or){ + tremor_ogg_buffer *ob=or->buffer; + tremor_ogg_buffer_state *bs=ob->ptr.owner; + + ob->refcount--; + if(ob->refcount==0){ + bs->outstanding--; /* for the returned buffer */ + ob->ptr.next=bs->unused_buffers; + bs->unused_buffers=ob; + } + + bs->outstanding--; /* for the returned reference */ + or->next=bs->unused_references; + bs->unused_references=or; + + _tremor_ogg_buffer_destroy(bs); /* lazy cleanup (if needed) */ + +} + +/* release the references, decrease the refcounts of buffers to which + they point, release any buffers with a refcount that drops to zero */ +static void tremor_ogg_buffer_release(tremor_ogg_reference *or){ + while(or){ + tremor_ogg_reference *next=or->next; + tremor_ogg_buffer_release_one(or); + or=next; + } +} + +static tremor_ogg_reference *tremor_ogg_buffer_pretruncate(tremor_ogg_reference *or,long pos){ + /* release preceeding fragments we don't want */ + while(or && pos>=or->length){ + tremor_ogg_reference *next=or->next; + pos-=or->length; + tremor_ogg_buffer_release_one(or); + or=next; + } + if (or) { + or->begin+=pos; + or->length-=pos; + } + return or; +} + +static tremor_ogg_reference *tremor_ogg_buffer_walk(tremor_ogg_reference *or){ + if(!or)return NULL; + while(or->next){ + or=or->next; + } + return(or); +} + +/* *head is appended to the front end (head) of *tail; both continue to + be valid pointers, with *tail at the tail and *head at the head */ +static tremor_ogg_reference *tremor_ogg_buffer_cat(tremor_ogg_reference *tail, tremor_ogg_reference *head){ + if(!tail)return head; + + while(tail->next){ + tail=tail->next; + } + tail->next=head; + return tremor_ogg_buffer_walk(head); +} + +static void _positionB(oggbyte_buffer *b,int pos){ + if(pos<b->pos){ + /* start at beginning, scan forward */ + b->ref=b->baseref; + b->pos=0; + b->end=b->pos+b->ref->length; + b->ptr=b->ref->buffer->data+b->ref->begin; + } +} + +static void _positionF(oggbyte_buffer *b,int pos){ + /* scan forward for position */ + while(pos>=b->end){ + /* just seek forward */ + b->pos+=b->ref->length; + b->ref=b->ref->next; + b->end=b->ref->length+b->pos; + b->ptr=b->ref->buffer->data+b->ref->begin; + } +} + +static int oggbyte_init(oggbyte_buffer *b,tremor_ogg_reference *or){ + memset(b,0,sizeof(*b)); + if(or){ + b->ref=b->baseref=or; + b->pos=0; + b->end=b->ref->length; + b->ptr=b->ref->buffer->data+b->ref->begin; + return 0; + }else + return -1; +} + +static void oggbyte_set4(oggbyte_buffer *b,tremor_ogg_uint32_t val,int pos){ + int i; + _positionB(b,pos); + for(i=0;i<4;i++){ + _positionF(b,pos); + b->ptr[pos-b->pos]=val; + val>>=8; + ++pos; + } +} + +static unsigned char oggbyte_read1(oggbyte_buffer *b,int pos){ + _positionB(b,pos); + _positionF(b,pos); + return b->ptr[pos-b->pos]; +} + +static tremor_ogg_uint32_t oggbyte_read4(oggbyte_buffer *b,int pos){ + tremor_ogg_uint32_t ret; + _positionB(b,pos); + _positionF(b,pos); + ret=b->ptr[pos-b->pos]; + _positionF(b,++pos); + ret|=b->ptr[pos-b->pos]<<8; + _positionF(b,++pos); + ret|=b->ptr[pos-b->pos]<<16; + _positionF(b,++pos); + ret|=b->ptr[pos-b->pos]<<24; + return ret; +} + +static tremor_ogg_int64_t oggbyte_read8(oggbyte_buffer *b,int pos){ + tremor_ogg_int64_t ret; + unsigned char t[7]; + int i; + _positionB(b,pos); + for(i=0;i<7;i++){ + _positionF(b,pos); + t[i]=b->ptr[pos++ -b->pos]; + } + + _positionF(b,pos); + ret=b->ptr[pos-b->pos]; + + for(i=6;i>=0;--i) + ret= ret<<8 | t[i]; + + return ret; +} + +/* Now we get to the actual framing code */ + +int tremor_ogg_page_version(tremor_ogg_page *og){ + oggbyte_buffer ob; + if(oggbyte_init(&ob,og->header))return -1; + return oggbyte_read1(&ob,4); +} + +int tremor_ogg_page_continued(tremor_ogg_page *og){ + oggbyte_buffer ob; + if(oggbyte_init(&ob,og->header))return -1; + return oggbyte_read1(&ob,5)&0x01; +} + +int tremor_ogg_page_bos(tremor_ogg_page *og){ + oggbyte_buffer ob; + if(oggbyte_init(&ob,og->header))return -1; + return oggbyte_read1(&ob,5)&0x02; +} + +int tremor_ogg_page_eos(tremor_ogg_page *og){ + oggbyte_buffer ob; + if(oggbyte_init(&ob,og->header))return -1; + return oggbyte_read1(&ob,5)&0x04; +} + +tremor_ogg_int64_t tremor_ogg_page_granulepos(tremor_ogg_page *og){ + oggbyte_buffer ob; + if(oggbyte_init(&ob,og->header))return -1; + return oggbyte_read8(&ob,6); +} + +tremor_ogg_uint32_t tremor_ogg_page_serialno(tremor_ogg_page *og){ + oggbyte_buffer ob; + if(oggbyte_init(&ob,og->header)) return 0xffffffffUL; + return oggbyte_read4(&ob,14); +} + +tremor_ogg_uint32_t tremor_ogg_page_pageno(tremor_ogg_page *og){ + oggbyte_buffer ob; + if(oggbyte_init(&ob,og->header))return 0xffffffffUL; + return oggbyte_read4(&ob,18); +} + +/* returns the number of packets that are completed on this page (if + the leading packet is begun on a previous page, but ends on this + page, it's counted */ + +/* NOTE: +If a page consists of a packet begun on a previous page, and a new +packet begun (but not completed) on this page, the return will be: + tremor_ogg_page_packets(page) ==1, + tremor_ogg_page_continued(page) !=0 + +If a page happens to be a single packet that was begun on a +previous page, and spans to the next page (in the case of a three or +more page packet), the return will be: + tremor_ogg_page_packets(page) ==0, + tremor_ogg_page_continued(page) !=0 +*/ + +int tremor_ogg_page_packets(tremor_ogg_page *og){ + int i; + int n; + int count=0; + oggbyte_buffer ob; + oggbyte_init(&ob,og->header); + + n=oggbyte_read1(&ob,26); + for(i=0;i<n;i++) + if(oggbyte_read1(&ob,27+i)<255)count++; + return(count); +} + +/* Static CRC calculation table. See older code in CVS for dead + run-time initialization code. */ + +static tremor_ogg_uint32_t crc_lookup[256]={ + 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, + 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, + 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61, + 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, + 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9, + 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75, + 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011, + 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd, + 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039, + 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5, + 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81, + 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d, + 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49, + 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95, + 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1, + 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d, + 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae, + 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072, + 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16, + 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca, + 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde, + 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02, + 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066, + 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba, + 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e, + 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692, + 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6, + 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a, + 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e, + 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2, + 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686, + 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a, + 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637, + 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb, + 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f, + 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53, + 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47, + 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b, + 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff, + 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623, + 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7, + 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b, + 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f, + 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3, + 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7, + 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b, + 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f, + 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3, + 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640, + 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c, + 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8, + 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24, + 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30, + 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec, + 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088, + 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654, + 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0, + 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c, + 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18, + 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4, + 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0, + 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c, + 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668, + 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4}; + +tremor_ogg_sync_state *tremor_ogg_sync_create(void){ + tremor_ogg_sync_state *oy=_tremor_ogg_calloc(1,sizeof(*oy)); + memset(oy,0,sizeof(*oy)); + oy->bufferpool=tremor_ogg_buffer_create(); + return oy; +} + +int tremor_ogg_sync_destroy(tremor_ogg_sync_state *oy){ + if(oy){ + tremor_ogg_sync_reset(oy); + tremor_ogg_buffer_destroy(oy->bufferpool); + memset(oy,0,sizeof(*oy)); + _tremor_ogg_free(oy); + } + return OGG_SUCCESS; +} + +unsigned char *tremor_ogg_sync_bufferin(tremor_ogg_sync_state *oy, long bytes){ + + /* [allocate and] expose a buffer for data submission. + + If there is no head fragment + allocate one and expose it + else + if the current head fragment has sufficient unused space + expose it + else + if the current head fragment is unused + resize and expose it + else + allocate new fragment and expose it + */ + + /* base case; fifo uninitialized */ + if(!oy->fifo_head){ + oy->fifo_head=oy->fifo_tail=tremor_ogg_buffer_alloc(oy->bufferpool,bytes); + return oy->fifo_head->buffer->data; + } + + /* space left in current fragment case */ + if(oy->fifo_head->buffer->size- + oy->fifo_head->length- + oy->fifo_head->begin >= bytes) + return oy->fifo_head->buffer->data+ + oy->fifo_head->length+oy->fifo_head->begin; + + /* current fragment is unused, but too small */ + if(!oy->fifo_head->length){ + tremor_ogg_buffer_realloc(oy->fifo_head,bytes); + return oy->fifo_head->buffer->data+oy->fifo_head->begin; + } + + /* current fragment used/full; get new fragment */ + { + tremor_ogg_reference *new=tremor_ogg_buffer_alloc(oy->bufferpool,bytes); + oy->fifo_head->next=new; + oy->fifo_head=new; + } + return oy->fifo_head->buffer->data; +} + +int tremor_ogg_sync_wrote(tremor_ogg_sync_state *oy, long bytes){ + if(!oy->fifo_head)return OGG_EINVAL; + if(oy->fifo_head->buffer->size-oy->fifo_head->length-oy->fifo_head->begin < + bytes)return OGG_EINVAL; + oy->fifo_head->length+=bytes; + oy->fifo_fill+=bytes; + return OGG_SUCCESS; +} + +static tremor_ogg_uint32_t _checksum(tremor_ogg_reference *or, int bytes){ + tremor_ogg_uint32_t crc_reg=0; + int j,post; + + while(or){ + unsigned char *data=or->buffer->data+or->begin; + post=(bytes<or->length?bytes:or->length); + for(j=0;j<post;++j) + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^data[j]]; + bytes-=j; + or=or->next; + } + + return crc_reg; +} + + +/* sync the stream. This is meant to be useful for finding page + boundaries. + + return values for this: + -n) skipped n bytes + 0) page not ready; more data (no bytes skipped) + n) page synced at current location; page length n bytes + +*/ + +long tremor_ogg_sync_pageseek(tremor_ogg_sync_state *oy,tremor_ogg_page *og){ + oggbyte_buffer page; + long bytes,ret=0; + + tremor_ogg_page_release(og); + + bytes=oy->fifo_fill; + oggbyte_init(&page,oy->fifo_tail); + + if(oy->headerbytes==0){ + if(bytes<27)goto sync_out; /* not enough for even a minimal header */ + + /* verify capture pattern */ + if(oggbyte_read1(&page,0)!=(int)'O' || + oggbyte_read1(&page,1)!=(int)'g' || + oggbyte_read1(&page,2)!=(int)'g' || + oggbyte_read1(&page,3)!=(int)'S' ) goto sync_fail; + + oy->headerbytes=oggbyte_read1(&page,26)+27; + } + if(bytes<oy->headerbytes)goto sync_out; /* not enough for header + + seg table */ + if(oy->bodybytes==0){ + int i; + /* count up body length in the segment table */ + for(i=0;i<oy->headerbytes-27;i++) + oy->bodybytes+=oggbyte_read1(&page,27+i); + } + + if(oy->bodybytes+oy->headerbytes>bytes)goto sync_out; + + /* we have what appears to be a complete page; last test: verify + checksum */ + { + tremor_ogg_uint32_t chksum=oggbyte_read4(&page,22); + oggbyte_set4(&page,0,22); + + /* Compare checksums; memory continues to be common access */ + if(chksum!=_checksum(oy->fifo_tail,oy->bodybytes+oy->headerbytes)){ + + /* D'oh. Mismatch! Corrupt page (or miscapture and not a page + at all). replace the computed checksum with the one actually + read in; remember all the memory is common access */ + + oggbyte_set4(&page,chksum,22); + goto sync_fail; + } + oggbyte_set4(&page,chksum,22); + } + + /* We have a page. Set up page return. */ + if(og){ + /* set up page output */ + og->header=tremor_ogg_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->headerbytes); + og->header_len=oy->headerbytes; + og->body=tremor_ogg_buffer_split(&oy->fifo_tail,&oy->fifo_head,oy->bodybytes); + og->body_len=oy->bodybytes; + }else{ + /* simply advance */ + oy->fifo_tail= + tremor_ogg_buffer_pretruncate(oy->fifo_tail,oy->headerbytes+oy->bodybytes); + if(!oy->fifo_tail)oy->fifo_head=0; + } + + ret=oy->headerbytes+oy->bodybytes; + oy->unsynced=0; + oy->headerbytes=0; + oy->bodybytes=0; + oy->fifo_fill-=ret; + + return ret; + + sync_fail: + + oy->headerbytes=0; + oy->bodybytes=0; + oy->fifo_tail=tremor_ogg_buffer_pretruncate(oy->fifo_tail,1); + ret--; + + /* search forward through fragments for possible capture */ + while(oy->fifo_tail){ + /* invariant: fifo_cursor points to a position in fifo_tail */ + unsigned char *now=oy->fifo_tail->buffer->data+oy->fifo_tail->begin; + unsigned char *next=memchr(now, 'O', oy->fifo_tail->length); + + if(next){ + /* possible capture in this segment */ + long bytes=next-now; + oy->fifo_tail=tremor_ogg_buffer_pretruncate(oy->fifo_tail,bytes); + ret-=bytes; + break; + }else{ + /* no capture. advance to next segment */ + long bytes=oy->fifo_tail->length; + ret-=bytes; + oy->fifo_tail=tremor_ogg_buffer_pretruncate(oy->fifo_tail,bytes); + } + } + if(!oy->fifo_tail)oy->fifo_head=0; + oy->fifo_fill+=ret; + + sync_out: + return ret; +} + +/* sync the stream and get a page. Keep trying until we find a page. + Supress 'sync errors' after reporting the first. + + return values: + OGG_HOLE) recapture (hole in data) + 0) need more data + 1) page returned + + Returns pointers into buffered data; invalidated by next call to + _stream, _clear, _init, or _buffer */ + +int tremor_ogg_sync_pageout(tremor_ogg_sync_state *oy, tremor_ogg_page *og){ + + /* all we need to do is verify a page at the head of the stream + buffer. If it doesn't verify, we look for the next potential + frame */ + + while(1){ + long ret=tremor_ogg_sync_pageseek(oy,og); + if(ret>0){ + /* have a page */ + return 1; + } + if(ret==0){ + /* need more data */ + return 0; + } + + /* head did not start a synced page... skipped some bytes */ + if(!oy->unsynced){ + oy->unsynced=1; + return OGG_HOLE; + } + + /* loop. keep looking */ + + } +} + +/* clear things to an initial state. Good to call, eg, before seeking */ +int tremor_ogg_sync_reset(tremor_ogg_sync_state *oy){ + + tremor_ogg_buffer_release(oy->fifo_tail); + oy->fifo_tail=0; + oy->fifo_head=0; + oy->fifo_fill=0; + + oy->unsynced=0; + oy->headerbytes=0; + oy->bodybytes=0; + return OGG_SUCCESS; +} + +tremor_ogg_stream_state *tremor_ogg_stream_create(int serialno){ + tremor_ogg_stream_state *os=_tremor_ogg_calloc(1,sizeof(*os)); + os->serialno=serialno; + os->pageno=-1; + return os; +} + +int tremor_ogg_stream_destroy(tremor_ogg_stream_state *os){ + if(os){ + tremor_ogg_buffer_release(os->header_tail); + tremor_ogg_buffer_release(os->body_tail); + memset(os,0,sizeof(*os)); + _tremor_ogg_free(os); + } + return OGG_SUCCESS; +} + + +#define FINFLAG 0x80000000UL +#define FINMASK 0x7fffffffUL + +static void _next_lace(oggbyte_buffer *ob,tremor_ogg_stream_state *os){ + /* search ahead one lace */ + os->body_fill_next=0; + while(os->laceptr<os->lacing_fill){ + int val=oggbyte_read1(ob,27+os->laceptr++); + os->body_fill_next+=val; + if(val<255){ + os->body_fill_next|=FINFLAG; + os->clearflag=1; + break; + } + } +} + +static void _span_queued_page(tremor_ogg_stream_state *os){ + while( !(os->body_fill&FINFLAG) ){ + + if(!os->header_tail)break; + + /* first flush out preceeding page header (if any). Body is + flushed as it's consumed, so that's not done here. */ + + if(os->lacing_fill>=0) + os->header_tail=tremor_ogg_buffer_pretruncate(os->header_tail, + os->lacing_fill+27); + os->lacing_fill=0; + os->laceptr=0; + os->clearflag=0; + + if(!os->header_tail){ + os->header_head=0; + break; + }else{ + + /* process/prepare next page, if any */ + + long pageno; + oggbyte_buffer ob; + tremor_ogg_page og; /* only for parsing header values */ + og.header=os->header_tail; /* only for parsing header values */ + pageno=tremor_ogg_page_pageno(&og); + + oggbyte_init(&ob,os->header_tail); + os->lacing_fill=oggbyte_read1(&ob,26); + + /* are we in sequence? */ + if(pageno!=os->pageno){ + if(os->pageno==-1) /* indicates seek or reset */ + os->holeflag=1; /* set for internal use */ + else + os->holeflag=2; /* set for external reporting */ + + os->body_tail=tremor_ogg_buffer_pretruncate(os->body_tail, + os->body_fill); + if(os->body_tail==0)os->body_head=0; + os->body_fill=0; + + } + + if(tremor_ogg_page_continued(&og)){ + if(os->body_fill==0){ + /* continued packet, but no preceeding data to continue */ + /* dump the first partial packet on the page */ + _next_lace(&ob,os); + os->body_tail= + tremor_ogg_buffer_pretruncate(os->body_tail,os->body_fill_next&FINMASK); + if(os->body_tail==0)os->body_head=0; + /* set span flag */ + if(!os->spanflag && !os->holeflag)os->spanflag=2; + } + }else{ + if(os->body_fill>0){ + /* preceeding data to continue, but not a continued page */ + /* dump body_fill */ + os->body_tail=tremor_ogg_buffer_pretruncate(os->body_tail, + os->body_fill); + if(os->body_tail==0)os->body_head=0; + os->body_fill=0; + + /* set espan flag */ + if(!os->spanflag && !os->holeflag)os->spanflag=2; + } + } + + if(os->laceptr<os->lacing_fill){ + os->granulepos=tremor_ogg_page_granulepos(&og); + + /* get current packet size & flag */ + _next_lace(&ob,os); + os->body_fill+=os->body_fill_next; /* addition handles the flag fine; + unsigned on purpose */ + /* ...and next packet size & flag */ + _next_lace(&ob,os); + + } + + os->pageno=pageno+1; + os->e_o_s=tremor_ogg_page_eos(&og); + os->b_o_s=tremor_ogg_page_bos(&og); + + } + } +} + +/* add the incoming page to the stream state; we decompose the page + into packet segments here as well. */ + +int tremor_ogg_stream_pagein(tremor_ogg_stream_state *os, tremor_ogg_page *og){ + + int serialno=tremor_ogg_page_serialno(og); + int version=tremor_ogg_page_version(og); + + /* check the serial number */ + if(serialno!=os->serialno){ + tremor_ogg_page_release(og); + return OGG_ESERIAL; + } + if(version>0){ + tremor_ogg_page_release(og); + return OGG_EVERSION; + } + + /* add to fifos */ + if(!os->body_tail){ + os->body_tail=og->body; + os->body_head=tremor_ogg_buffer_walk(og->body); + }else{ + os->body_head=tremor_ogg_buffer_cat(os->body_head,og->body); + } + if(!os->header_tail){ + os->header_tail=og->header; + os->header_head=tremor_ogg_buffer_walk(og->header); + os->lacing_fill=-27; + }else{ + os->header_head=tremor_ogg_buffer_cat(os->header_head,og->header); + } + + memset(og,0,sizeof(*og)); + return OGG_SUCCESS; +} + +int tremor_ogg_stream_reset(tremor_ogg_stream_state *os){ + + tremor_ogg_buffer_release(os->header_tail); + tremor_ogg_buffer_release(os->body_tail); + os->header_tail=os->header_head=0; + os->body_tail=os->body_head=0; + + os->e_o_s=0; + os->b_o_s=0; + os->pageno=-1; + os->packetno=0; + os->granulepos=0; + + os->body_fill=0; + os->lacing_fill=0; + + os->holeflag=0; + os->spanflag=0; + os->clearflag=0; + os->laceptr=0; + os->body_fill_next=0; + + return OGG_SUCCESS; +} + +int tremor_ogg_stream_reset_serialno(tremor_ogg_stream_state *os,int serialno){ + tremor_ogg_stream_reset(os); + os->serialno=serialno; + return OGG_SUCCESS; +} + +static int _packetout(tremor_ogg_stream_state *os,tremor_ogg_packet *op,int adv){ + + tremor_ogg_packet_release(op); + _span_queued_page(os); + + if(os->holeflag){ + int temp=os->holeflag; + if(os->clearflag) + os->holeflag=0; + else + os->holeflag=1; + if(temp==2){ + os->packetno++; + return OGG_HOLE; + } + } + if(os->spanflag){ + int temp=os->spanflag; + if(os->clearflag) + os->spanflag=0; + else + os->spanflag=1; + if(temp==2){ + os->packetno++; + return OGG_SPAN; + } + } + + if(!(os->body_fill&FINFLAG)) return 0; + if(!op && !adv)return 1; /* just using peek as an inexpensive way + to ask if there's a whole packet + waiting */ + if(op){ + op->b_o_s=os->b_o_s; + if(os->e_o_s && os->body_fill_next==0) + op->e_o_s=os->e_o_s; + else + op->e_o_s=0; + if( (os->body_fill&FINFLAG) && !(os->body_fill_next&FINFLAG) ) + op->granulepos=os->granulepos; + else + op->granulepos=-1; + op->packetno=os->packetno; + } + + if(adv){ + oggbyte_buffer ob; + oggbyte_init(&ob,os->header_tail); + + /* split the body contents off */ + if(op){ + op->packet=tremor_ogg_buffer_split(&os->body_tail,&os->body_head, + os->body_fill&FINMASK); + op->bytes=os->body_fill&FINMASK; + }else{ + os->body_tail=tremor_ogg_buffer_pretruncate(os->body_tail, + os->body_fill&FINMASK); + if(os->body_tail==0)os->body_head=0; + } + + /* update lacing pointers */ + os->body_fill=os->body_fill_next; + _next_lace(&ob,os); + }else{ + if(op){ + op->packet=tremor_ogg_buffer_sub(os->body_tail,os->body_fill&FINMASK); + op->bytes=os->body_fill&FINMASK; + } + } + + if(adv){ + os->packetno++; + os->b_o_s=0; + } + + return 1; +} + +int tremor_ogg_stream_packetout(tremor_ogg_stream_state *os,tremor_ogg_packet *op){ + return _packetout(os,op,1); +} + +int tremor_ogg_stream_packetpeek(tremor_ogg_stream_state *os,tremor_ogg_packet *op){ + return _packetout(os,op,0); +} + +int tremor_ogg_packet_release(tremor_ogg_packet *op) { + if(op){ + tremor_ogg_buffer_release(op->packet); + memset(op, 0, sizeof(*op)); + } + return OGG_SUCCESS; +} + +int tremor_ogg_page_release(tremor_ogg_page *og) { + if(og){ + tremor_ogg_buffer_release(og->header); + tremor_ogg_buffer_release(og->body); + memset(og, 0, sizeof(*og)); + } + return OGG_SUCCESS; +} + +void tremor_ogg_page_dup(tremor_ogg_page *dup,tremor_ogg_page *orig){ + dup->header_len=orig->header_len; + dup->body_len=orig->body_len; + dup->header=tremor_ogg_buffer_dup(orig->header); + dup->body=tremor_ogg_buffer_dup(orig->body); +} + diff --git a/lib/tremor/info.c b/lib/tremor/info.c index 24e24ac7..da393f9f 100644 --- a/lib/tremor/info.c +++ b/lib/tremor/info.c @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -21,19 +21,17 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> -#include <limits.h> -#include <ogg/ogg.h> +#include "tremor_ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" #include "codebook.h" -#include "registry.h" -#include "window.h" #include "misc.h" +#include "os.h" /* helpers */ -static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ +static void _v_readstring(tremor_oggpack_buffer *o,char *buf,int bytes){ while(bytes--){ - *buf++=oggpack_read(o,8); + *buf++=tremor_oggpack_read(o,8); } } @@ -92,15 +90,13 @@ int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ void vorbis_comment_clear(vorbis_comment *vc){ if(vc){ long i; - if(vc->user_comments){ - for(i=0;i<vc->comments;i++) - if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); - _ogg_free(vc->user_comments); - } - if(vc->comment_lengths)_ogg_free(vc->comment_lengths); - if(vc->vendor)_ogg_free(vc->vendor); - memset(vc,0,sizeof(*vc)); + for(i=0;i<vc->comments;i++) + if(vc->user_comments[i])_tremor_ogg_free(vc->user_comments[i]); + if(vc->user_comments)_tremor_ogg_free(vc->user_comments); + if(vc->comment_lengths)_tremor_ogg_free(vc->comment_lengths); + if(vc->vendor)_tremor_ogg_free(vc->vendor); } + memset(vc,0,sizeof(*vc)); } /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. @@ -113,7 +109,7 @@ int vorbis_info_blocksize(vorbis_info *vi,int zo){ /* used by synthesis, which has a full, alloced vi */ void vorbis_info_init(vorbis_info *vi){ memset(vi,0,sizeof(*vi)); - vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info)); + vi->codec_setup=(codec_setup_info *)_tremor_ogg_calloc(1,sizeof(codec_setup_info)); } void vorbis_info_clear(vorbis_info *vi){ @@ -122,33 +118,37 @@ void vorbis_info_clear(vorbis_info *vi){ if(ci){ - for(i=0;i<ci->modes;i++) - if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); + if(ci->mode_param)_tremor_ogg_free(ci->mode_param); - for(i=0;i<ci->maps;i++) /* unpack does the range checking */ - if(ci->map_param[i]) - _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); + if(ci->map_param){ + for(i=0;i<ci->maps;i++) /* unpack does the range checking */ + mapping_clear_info(ci->map_param+i); + _tremor_ogg_free(ci->map_param); + } - for(i=0;i<ci->floors;i++) /* unpack does the range checking */ - if(ci->floor_param[i]) - _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); - - for(i=0;i<ci->residues;i++) /* unpack does the range checking */ - if(ci->residue_param[i]) - _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); - - for(i=0;i<ci->books;i++){ - if(ci->book_param[i]){ - /* knows if the book was not alloced */ - vorbis_staticbook_destroy(ci->book_param[i]); - } - if(ci->fullbooks) - vorbis_book_clear(ci->fullbooks+i); + if(ci->floor_param){ + for(i=0;i<ci->floors;i++) /* unpack does the range checking */ + if(ci->floor_type[i]) + floor1_free_info(ci->floor_param[i]); + else + floor0_free_info(ci->floor_param[i]); + _tremor_ogg_free(ci->floor_param); + _tremor_ogg_free(ci->floor_type); + } + + if(ci->residue_param){ + for(i=0;i<ci->residues;i++) /* unpack does the range checking */ + res_clear_info(ci->residue_param+i); + _tremor_ogg_free(ci->residue_param); + } + + if(ci->book_param){ + for(i=0;i<ci->books;i++) + vorbis_book_clear(ci->book_param+i); + _tremor_ogg_free(ci->book_param); } - if(ci->fullbooks) - _ogg_free(ci->fullbooks); - _ogg_free(ci); + _tremor_ogg_free(ci); } memset(vi,0,sizeof(*vi)); @@ -156,30 +156,36 @@ void vorbis_info_clear(vorbis_info *vi){ /* Header packing/unpacking ********************************************/ -static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ +static int _vorbis_unpack_info(vorbis_info *vi,tremor_oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; if(!ci)return(OV_EFAULT); - vi->version=oggpack_read(opb,32); + vi->version=tremor_oggpack_read(opb,32); if(vi->version!=0)return(OV_EVERSION); - vi->channels=oggpack_read(opb,8); - vi->rate=oggpack_read(opb,32); + vi->channels=tremor_oggpack_read(opb,8); + vi->rate=tremor_oggpack_read(opb,32); - vi->bitrate_upper=oggpack_read(opb,32); - vi->bitrate_nominal=oggpack_read(opb,32); - vi->bitrate_lower=oggpack_read(opb,32); + vi->bitrate_upper=tremor_oggpack_read(opb,32); + vi->bitrate_nominal=tremor_oggpack_read(opb,32); + vi->bitrate_lower=tremor_oggpack_read(opb,32); - ci->blocksizes[0]=1<<oggpack_read(opb,4); - ci->blocksizes[1]=1<<oggpack_read(opb,4); + ci->blocksizes[0]=1<<tremor_oggpack_read(opb,4); + ci->blocksizes[1]=1<<tremor_oggpack_read(opb,4); +#ifdef LIMIT_TO_64kHz + if(vi->rate>=64000 || ci->blocksizes[1]>4096)goto err_out; +#else + if(vi->rate<64000 && ci->blocksizes[1]>4096)goto err_out; +#endif + if(vi->rate<1)goto err_out; if(vi->channels<1)goto err_out; if(ci->blocksizes[0]<64)goto err_out; if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; if(ci->blocksizes[1]>8192)goto err_out; - if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ + if(tremor_oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ return(0); err_out: @@ -187,34 +193,25 @@ static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ return(OV_EBADHEADER); } -static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ +static int _vorbis_unpack_comment(vorbis_comment *vc,tremor_oggpack_buffer *opb){ int i; - int vendorlen; - vendorlen=oggpack_read(opb,32); + int vendorlen=tremor_oggpack_read(opb,32); if(vendorlen<0)goto err_out; - if(vendorlen>opb->storage-oggpack_bytes(opb))goto err_out; - vc->vendor=(char *)_ogg_calloc(vendorlen+1,1); - if(vc->vendor==NULL)goto err_out; + vc->vendor=(char *)_tremor_ogg_calloc(vendorlen+1,1); _v_readstring(opb,vc->vendor,vendorlen); - i=oggpack_read(opb,32); - if(i<0||i>=INT_MAX||i>(opb->storage-oggpack_bytes(opb))>>2)goto err_out; - vc->user_comments=(char **)_ogg_calloc(i+1,sizeof(*vc->user_comments)); - vc->comment_lengths=(int *)_ogg_calloc(i+1, sizeof(*vc->comment_lengths)); - if(vc->user_comments==NULL||vc->comment_lengths==NULL)goto err_out; - vc->comments=i; - + vc->comments=tremor_oggpack_read(opb,32); + if(vc->comments<0)goto err_out; + vc->user_comments=(char **)_tremor_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments)); + vc->comment_lengths=(int *)_tremor_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths)); + for(i=0;i<vc->comments;i++){ - int len=oggpack_read(opb,32); - if(len<0||len>opb->storage-oggpack_bytes(opb))goto err_out; - vc->comment_lengths[i]=len; - vc->user_comments[i]=(char *)_ogg_calloc(len+1,1); - if(vc->user_comments[i]==NULL){ - vc->comments=i; - goto err_out; - } + int len=tremor_oggpack_read(opb,32); + if(len<0)goto err_out; + vc->comment_lengths[i]=len; + vc->user_comments[i]=(char *)_tremor_ogg_calloc(len+1,1); _v_readstring(opb,vc->user_comments[i],len); - } - if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ + } + if(tremor_oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ return(0); err_out: @@ -224,76 +221,63 @@ static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ /* all of the real encoding details are here. The modes, books, everything */ -static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ +static int _vorbis_unpack_books(vorbis_info *vi,tremor_oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; + if(!ci)return(OV_EFAULT); /* codebooks */ - ci->books=oggpack_read(opb,8)+1; - if(ci->books<=0)goto err_out; - for(i=0;i<ci->books;i++){ - ci->book_param[i]=vorbis_staticbook_unpack(opb); - if(!ci->book_param[i])goto err_out; - } + ci->books=tremor_oggpack_read(opb,8)+1; + ci->book_param=(codebook *)_tremor_ogg_calloc(ci->books,sizeof(*ci->book_param)); + for(i=0;i<ci->books;i++) + if(vorbis_book_unpack(opb,ci->book_param+i))goto err_out; - /* time backend settings */ - ci->times=oggpack_read(opb,6)+1; - if(ci->times<=0)goto err_out; - for(i=0;i<ci->times;i++){ - ci->time_type[i]=oggpack_read(opb,16); - if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out; - /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb); - Vorbis I has no time backend */ - /*if(!ci->time_param[i])goto err_out;*/ - } + /* time backend settings, not actually used */ + i=tremor_oggpack_read(opb,6); + for(;i>=0;i--) + if(tremor_oggpack_read(opb,16)!=0)goto err_out; /* floor backend settings */ - ci->floors=oggpack_read(opb,6)+1; - if(ci->floors<=0)goto err_out; + ci->floors=tremor_oggpack_read(opb,6)+1; + ci->floor_param=_tremor_ogg_malloc(sizeof(*ci->floor_param)*ci->floors); + ci->floor_type=_tremor_ogg_malloc(sizeof(*ci->floor_type)*ci->floors); for(i=0;i<ci->floors;i++){ - ci->floor_type[i]=oggpack_read(opb,16); + ci->floor_type[i]=tremor_oggpack_read(opb,16); if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; - ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); + if(ci->floor_type[i]) + ci->floor_param[i]=floor1_info_unpack(vi,opb); + else + ci->floor_param[i]=floor0_info_unpack(vi,opb); if(!ci->floor_param[i])goto err_out; } /* residue backend settings */ - ci->residues=oggpack_read(opb,6)+1; - if(ci->residues<=0)goto err_out; - for(i=0;i<ci->residues;i++){ - ci->residue_type[i]=oggpack_read(opb,16); - if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; - ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); - if(!ci->residue_param[i])goto err_out; - } + ci->residues=tremor_oggpack_read(opb,6)+1; + ci->residue_param=_tremor_ogg_malloc(sizeof(*ci->residue_param)*ci->residues); + for(i=0;i<ci->residues;i++) + if(res_unpack(ci->residue_param+i,vi,opb))goto err_out; /* map backend settings */ - ci->maps=oggpack_read(opb,6)+1; - if(ci->maps<=0)goto err_out; + ci->maps=tremor_oggpack_read(opb,6)+1; + ci->map_param=_tremor_ogg_malloc(sizeof(*ci->map_param)*ci->maps); for(i=0;i<ci->maps;i++){ - ci->map_type[i]=oggpack_read(opb,16); - if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; - ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); - if(!ci->map_param[i])goto err_out; + if(tremor_oggpack_read(opb,16)!=0)goto err_out; + if(mapping_info_unpack(ci->map_param+i,vi,opb))goto err_out; } /* mode settings */ - ci->modes=oggpack_read(opb,6)+1; - if(ci->modes<=0)goto err_out; + ci->modes=tremor_oggpack_read(opb,6)+1; + ci->mode_param= + (vorbis_info_mode *)_tremor_ogg_malloc(ci->modes*sizeof(*ci->mode_param)); for(i=0;i<ci->modes;i++){ - ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i])); - ci->mode_param[i]->blockflag=oggpack_read(opb,1); - ci->mode_param[i]->windowtype=oggpack_read(opb,16); - ci->mode_param[i]->transformtype=oggpack_read(opb,16); - ci->mode_param[i]->mapping=oggpack_read(opb,8); - - if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; - if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; - if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; - if(ci->mode_param[i]->mapping<0)goto err_out; + ci->mode_param[i].blockflag=tremor_oggpack_read(opb,1); + if(tremor_oggpack_read(opb,16))goto err_out; + if(tremor_oggpack_read(opb,16))goto err_out; + ci->mode_param[i].mapping=tremor_oggpack_read(opb,8); + if(ci->mode_param[i].mapping>=ci->maps)goto err_out; } - if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ + if(tremor_oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); err_out: @@ -301,47 +285,22 @@ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ return(OV_EBADHEADER); } -/* Is this packet a vorbis ID header? */ -int vorbis_synthesis_idheader(ogg_packet *op){ - oggpack_buffer opb; - char buffer[6]; - - if(op){ - oggpack_readinit(&opb,op->packet,op->bytes); - - if(!op->b_o_s) - return(0); /* Not the initial packet */ - - if(oggpack_read(&opb,8) != 1) - return 0; /* not an ID header */ - - memset(buffer,0,6); - _v_readstring(&opb,buffer,6); - if(memcmp(buffer,"vorbis",6)) - return 0; /* not vorbis */ - - return 1; - } - - return 0; -} - /* The Vorbis header is in three packets; the initial small packet in the first page that identifies basic parameters, a second packet with bitstream comments and a third packet that holds the codebook. */ -int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ - oggpack_buffer opb; +int vorbis_dsp_headerin(vorbis_info *vi,vorbis_comment *vc,tremor_ogg_packet *op){ + tremor_oggpack_buffer opb; if(op){ - oggpack_readinit(&opb,op->packet,op->bytes); + tremor_oggpack_readinit(&opb,op->packet); /* Which of the three types of header is this? */ /* Also verify header-ness, vorbis */ { char buffer[6]; - int packtype=oggpack_read(&opb,8); + int packtype=tremor_oggpack_read(&opb,8); memset(buffer,0,6); _v_readstring(&opb,buffer,6); if(memcmp(buffer,"vorbis",6)){ @@ -366,10 +325,6 @@ int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op) /* um... we didn't get the initial header */ return(OV_EBADHEADER); } - if(vc->vendor!=NULL){ - /* previously initialized comment header */ - return(OV_EBADHEADER); - } return(_vorbis_unpack_comment(vc,&opb)); @@ -378,14 +333,6 @@ int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op) /* um... we didn;t get the initial header or comments yet */ return(OV_EBADHEADER); } - if(vi->codec_setup==NULL){ - /* improperly initialized vorbis_info */ - return(OV_EFAULT); - } - if(((codec_setup_info *)vi->codec_setup)->books>0){ - /* previously initialized setup header */ - return(OV_EBADHEADER); - } return(_vorbis_unpack_books(vi,&opb)); diff --git a/lib/tremor/iseeking_example.c b/lib/tremor/iseeking_example.c deleted file mode 100644 index dc971ba4..00000000 --- a/lib/tremor/iseeking_example.c +++ /dev/null @@ -1,265 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2009 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: illustrate seeking, and test it too - last mod: $Id$ - - ********************************************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include "ivorbiscodec.h" -#include "ivorbisfile.h" - -#ifdef _WIN32 /* We need the following two to set stdin/stdout to binary */ -# include <io.h> -# include <fcntl.h> -#endif - -void _verify(OggVorbis_File *ov, - ogg_int64_t val, - ogg_int64_t pcmval, - ogg_int64_t timeval, - ogg_int64_t pcmlength, - char *bigassbuffer){ - int j; - long bread; - char buffer[4096]; - int dummy; - ogg_int64_t pos; - - /* verify the raw position, the pcm position and position decode */ - if(val!=-1 && ov_raw_tell(ov)<val){ - fprintf(stderr,"raw position out of tolerance: requested %ld, got %ld\n", - (long)val,(long)ov_raw_tell(ov)); - exit(1); - } - if(pcmval!=-1 && ov_pcm_tell(ov)>pcmval){ - fprintf(stderr,"pcm position out of tolerance: requested %ld, got %ld\n", - (long)pcmval,(long)ov_pcm_tell(ov)); - exit(1); - } - if(timeval!=-1 && ov_time_tell(ov)>timeval){ - fprintf(stderr,"time position out of tolerance: requested %ld, got %ld\n", - (long)timeval,(long)ov_time_tell(ov)); - exit(1); - } - pos=ov_pcm_tell(ov); - if(pos<0 || pos>pcmlength){ - fprintf(stderr,"pcm position out of bounds: got %ld\n",(long)pos); - exit(1); - } - bread=ov_read(ov,buffer,4096,&dummy); - if(bigassbuffer){ - for(j=0;j<bread;j++){ - if(buffer[j]!=bigassbuffer[j+pos*4]){ - fprintf(stderr,"data position after seek doesn't match pcm position\n"); - - { - FILE *f=fopen("a.m","w"); - for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)buffer[j]); - fclose(f); - f=fopen("b.m","w"); - for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)bigassbuffer[j+pos*2]); - fclose(f); - } - - exit(1); - } - } - } -} - -int main(){ - OggVorbis_File ov; - int i,ret; - ogg_int64_t pcmlength; - ogg_int64_t timelength; - char *bigassbuffer; - int dummy; - -#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ - _setmode( _fileno( stdin ), _O_BINARY ); -#endif - - - /* open the file/pipe on stdin */ - if(ov_open(stdin, &ov, NULL, 0) < 0) { - fprintf(stderr,"Could not open input as an OggVorbis file.\n\n"); - exit(1); - } - - if(ov_seekable(&ov)){ - - /* to simplify our own lives, we want to assume the whole file is - stereo. Verify this to avoid potentially mystifying users - (pissing them off is OK, just don't confuse them) */ - for(i=0;i<ov.links;i++){ - vorbis_info *vi=ov_info(&ov,i); - if(vi->channels!=2){ - fprintf(stderr,"Sorry; right now seeking_test can only use Vorbis files\n" - "that are entirely stereo.\n\n"); - exit(1); - } - } - - /* because we want to do sample-level verification that the seek - does what it claimed, decode the entire file into memory */ - pcmlength=ov_pcm_total(&ov,-1); - timelength=ov_time_total(&ov,-1); - bigassbuffer=malloc(pcmlength*4); /* w00t */ - if(bigassbuffer){ - i=0; - while(i<pcmlength*4){ - int ret=ov_read(&ov,bigassbuffer+i,pcmlength*4-i,&dummy); - if(ret<0)continue; - if(ret){ - i+=ret; - }else{ - pcmlength=i/4; - } - fprintf(stderr,"\rloading.... [%ld left] ", - (long)(pcmlength*4-i)); - } - }else{ - fprintf(stderr,"\rfile too large to load into memory for read tests;\n\tonly verifying seek positioning...\n"); - } - - { - ogg_int64_t length=ov.end; - fprintf(stderr,"\rtesting raw seeking to random places in %ld bytes....\n", - (long)length); - - for(i=0;i<1000;i++){ - ogg_int64_t val=rand()*length/RAND_MAX; - fprintf(stderr,"\r\t%d [raw position %ld]... ",i,(long)val); - ret=ov_raw_seek(&ov,val); - if(ret<0){ - fprintf(stderr,"seek failed: %d\n",ret); - exit(1); - } - - _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer); - - } - } - - fprintf(stderr,"\r"); - { - fprintf(stderr,"testing pcm page seeking to random places in %ld samples....\n", - (long)pcmlength); - - for(i=0;i<1000;i++){ - ogg_int64_t val=i==0?0:(double)rand()*pcmlength/RAND_MAX; - fprintf(stderr,"\r\t%d [pcm position %ld]... ",i,(long)val); - ret=ov_pcm_seek_page(&ov,val); - if(ret<0){ - fprintf(stderr,"seek failed: %d\n",ret); - exit(1); - } - - _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer); - - } - } - - fprintf(stderr,"\r"); - { - fprintf(stderr,"testing pcm exact seeking to random places in %ld samples....\n", - (long)pcmlength); - - for(i=0;i<1000;i++){ - ogg_int64_t val=i==0?0:(double)rand()*pcmlength/RAND_MAX; - fprintf(stderr,"\r\t%d [pcm position %ld]... ",i,(long)val); - ret=ov_pcm_seek(&ov,val); - if(ret<0){ - fprintf(stderr,"seek failed: %d\n",ret); - exit(1); - } - if(ov_pcm_tell(&ov)!=val){ - fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n", - (long)val,(long)ov_pcm_tell(&ov)); - exit(1); - } - - _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer); - - } - } - - fprintf(stderr,"\r"); - { - fprintf(stderr,"testing time page seeking to random places in %ld milliseconds....\n", - (long)timelength); - - for(i=0;i<1000;i++){ - ogg_int64_t val=(double)rand()*timelength/RAND_MAX; - fprintf(stderr,"\r\t%d [time position %ld]... ",i,(long)val); - ret=ov_time_seek_page(&ov,val); - if(ret<0){ - fprintf(stderr,"seek failed: %d\n",ret); - exit(1); - } - - _verify(&ov,-1,-1,val,pcmlength,bigassbuffer); - - } - } - - fprintf(stderr,"\r"); - { - fprintf(stderr,"testing time exact seeking to random places in %ld milliseconds....\n", - (long)timelength); - - for(i=0;i<1000;i++){ - ogg_int64_t val=(double)rand()*timelength/RAND_MAX; - fprintf(stderr,"\r\t%d [time position %ld]... ",i,(long)val); - ret=ov_time_seek(&ov,val); - if(ret<0){ - fprintf(stderr,"seek failed: %d\n",ret); - exit(1); - } - if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){ - fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n", - (long)val,(long)ov_time_tell(&ov)); - exit(1); - } - - _verify(&ov,-1,-1,val,pcmlength,bigassbuffer); - - } - } - - fprintf(stderr,"\r \nOK.\n\n"); - - - }else{ - fprintf(stderr,"Standard input was not seekable.\n"); - } - - ov_clear(&ov); - return 0; -} - - - - - - - - - - - - - diff --git a/lib/tremor/ivorbiscodec.h b/lib/tremor/ivorbiscodec.h index 17eab58d..41d4d5da 100644 --- a/lib/tremor/ivorbiscodec.h +++ b/lib/tremor/ivorbiscodec.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -23,7 +23,10 @@ extern "C" { #endif /* __cplusplus */ -#include <ogg/ogg.h> +#include "tremor_ogg.h" + +struct vorbis_dsp_state; +typedef struct vorbis_dsp_state vorbis_dsp_state; typedef struct vorbis_info{ int version; @@ -53,80 +56,7 @@ typedef struct vorbis_info{ void *codec_setup; } vorbis_info; -/* vorbis_dsp_state buffers the current vorbis audio - analysis/synthesis state. The DSP state belongs to a specific - logical bitstream ****************************************************/ -typedef struct vorbis_dsp_state{ - int analysisp; - vorbis_info *vi; - - ogg_int32_t **pcm; - ogg_int32_t **pcmret; - int pcm_storage; - int pcm_current; - int pcm_returned; - - int preextrapolate; - int eofflag; - - long lW; - long W; - long nW; - long centerW; - - ogg_int64_t granulepos; - ogg_int64_t sequence; - - void *backend_state; -} vorbis_dsp_state; - -typedef struct vorbis_block{ - /* necessary stream state for linking to the framing abstraction */ - ogg_int32_t **pcm; /* this is a pointer into local storage */ - oggpack_buffer opb; - - long lW; - long W; - long nW; - int pcmend; - int mode; - - int eofflag; - ogg_int64_t granulepos; - ogg_int64_t sequence; - vorbis_dsp_state *vd; /* For read-only access of configuration */ - - /* local storage to avoid remallocing; it's up to the mapping to - structure it */ - void *localstore; - long localtop; - long localalloc; - long totaluse; - struct alloc_chain *reap; - -} vorbis_block; - -/* vorbis_block is a single block of data to be processed as part of -the analysis/synthesis stream; it belongs to a specific logical -bitstream, but is independant from other vorbis_blocks belonging to -that logical bitstream. *************************************************/ - -struct alloc_chain{ - void *ptr; - struct alloc_chain *next; -}; - -/* vorbis_info contains all the setup information specific to the - specific compression/decompression mode in progress (eg, - psychoacoustic settings, channel setup, options, codebook - etc). vorbis_info and substructures are in backends.h. -*********************************************************************/ - -/* the comments are not part of vorbis_info so that vorbis_info can be - static storage */ typedef struct vorbis_comment{ - /* unlimited user comment fields. libvorbis writes 'libvorbis' - whatever vendor is set to in encode */ char **user_comments; int *comment_lengths; int comments; @@ -135,18 +65,6 @@ typedef struct vorbis_comment{ } vorbis_comment; -/* libvorbis encodes in two abstraction layers; first we perform DSP - and produce a packet (see docs/analysis.txt). The packet is then - coded into a framed OggSquish bitstream by the second layer (see - docs/framing.txt). Decode is the reverse process; we sync/frame - the bitstream and extract individual packets, then decode the - packet back into PCM audio. - - The extra framing/packetizing is used in streaming formats, such as - files. Over the net (such as with UDP), the framing and - packetization aren't necessary as they're provided by the transport - and the streaming layer is not used */ - /* Vorbis PRIMITIVES: general ***************************************/ extern void vorbis_info_init(vorbis_info *vi); @@ -160,24 +78,6 @@ extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count); extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag); extern void vorbis_comment_clear(vorbis_comment *vc); -extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); -extern int vorbis_block_clear(vorbis_block *vb); -extern void vorbis_dsp_clear(vorbis_dsp_state *v); - -/* Vorbis PRIMITIVES: synthesis layer *******************************/ -extern int vorbis_synthesis_idheader(ogg_packet *op); -extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, - ogg_packet *op); - -extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); -extern int vorbis_synthesis_restart(vorbis_dsp_state *v); -extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); -extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); -extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); -extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm); -extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); -extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); - /* Vorbis ERRORS and return codes ***********************************/ #define OV_FALSE -1 diff --git a/lib/tremor/ivorbisfile.h b/lib/tremor/ivorbisfile.h index f6ecb0e4..c8734031 100644 --- a/lib/tremor/ivorbisfile.h +++ b/lib/tremor/ivorbisfile.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -26,8 +26,6 @@ extern "C" #include <stdio.h> #include "ivorbiscodec.h" -#define CHUNKSIZE 65535 -#define READSIZE 1024 /* The function prototypes for the callbacks are basically the same as for * the stdio functions fread, fseek, fclose, ftell. * The one difference is that the FILE * arguments have been replaced with @@ -40,86 +38,79 @@ extern "C" */ typedef struct { size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); - int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); + int (*seek_func) (void *datasource, tremor_ogg_int64_t offset, int whence); int (*close_func) (void *datasource); long (*tell_func) (void *datasource); } ov_callbacks; -#define NOTOPEN 0 -#define PARTOPEN 1 -#define OPENED 2 -#define STREAMSET 3 -#define INITSET 4 - -typedef struct OggVorbis_File { +typedef struct TremorOggVorbis_File { void *datasource; /* Pointer to a FILE *, etc. */ int seekable; - ogg_int64_t offset; - ogg_int64_t end; - ogg_sync_state oy; + tremor_ogg_int64_t offset; + tremor_ogg_int64_t end; + tremor_ogg_sync_state *oy; /* If the FILE handle isn't seekable (eg, a pipe), only the current stream appears */ int links; - ogg_int64_t *offsets; - ogg_int64_t *dataoffsets; - ogg_uint32_t *serialnos; - ogg_int64_t *pcmlengths; - vorbis_info *vi; - vorbis_comment *vc; + tremor_ogg_int64_t *offsets; + tremor_ogg_int64_t *dataoffsets; + tremor_ogg_uint32_t *serialnos; + tremor_ogg_int64_t *pcmlengths; + vorbis_info vi; + vorbis_comment vc; /* Decoding working state local storage */ - ogg_int64_t pcm_offset; + tremor_ogg_int64_t pcm_offset; int ready_state; - ogg_uint32_t current_serialno; + tremor_ogg_uint32_t current_serialno; int current_link; - ogg_int64_t bittrack; - ogg_int64_t samptrack; + tremor_ogg_int64_t bittrack; + tremor_ogg_int64_t samptrack; - ogg_stream_state os; /* take physical pages, weld into a logical + tremor_ogg_stream_state *os; /* take physical pages, weld into a logical stream of packets */ - vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ - vorbis_block vb; /* local working space for packet->PCM decode */ + vorbis_dsp_state *vd; /* central working state for the packet->PCM decoder */ ov_callbacks callbacks; -} OggVorbis_File; +} TremorOggVorbis_File; -extern int ov_clear(OggVorbis_File *vf); -extern int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); -extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, - const char *initial, long ibytes, ov_callbacks callbacks); +extern int ov_clear(TremorOggVorbis_File *vf); +extern int ov_open(FILE *f,TremorOggVorbis_File *vf,char *initial,long ibytes); +extern int ov_open_callbacks(void *datasource, TremorOggVorbis_File *vf, + char *initial, long ibytes, ov_callbacks callbacks); -extern int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); -extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, - const char *initial, long ibytes, ov_callbacks callbacks); -extern int ov_test_open(OggVorbis_File *vf); +extern int ov_test(FILE *f,TremorOggVorbis_File *vf,char *initial,long ibytes); +extern int ov_test_callbacks(void *datasource, TremorOggVorbis_File *vf, + char *initial, long ibytes, ov_callbacks callbacks); +extern int ov_test_open(TremorOggVorbis_File *vf); -extern long ov_bitrate(OggVorbis_File *vf,int i); -extern long ov_bitrate_instant(OggVorbis_File *vf); -extern long ov_streams(OggVorbis_File *vf); -extern long ov_seekable(OggVorbis_File *vf); -extern long ov_serialnumber(OggVorbis_File *vf,int i); +extern long ov_bitrate(TremorOggVorbis_File *vf,int i); +extern long ov_bitrate_instant(TremorOggVorbis_File *vf); +extern long ov_streams(TremorOggVorbis_File *vf); +extern long ov_seekable(TremorOggVorbis_File *vf); +extern long ov_serialnumber(TremorOggVorbis_File *vf,int i); -extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i); -extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i); -extern ogg_int64_t ov_time_total(OggVorbis_File *vf,int i); +extern tremor_ogg_int64_t ov_raw_total(TremorOggVorbis_File *vf,int i); +extern tremor_ogg_int64_t ov_pcm_total(TremorOggVorbis_File *vf,int i); +extern tremor_ogg_int64_t ov_time_total(TremorOggVorbis_File *vf,int i); -extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_time_seek(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_raw_seek(TremorOggVorbis_File *vf,tremor_ogg_int64_t pos); +extern int ov_pcm_seek(TremorOggVorbis_File *vf,tremor_ogg_int64_t pos); +extern int ov_pcm_seek_page(TremorOggVorbis_File *vf,tremor_ogg_int64_t pos); +extern int ov_time_seek(TremorOggVorbis_File *vf,tremor_ogg_int64_t pos); +extern int ov_time_seek_page(TremorOggVorbis_File *vf,tremor_ogg_int64_t pos); -extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf); -extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf); -extern ogg_int64_t ov_time_tell(OggVorbis_File *vf); +extern tremor_ogg_int64_t ov_raw_tell(TremorOggVorbis_File *vf); +extern tremor_ogg_int64_t ov_pcm_tell(TremorOggVorbis_File *vf); +extern tremor_ogg_int64_t ov_time_tell(TremorOggVorbis_File *vf); -extern vorbis_info *ov_info(OggVorbis_File *vf,int link); -extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link); +extern vorbis_info *ov_info(TremorOggVorbis_File *vf,int link); +extern vorbis_comment *ov_comment(TremorOggVorbis_File *vf,int link); -extern long ov_read(OggVorbis_File *vf,char *buffer,int length, +extern long ov_read(TremorOggVorbis_File *vf,void *buffer,int length, int *bitstream); #ifdef __cplusplus diff --git a/lib/tremor/ivorbisfile_example.c b/lib/tremor/ivorbisfile_example.c index 7b0cf109..5c0e6bcc 100644 --- a/lib/tremor/ivorbisfile_example.c +++ b/lib/tremor/ivorbisfile_example.c @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -32,7 +32,7 @@ char pcmout[4096]; /* take 4k out of the data segment, not the stack */ int main(){ - OggVorbis_File vf; + TremorOggVorbis_File vf; int eof=0; int current_section; @@ -69,12 +69,7 @@ int main(){ /* EOF */ eof=1; } else if (ret < 0) { - if(ret==OV_EBADLINK){ - fprintf(stderr,"Corrupt bitstream section! Exiting.\n"); - exit(1); - } - - /* some other error in the stream. Not a problem, just reporting it in + /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ } else { /* we don't bother dealing with sample rate changes, etc, but diff --git a/lib/tremor/lsp_lookup.h b/lib/tremor/lsp_lookup.h index 7162392b..3edcab3a 100644 --- a/lib/tremor/lsp_lookup.h +++ b/lib/tremor/lsp_lookup.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,35 +18,7 @@ #ifndef _V_LOOKUP_DATA_H_ #define _V_LOOKUP_DATA_H_ -#include <ogg/os_types.h> - -#define FROMdB_LOOKUP_SZ 35 -#define FROMdB2_LOOKUP_SZ 32 -#define FROMdB_SHIFT 5 -#define FROMdB2_SHIFT 3 -#define FROMdB2_MASK 31 - -static const ogg_int32_t FROMdB_LOOKUP[FROMdB_LOOKUP_SZ]={ - 0x003fffff, 0x0028619b, 0x00197a96, 0x0010137a, - 0x000a24b0, 0x00066666, 0x000409c3, 0x00028c42, - 0x00019b8c, 0x000103ab, 0x0000a3d7, 0x00006760, - 0x0000413a, 0x00002928, 0x000019f8, 0x00001062, - 0x00000a56, 0x00000686, 0x0000041e, 0x00000299, - 0x000001a3, 0x00000109, 0x000000a7, 0x00000069, - 0x00000042, 0x0000002a, 0x0000001a, 0x00000011, - 0x0000000b, 0x00000007, 0x00000004, 0x00000003, - 0x00000002, 0x00000001, 0x00000001}; - -static const ogg_int32_t FROMdB2_LOOKUP[FROMdB2_LOOKUP_SZ]={ - 0x000001fc, 0x000001f5, 0x000001ee, 0x000001e7, - 0x000001e0, 0x000001d9, 0x000001d2, 0x000001cc, - 0x000001c5, 0x000001bf, 0x000001b8, 0x000001b2, - 0x000001ac, 0x000001a6, 0x000001a0, 0x0000019a, - 0x00000194, 0x0000018e, 0x00000188, 0x00000183, - 0x0000017d, 0x00000178, 0x00000172, 0x0000016d, - 0x00000168, 0x00000163, 0x0000015e, 0x00000159, - 0x00000154, 0x0000014f, 0x0000014a, 0x00000145, -}; +#include "os_types.h" #define INVSQ_LOOKUP_I_SHIFT 10 #define INVSQ_LOOKUP_I_MASK 1023 @@ -92,7 +64,7 @@ static const long INVSQ_LOOKUP_IDel[64]={ #define COS_LOOKUP_I_SHIFT 9 #define COS_LOOKUP_I_MASK 511 #define COS_LOOKUP_I_SZ 128 -static const ogg_int32_t COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={ +static const tremor_ogg_int32_t COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={ 16384, 16379, 16364, 16340, 16305, 16261, 16207, 16143, 16069, 15986, 15893, 15791, diff --git a/lib/tremor/mapping0.c b/lib/tremor/mapping0.c index aa03e854..3da185c5 100644 --- a/lib/tremor/mapping0.c +++ b/lib/tremor/mapping0.c @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -19,101 +19,23 @@ #include <stdio.h> #include <string.h> #include <math.h> -#include <ogg/ogg.h> +#include "tremor_ogg.h" +#include "os.h" #include "ivorbiscodec.h" #include "mdct.h" #include "codec_internal.h" #include "codebook.h" -#include "window.h" -#include "registry.h" #include "misc.h" -/* simplistic, wasteful way of doing this (unique lookup for each - mode/submapping); there should be a central repository for - identical lookups. That will require minor work, so I'm putting it - off as low priority. - - Why a lookup for each backend in a given mode? Because the - blocksize is set by the mode, and low backend lookups may require - parameters from other areas of the mode/mapping */ - -typedef struct { - vorbis_info_mode *mode; - vorbis_info_mapping0 *map; - - vorbis_look_floor **floor_look; - - vorbis_look_residue **residue_look; - - vorbis_func_floor **floor_func; - vorbis_func_residue **residue_func; - - int ch; - long lastframe; /* if a different mode is called, we need to - invalidate decay */ -} vorbis_look_mapping0; - -static void mapping0_free_info(vorbis_info_mapping *i){ - vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i; +void mapping_clear_info(vorbis_info_mapping *info){ if(info){ + if(info->chmuxlist)_tremor_ogg_free(info->chmuxlist); + if(info->submaplist)_tremor_ogg_free(info->submaplist); + if(info->coupling)_tremor_ogg_free(info->coupling); memset(info,0,sizeof(*info)); - _ogg_free(info); - } -} - -static void mapping0_free_look(vorbis_look_mapping *look){ - int i; - vorbis_look_mapping0 *l=(vorbis_look_mapping0 *)look; - if(l){ - - for(i=0;i<l->map->submaps;i++){ - l->floor_func[i]->free_look(l->floor_look[i]); - l->residue_func[i]->free_look(l->residue_look[i]); - } - - _ogg_free(l->floor_func); - _ogg_free(l->residue_func); - _ogg_free(l->floor_look); - _ogg_free(l->residue_look); - memset(l,0,sizeof(*l)); - _ogg_free(l); } } -static vorbis_look_mapping *mapping0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, - vorbis_info_mapping *m){ - int i; - vorbis_info *vi=vd->vi; - codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; - vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)_ogg_calloc(1,sizeof(*look)); - vorbis_info_mapping0 *info=look->map=(vorbis_info_mapping0 *)m; - look->mode=vm; - - look->floor_look=(vorbis_look_floor **)_ogg_calloc(info->submaps,sizeof(*look->floor_look)); - - look->residue_look=(vorbis_look_residue **)_ogg_calloc(info->submaps,sizeof(*look->residue_look)); - - look->floor_func=(vorbis_func_floor **)_ogg_calloc(info->submaps,sizeof(*look->floor_func)); - look->residue_func=(vorbis_func_residue **)_ogg_calloc(info->submaps,sizeof(*look->residue_func)); - - for(i=0;i<info->submaps;i++){ - int floornum=info->floorsubmap[i]; - int resnum=info->residuesubmap[i]; - - look->floor_func[i]=_floor_P[ci->floor_type[floornum]]; - look->floor_look[i]=look->floor_func[i]-> - look(vd,vm,ci->floor_param[floornum]); - look->residue_func[i]=_residue_P[ci->residue_type[resnum]]; - look->residue_look[i]=look->residue_func[i]-> - look(vd,vm,ci->residue_param[resnum]); - - } - - look->ch=vi->channels; - - return(look); -} - static int ilog(unsigned int v){ int ret=0; if(v)--v; @@ -125,28 +47,25 @@ static int ilog(unsigned int v){ } /* also responsible for range checking */ -static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){ - int i,b; - vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)_ogg_calloc(1,sizeof(*info)); +int mapping_info_unpack(vorbis_info_mapping *info,vorbis_info *vi, + tremor_oggpack_buffer *opb){ + int i; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; memset(info,0,sizeof(*info)); - b=oggpack_read(opb,1); - if(b<0)goto err_out; - if(b){ - info->submaps=oggpack_read(opb,4)+1; - if(info->submaps<=0)goto err_out; - }else + if(tremor_oggpack_read(opb,1)) + info->submaps=tremor_oggpack_read(opb,4)+1; + else info->submaps=1; - b=oggpack_read(opb,1); - if(b<0)goto err_out; - if(b){ - info->coupling_steps=oggpack_read(opb,8)+1; - if(info->coupling_steps<=0)goto err_out; + if(tremor_oggpack_read(opb,1)){ + info->coupling_steps=tremor_oggpack_read(opb,8)+1; + info->coupling= + _tremor_ogg_malloc(info->coupling_steps*sizeof(*info->coupling)); + for(i=0;i<info->coupling_steps;i++){ - int testM=info->coupling_mag[i]=oggpack_read(opb,ilog(vi->channels)); - int testA=info->coupling_ang[i]=oggpack_read(opb,ilog(vi->channels)); + int testM=info->coupling[i].mag=tremor_oggpack_read(opb,ilog(vi->channels)); + int testA=info->coupling[i].ang=tremor_oggpack_read(opb,ilog(vi->channels)); if(testM<0 || testA<0 || @@ -157,72 +76,82 @@ static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb) } - if(oggpack_read(opb,2)!=0)goto err_out; /* 2,3:reserved */ + if(tremor_oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */ if(info->submaps>1){ + info->chmuxlist=_tremor_ogg_malloc(sizeof(*info->chmuxlist)*vi->channels); for(i=0;i<vi->channels;i++){ - info->chmuxlist[i]=oggpack_read(opb,4); - if(info->chmuxlist[i]>=info->submaps || info->chmuxlist[i]<0)goto err_out; + info->chmuxlist[i]=tremor_oggpack_read(opb,4); + if(info->chmuxlist[i]>=info->submaps)goto err_out; } } + + info->submaplist=_tremor_ogg_malloc(sizeof(*info->submaplist)*info->submaps); for(i=0;i<info->submaps;i++){ - int temp=oggpack_read(opb,8); - if(temp>=ci->times)goto err_out; - info->floorsubmap[i]=oggpack_read(opb,8); - if(info->floorsubmap[i]>=ci->floors || info->floorsubmap[i]<0)goto err_out; - info->residuesubmap[i]=oggpack_read(opb,8); - if(info->residuesubmap[i]>=ci->residues || info->residuesubmap[i]<0) - goto err_out; + int temp=tremor_oggpack_read(opb,8); + info->submaplist[i].floor=tremor_oggpack_read(opb,8); + if(info->submaplist[i].floor>=ci->floors)goto err_out; + info->submaplist[i].residue=tremor_oggpack_read(opb,8); + if(info->submaplist[i].residue>=ci->residues)goto err_out; } - return info; + return 0; err_out: - mapping0_free_info(info); - return(NULL); + mapping_clear_info(info); + return -1; } -static int seq=0; -static int mapping0_inverse(vorbis_block *vb,vorbis_look_mapping *l){ - vorbis_dsp_state *vd=vb->vd; +int mapping_inverse(vorbis_dsp_state *vd,vorbis_info_mapping *info){ vorbis_info *vi=vd->vi; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; - private_state *b=(private_state *)vd->backend_state; - vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l; - vorbis_info_mapping0 *info=look->map; int i,j; - long n=vb->pcmend=ci->blocksizes[vb->W]; - - ogg_int32_t **pcmbundle=(ogg_int32_t **)alloca(sizeof(*pcmbundle)*vi->channels); - int *zerobundle=(int *)alloca(sizeof(*zerobundle)*vi->channels); + long n=ci->blocksizes[vd->W]; + + tremor_ogg_int32_t **pcmbundle= + alloca(sizeof(*pcmbundle)*vi->channels); + int *zerobundle= + alloca(sizeof(*zerobundle)*vi->channels); + int *nonzero= + alloca(sizeof(*nonzero)*vi->channels); + tremor_ogg_int32_t **floormemo= + alloca(sizeof(*floormemo)*vi->channels); - int *nonzero =(int *)alloca(sizeof(*nonzero)*vi->channels); - void **floormemo=(void **)alloca(sizeof(*floormemo)*vi->channels); - - /* time domain information decode (note that applying the - information would have to happen later; we'll probably add a - function entry to the harness for that later */ - /* NOT IMPLEMENTED */ - /* recover the spectral envelope; store it in the PCM vector for now */ for(i=0;i<vi->channels;i++){ - int submap=info->chmuxlist[i]; - floormemo[i]=look->floor_func[submap]-> - inverse1(vb,look->floor_look[submap]); + int submap=0; + int floorno; + + if(info->submaps>1) + submap=info->chmuxlist[i]; + floorno=info->submaplist[submap].floor; + + if(ci->floor_type[floorno]){ + /* floor 1 */ + floormemo[i]=alloca(sizeof(*floormemo[i])* + floor1_memosize(ci->floor_param[floorno])); + floormemo[i]=floor1_inverse1(vd,ci->floor_param[floorno],floormemo[i]); + }else{ + /* floor 0 */ + floormemo[i]=alloca(sizeof(*floormemo[i])* + floor0_memosize(ci->floor_param[floorno])); + floormemo[i]=floor0_inverse1(vd,ci->floor_param[floorno],floormemo[i]); + } + if(floormemo[i]) nonzero[i]=1; else nonzero[i]=0; - memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2); + memset(vd->work[i],0,sizeof(*vd->work[i])*n/2); } /* channel coupling can 'dirty' the nonzero listing */ for(i=0;i<info->coupling_steps;i++){ - if(nonzero[info->coupling_mag[i]] || - nonzero[info->coupling_ang[i]]){ - nonzero[info->coupling_mag[i]]=1; - nonzero[info->coupling_ang[i]]=1; + if(nonzero[info->coupling[i].mag] || + nonzero[info->coupling[i].ang]){ + nonzero[info->coupling[i].mag]=1; + nonzero[info->coupling[i].ang]=1; } } @@ -230,31 +159,30 @@ static int mapping0_inverse(vorbis_block *vb,vorbis_look_mapping *l){ for(i=0;i<info->submaps;i++){ int ch_in_bundle=0; for(j=0;j<vi->channels;j++){ - if(info->chmuxlist[j]==i){ + if(!info->chmuxlist || info->chmuxlist[j]==i){ if(nonzero[j]) zerobundle[ch_in_bundle]=1; else zerobundle[ch_in_bundle]=0; - pcmbundle[ch_in_bundle++]=vb->pcm[j]; + pcmbundle[ch_in_bundle++]=vd->work[j]; } } - look->residue_func[i]->inverse(vb,look->residue_look[i], - pcmbundle,zerobundle,ch_in_bundle); + res_inverse(vd,ci->residue_param+info->submaplist[i].residue, + pcmbundle,zerobundle,ch_in_bundle); } //for(j=0;j<vi->channels;j++) //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0); - /* channel coupling */ for(i=info->coupling_steps-1;i>=0;i--){ - ogg_int32_t *pcmM=vb->pcm[info->coupling_mag[i]]; - ogg_int32_t *pcmA=vb->pcm[info->coupling_ang[i]]; + tremor_ogg_int32_t *pcmM=vd->work[info->coupling[i].mag]; + tremor_ogg_int32_t *pcmA=vd->work[info->coupling[i].ang]; for(j=0;j<n/2;j++){ - ogg_int32_t mag=pcmM[j]; - ogg_int32_t ang=pcmA[j]; + tremor_ogg_int32_t mag=pcmM[j]; + tremor_ogg_int32_t ang=pcmA[j]; if(mag>0) if(ang>0){ @@ -280,10 +208,21 @@ static int mapping0_inverse(vorbis_block *vb,vorbis_look_mapping *l){ /* compute and apply spectral envelope */ for(i=0;i<vi->channels;i++){ - ogg_int32_t *pcm=vb->pcm[i]; - int submap=info->chmuxlist[i]; - look->floor_func[submap]-> - inverse2(vb,look->floor_look[submap],floormemo[i],pcm); + tremor_ogg_int32_t *pcm=vd->work[i]; + int submap=0; + int floorno; + + if(info->submaps>1) + submap=info->chmuxlist[i]; + floorno=info->submaplist[submap].floor; + + if(ci->floor_type[floorno]){ + /* floor 1 */ + floor1_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm); + }else{ + /* floor 0 */ + floor0_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm); + } } //for(j=0;j<vi->channels;j++) @@ -291,38 +230,12 @@ static int mapping0_inverse(vorbis_block *vb,vorbis_look_mapping *l){ /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ /* only MDCT right now.... */ - for(i=0;i<vi->channels;i++){ - ogg_int32_t *pcm=vb->pcm[i]; - mdct_backward(n,pcm,pcm); - } + for(i=0;i<vi->channels;i++) + mdct_backward(n,vd->work[i]); //for(j=0;j<vi->channels;j++) //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0); - /* window the data */ - for(i=0;i<vi->channels;i++){ - ogg_int32_t *pcm=vb->pcm[i]; - if(nonzero[i]) - _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW); - else - for(j=0;j<n;j++) - pcm[j]=0; - - } - - //for(j=0;j<vi->channels;j++) - //_analysis_output("window",seq+j,vb->pcm[j],-24,n,0,0); - - seq+=vi->channels; /* all done! */ return(0); } - -/* export hooks */ -vorbis_func_mapping mapping0_exportbundle={ - &mapping0_unpack, - &mapping0_look, - &mapping0_free_info, - &mapping0_free_look, - &mapping0_inverse -}; diff --git a/lib/tremor/mdct.c b/lib/tremor/mdct.c index 2aed62c5..40f53877 100644 --- a/lib/tremor/mdct.c +++ b/lib/tremor/mdct.c @@ -1,19 +1,19 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: normalized modified discrete cosine transform power of two length transform only [64 <= n ] - last mod: $Id$ + last mod: $Id: mdct.c,v 1.9.6.5 2003/04/29 04:03:27 xiphmont Exp $ Original algorithm adapted long ago from _The use of multirate filter banks for coding of high quality digital audio_, by T. Sporer, @@ -33,23 +33,62 @@ ********************************************************************/ #include "ivorbiscodec.h" -#include "codebook.h" +#include "os.h" #include "misc.h" #include "mdct.h" #include "mdct_lookup.h" +STIN void presymmetry(DATA_TYPE *in,int n2,int step){ + DATA_TYPE *aX; + DATA_TYPE *bX; + LOOKUP_T *T; + int n4=n2>>1; + + aX = in+n2-3; + T = sincos_lookup0; + + do{ + REG_TYPE r0= aX[0]; + REG_TYPE r2= aX[2]; + XPROD31( r0, r2, T[0], T[1], &aX[0], &aX[2] ); T+=step; + aX-=4; + }while(aX>=in+n4); + do{ + REG_TYPE r0= aX[0]; + REG_TYPE r2= aX[2]; + XPROD31( r0, r2, T[1], T[0], &aX[0], &aX[2] ); T-=step; + aX-=4; + }while(aX>=in); + + aX = in+n2-4; + bX = in; + T = sincos_lookup0; + do{ + REG_TYPE ri0= aX[0]; + REG_TYPE ri2= aX[2]; + REG_TYPE ro0= bX[0]; + REG_TYPE ro2= bX[2]; + + XNPROD31( ro2, ro0, T[1], T[0], &aX[0], &aX[2] ); T+=step; + XNPROD31( ri2, ri0, T[0], T[1], &bX[0], &bX[2] ); + + aX-=4; + bX+=4; + }while(aX>=in+n4); + +} /* 8 point butterfly (in place) */ STIN void mdct_butterfly_8(DATA_TYPE *x){ - REG_TYPE r0 = x[4] + x[0]; - REG_TYPE r1 = x[4] - x[0]; - REG_TYPE r2 = x[5] + x[1]; - REG_TYPE r3 = x[5] - x[1]; - REG_TYPE r4 = x[6] + x[2]; - REG_TYPE r5 = x[6] - x[2]; - REG_TYPE r6 = x[7] + x[3]; - REG_TYPE r7 = x[7] - x[3]; + REG_TYPE r0 = x[0] + x[1]; + REG_TYPE r1 = x[0] - x[1]; + REG_TYPE r2 = x[2] + x[3]; + REG_TYPE r3 = x[2] - x[3]; + REG_TYPE r4 = x[4] + x[5]; + REG_TYPE r5 = x[4] - x[5]; + REG_TYPE r6 = x[6] + x[7]; + REG_TYPE r7 = x[6] - x[7]; x[0] = r5 + r3; x[1] = r7 - r1; @@ -64,29 +103,25 @@ STIN void mdct_butterfly_8(DATA_TYPE *x){ /* 16 point butterfly (in place, 4 register) */ STIN void mdct_butterfly_16(DATA_TYPE *x){ - - REG_TYPE r0, r1; - - r0 = x[ 0] - x[ 8]; x[ 8] += x[ 0]; - r1 = x[ 1] - x[ 9]; x[ 9] += x[ 1]; - x[ 0] = MULT31((r0 + r1) , cPI2_8); - x[ 1] = MULT31((r1 - r0) , cPI2_8); - MB(); - - r0 = x[10] - x[ 2]; x[10] += x[ 2]; - r1 = x[ 3] - x[11]; x[11] += x[ 3]; - x[ 2] = r1; x[ 3] = r0; - MB(); - - r0 = x[12] - x[ 4]; x[12] += x[ 4]; - r1 = x[13] - x[ 5]; x[13] += x[ 5]; - x[ 4] = MULT31((r0 - r1) , cPI2_8); - x[ 5] = MULT31((r0 + r1) , cPI2_8); + + REG_TYPE r0, r1, r2, r3; + + r0 = x[ 8] - x[ 9]; x[ 8] += x[ 9]; + r1 = x[10] - x[11]; x[10] += x[11]; + r2 = x[ 1] - x[ 0]; x[ 9] = x[ 1] + x[0]; + r3 = x[ 3] - x[ 2]; x[11] = x[ 3] + x[2]; + x[ 0] = MULT31((r0 - r1) , cPI2_8); + x[ 1] = MULT31((r2 + r3) , cPI2_8); + x[ 2] = MULT31((r0 + r1) , cPI2_8); + x[ 3] = MULT31((r3 - r2) , cPI2_8); MB(); - r0 = x[14] - x[ 6]; x[14] += x[ 6]; - r1 = x[15] - x[ 7]; x[15] += x[ 7]; - x[ 6] = r0; x[ 7] = r1; + r2 = x[12] - x[13]; x[12] += x[13]; + r3 = x[14] - x[15]; x[14] += x[15]; + r0 = x[ 4] - x[ 5]; x[13] = x[ 5] + x[ 4]; + r1 = x[ 7] - x[ 6]; x[15] = x[ 7] + x[ 6]; + x[ 4] = r2; x[ 5] = r1; + x[ 6] = r3; x[ 7] = r0; MB(); mdct_butterfly_8(x); @@ -96,48 +131,40 @@ STIN void mdct_butterfly_16(DATA_TYPE *x){ /* 32 point butterfly (in place, 4 register) */ STIN void mdct_butterfly_32(DATA_TYPE *x){ - REG_TYPE r0, r1; - - r0 = x[30] - x[14]; x[30] += x[14]; - r1 = x[31] - x[15]; x[31] += x[15]; - x[14] = r0; x[15] = r1; - MB(); - - r0 = x[28] - x[12]; x[28] += x[12]; - r1 = x[29] - x[13]; x[29] += x[13]; - XNPROD31( r0, r1, cPI1_8, cPI3_8, &x[12], &x[13] ); - MB(); - - r0 = x[26] - x[10]; x[26] += x[10]; - r1 = x[27] - x[11]; x[27] += x[11]; - x[10] = MULT31((r0 - r1) , cPI2_8); - x[11] = MULT31((r0 + r1) , cPI2_8); - MB(); - - r0 = x[24] - x[ 8]; x[24] += x[ 8]; - r1 = x[25] - x[ 9]; x[25] += x[ 9]; - XNPROD31( r0, r1, cPI3_8, cPI1_8, &x[ 8], &x[ 9] ); - MB(); + REG_TYPE r0, r1, r2, r3; - r0 = x[22] - x[ 6]; x[22] += x[ 6]; - r1 = x[ 7] - x[23]; x[23] += x[ 7]; - x[ 6] = r1; x[ 7] = r0; + r0 = x[16] - x[17]; x[16] += x[17]; + r1 = x[18] - x[19]; x[18] += x[19]; + r2 = x[ 1] - x[ 0]; x[17] = x[ 1] + x[ 0]; + r3 = x[ 3] - x[ 2]; x[19] = x[ 3] + x[ 2]; + XNPROD31( r0, r1, cPI3_8, cPI1_8, &x[ 0], &x[ 2] ); + XPROD31 ( r2, r3, cPI1_8, cPI3_8, &x[ 1], &x[ 3] ); MB(); - r0 = x[ 4] - x[20]; x[20] += x[ 4]; - r1 = x[ 5] - x[21]; x[21] += x[ 5]; - XPROD31 ( r0, r1, cPI3_8, cPI1_8, &x[ 4], &x[ 5] ); + r0 = x[20] - x[21]; x[20] += x[21]; + r1 = x[22] - x[23]; x[22] += x[23]; + r2 = x[ 5] - x[ 4]; x[21] = x[ 5] + x[ 4]; + r3 = x[ 7] - x[ 6]; x[23] = x[ 7] + x[ 6]; + x[ 4] = MULT31((r0 - r1) , cPI2_8); + x[ 5] = MULT31((r3 + r2) , cPI2_8); + x[ 6] = MULT31((r0 + r1) , cPI2_8); + x[ 7] = MULT31((r3 - r2) , cPI2_8); MB(); - r0 = x[ 2] - x[18]; x[18] += x[ 2]; - r1 = x[ 3] - x[19]; x[19] += x[ 3]; - x[ 2] = MULT31((r1 + r0) , cPI2_8); - x[ 3] = MULT31((r1 - r0) , cPI2_8); + r0 = x[24] - x[25]; x[24] += x[25]; + r1 = x[26] - x[27]; x[26] += x[27]; + r2 = x[ 9] - x[ 8]; x[25] = x[ 9] + x[ 8]; + r3 = x[11] - x[10]; x[27] = x[11] + x[10]; + XNPROD31( r0, r1, cPI1_8, cPI3_8, &x[ 8], &x[10] ); + XPROD31 ( r2, r3, cPI3_8, cPI1_8, &x[ 9], &x[11] ); MB(); - r0 = x[ 0] - x[16]; x[16] += x[ 0]; - r1 = x[ 1] - x[17]; x[17] += x[ 1]; - XPROD31 ( r0, r1, cPI1_8, cPI3_8, &x[ 0], &x[ 1] ); + r0 = x[28] - x[29]; x[28] += x[29]; + r1 = x[30] - x[31]; x[30] += x[31]; + r2 = x[12] - x[13]; x[29] = x[13] + x[12]; + r3 = x[15] - x[14]; x[31] = x[15] + x[14]; + x[12] = r0; x[13] = r3; + x[14] = r1; x[15] = r2; MB(); mdct_butterfly_16(x); @@ -147,87 +174,30 @@ STIN void mdct_butterfly_32(DATA_TYPE *x){ /* N/stage point generic N stage butterfly (in place, 2 register) */ STIN void mdct_butterfly_generic(DATA_TYPE *x,int points,int step){ - LOOKUP_T *T = sincos_lookup0; - DATA_TYPE *x1 = x + points - 8; - DATA_TYPE *x2 = x + (points>>1) - 8; - REG_TYPE r0; - REG_TYPE r1; - - do{ - r0 = x1[6] - x2[6]; x1[6] += x2[6]; - r1 = x2[7] - x1[7]; x1[7] += x2[7]; - XPROD31( r1, r0, T[0], T[1], &x2[6], &x2[7] ); T+=step; - - r0 = x1[4] - x2[4]; x1[4] += x2[4]; - r1 = x2[5] - x1[5]; x1[5] += x2[5]; - XPROD31( r1, r0, T[0], T[1], &x2[4], &x2[5] ); T+=step; + LOOKUP_T *T = sincos_lookup0; + DATA_TYPE *x1 = x + points - 4; + DATA_TYPE *x2 = x + (points>>1) - 4; + REG_TYPE r0, r1, r2, r3; - r0 = x1[2] - x2[2]; x1[2] += x2[2]; - r1 = x2[3] - x1[3]; x1[3] += x2[3]; - XPROD31( r1, r0, T[0], T[1], &x2[2], &x2[3] ); T+=step; - - r0 = x1[0] - x2[0]; x1[0] += x2[0]; - r1 = x2[1] - x1[1]; x1[1] += x2[1]; - XPROD31( r1, r0, T[0], T[1], &x2[0], &x2[1] ); T+=step; - - x1-=8; x2-=8; - }while(T<sincos_lookup0+1024); - do{ - r0 = x1[6] - x2[6]; x1[6] += x2[6]; - r1 = x1[7] - x2[7]; x1[7] += x2[7]; - XNPROD31( r0, r1, T[0], T[1], &x2[6], &x2[7] ); T-=step; - - r0 = x1[4] - x2[4]; x1[4] += x2[4]; - r1 = x1[5] - x2[5]; x1[5] += x2[5]; - XNPROD31( r0, r1, T[0], T[1], &x2[4], &x2[5] ); T-=step; - - r0 = x1[2] - x2[2]; x1[2] += x2[2]; - r1 = x1[3] - x2[3]; x1[3] += x2[3]; - XNPROD31( r0, r1, T[0], T[1], &x2[2], &x2[3] ); T-=step; - - r0 = x1[0] - x2[0]; x1[0] += x2[0]; - r1 = x1[1] - x2[1]; x1[1] += x2[1]; - XNPROD31( r0, r1, T[0], T[1], &x2[0], &x2[1] ); T-=step; - - x1-=8; x2-=8; - }while(T>sincos_lookup0); do{ - r0 = x2[6] - x1[6]; x1[6] += x2[6]; - r1 = x2[7] - x1[7]; x1[7] += x2[7]; - XPROD31( r0, r1, T[0], T[1], &x2[6], &x2[7] ); T+=step; - - r0 = x2[4] - x1[4]; x1[4] += x2[4]; - r1 = x2[5] - x1[5]; x1[5] += x2[5]; - XPROD31( r0, r1, T[0], T[1], &x2[4], &x2[5] ); T+=step; - - r0 = x2[2] - x1[2]; x1[2] += x2[2]; - r1 = x2[3] - x1[3]; x1[3] += x2[3]; - XPROD31( r0, r1, T[0], T[1], &x2[2], &x2[3] ); T+=step; - - r0 = x2[0] - x1[0]; x1[0] += x2[0]; - r1 = x2[1] - x1[1]; x1[1] += x2[1]; - XPROD31( r0, r1, T[0], T[1], &x2[0], &x2[1] ); T+=step; - - x1-=8; x2-=8; + r0 = x1[0] - x1[1]; x1[0] += x1[1]; + r1 = x1[3] - x1[2]; x1[2] += x1[3]; + r2 = x2[1] - x2[0]; x1[1] = x2[1] + x2[0]; + r3 = x2[3] - x2[2]; x1[3] = x2[3] + x2[2]; + XPROD31( r1, r0, T[0], T[1], &x2[0], &x2[2] ); + XPROD31( r2, r3, T[0], T[1], &x2[1], &x2[3] ); T+=step; + x1-=4; + x2-=4; }while(T<sincos_lookup0+1024); do{ - r0 = x1[6] - x2[6]; x1[6] += x2[6]; - r1 = x2[7] - x1[7]; x1[7] += x2[7]; - XNPROD31( r1, r0, T[0], T[1], &x2[6], &x2[7] ); T-=step; - - r0 = x1[4] - x2[4]; x1[4] += x2[4]; - r1 = x2[5] - x1[5]; x1[5] += x2[5]; - XNPROD31( r1, r0, T[0], T[1], &x2[4], &x2[5] ); T-=step; - - r0 = x1[2] - x2[2]; x1[2] += x2[2]; - r1 = x2[3] - x1[3]; x1[3] += x2[3]; - XNPROD31( r1, r0, T[0], T[1], &x2[2], &x2[3] ); T-=step; - - r0 = x1[0] - x2[0]; x1[0] += x2[0]; - r1 = x2[1] - x1[1]; x1[1] += x2[1]; - XNPROD31( r1, r0, T[0], T[1], &x2[0], &x2[1] ); T-=step; - - x1-=8; x2-=8; + r0 = x1[0] - x1[1]; x1[0] += x1[1]; + r1 = x1[2] - x1[3]; x1[2] += x1[3]; + r2 = x2[0] - x2[1]; x1[1] = x2[1] + x2[0]; + r3 = x2[3] - x2[2]; x1[3] = x2[3] + x2[2]; + XNPROD31( r0, r1, T[0], T[1], &x2[0], &x2[2] ); + XNPROD31( r3, r2, T[0], T[1], &x2[1], &x2[3] ); T-=step; + x1-=4; + x2-=4; }while(T>sincos_lookup0); } @@ -235,15 +205,14 @@ STIN void mdct_butterflies(DATA_TYPE *x,int points,int shift){ int stages=8-shift; int i,j; - + for(i=0;--stages>0;i++){ for(j=0;j<(1<<i);j++) mdct_butterfly_generic(x+(points>>i)*j,points>>i,4<<(i+shift)); } - + for(j=0;j<points;j+=32) mdct_butterfly_32(x+j); - } static unsigned char bitrev[16]={0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; @@ -252,259 +221,266 @@ STIN int bitrev12(int x){ return bitrev[x>>8]|(bitrev[(x&0x0f0)>>4]<<4)|(((int)bitrev[x&0x00f])<<8); } -STIN void mdct_bitreverse(DATA_TYPE *x,int n,int step,int shift){ - +STIN void mdct_bitreverse(DATA_TYPE *x,int n,int shift){ int bit = 0; + DATA_TYPE *w = x+(n>>1); + + do{ + DATA_TYPE b = bitrev12(bit++); + DATA_TYPE *xx = x + (b>>shift); + REG_TYPE r; + + w -= 2; + + if(w>xx){ + + r = xx[0]; + xx[0] = w[0]; + w[0] = r; + + r = xx[1]; + xx[1] = w[1]; + w[1] = r; + } + }while(w>x); +} + +STIN void mdct_step7(DATA_TYPE *x,int n,int step){ DATA_TYPE *w0 = x; - DATA_TYPE *w1 = x = w0+(n>>1); + DATA_TYPE *w1 = x+(n>>1); LOOKUP_T *T = (step>=4)?(sincos_lookup0+(step>>1)):sincos_lookup1; LOOKUP_T *Ttop = T+1024; - DATA_TYPE r2; - + REG_TYPE r0, r1, r2, r3; + do{ - DATA_TYPE r3 = bitrev12(bit++); - DATA_TYPE *x0 = x + ((r3 ^ 0xfff)>>shift) -1; - DATA_TYPE *x1 = x + (r3>>shift); + w1 -= 2; - REG_TYPE r0 = x0[0] + x1[0]; - REG_TYPE r1 = x1[1] - x0[1]; + r0 = w0[0] + w1[0]; + r1 = w1[1] - w0[1]; + r2 = MULT32(r0, T[1]) + MULT32(r1, T[0]); + r3 = MULT32(r1, T[1]) - MULT32(r0, T[0]); + T+=step; - XPROD32( r0, r1, T[1], T[0], &r2, &r3 ); T+=step; - - w1 -= 4; - - r0 = (x0[1] + x1[1])>>1; - r1 = (x0[0] - x1[0])>>1; + r0 = (w0[1] + w1[1])>>1; + r1 = (w0[0] - w1[0])>>1; w0[0] = r0 + r2; w0[1] = r1 + r3; - w1[2] = r0 - r2; - w1[3] = r3 - r1; - - r3 = bitrev12(bit++); - x0 = x + ((r3 ^ 0xfff)>>shift) -1; - x1 = x + (r3>>shift); - - r0 = x0[0] + x1[0]; - r1 = x1[1] - x0[1]; - - XPROD32( r0, r1, T[1], T[0], &r2, &r3 ); T+=step; - - r0 = (x0[1] + x1[1])>>1; - r1 = (x0[0] - x1[0])>>1; - w0[2] = r0 + r2; - w0[3] = r1 + r3; w1[0] = r0 - r2; w1[1] = r3 - r1; - w0 += 4; + w0 += 2; }while(T<Ttop); do{ - DATA_TYPE r3 = bitrev12(bit++); - DATA_TYPE *x0 = x + ((r3 ^ 0xfff)>>shift) -1; - DATA_TYPE *x1 = x + (r3>>shift); - - REG_TYPE r0 = x0[0] + x1[0]; - REG_TYPE r1 = x1[1] - x0[1]; + w1 -= 2; - T-=step; XPROD32( r0, r1, T[0], T[1], &r2, &r3 ); + r0 = w0[0] + w1[0]; + r1 = w1[1] - w0[1]; + T-=step; + r2 = MULT32(r0, T[0]) + MULT32(r1, T[1]); + r3 = MULT32(r1, T[0]) - MULT32(r0, T[1]); - w1 -= 4; - - r0 = (x0[1] + x1[1])>>1; - r1 = (x0[0] - x1[0])>>1; + r0 = (w0[1] + w1[1])>>1; + r1 = (w0[0] - w1[0])>>1; w0[0] = r0 + r2; w0[1] = r1 + r3; - w1[2] = r0 - r2; - w1[3] = r3 - r1; - - r3 = bitrev12(bit++); - x0 = x + ((r3 ^ 0xfff)>>shift) -1; - x1 = x + (r3>>shift); - - r0 = x0[0] + x1[0]; - r1 = x1[1] - x0[1]; - - T-=step; XPROD32( r0, r1, T[0], T[1], &r2, &r3 ); - - r0 = (x0[1] + x1[1])>>1; - r1 = (x0[0] - x1[0])>>1; - w0[2] = r0 + r2; - w0[3] = r1 + r3; w1[0] = r0 - r2; w1[1] = r3 - r1; - w0 += 4; + w0 += 2; }while(w0<w1); } -void mdct_backward(int n, DATA_TYPE *in, DATA_TYPE *out){ - int n2=n>>1; - int n4=n>>2; - DATA_TYPE *iX; - DATA_TYPE *oX; +STIN void mdct_step8(DATA_TYPE *x, int n, int step){ LOOKUP_T *T; LOOKUP_T *V; + DATA_TYPE *iX =x+(n>>1); + step>>=2; + + switch(step) { + default: + T=(step>=4)?(sincos_lookup0+(step>>1)):sincos_lookup1; + do{ + REG_TYPE r0 = x[0]; + REG_TYPE r1 = -x[1]; + XPROD31( r0, r1, T[0], T[1], x, x+1); T+=step; + x +=2; + }while(x<iX); + break; + + case 1: + { + /* linear interpolation between table values: offset=0.5, step=1 */ + REG_TYPE t0,t1,v0,v1,r0,r1; + T = sincos_lookup0; + V = sincos_lookup1; + t0 = (*T++)>>1; + t1 = (*T++)>>1; + do{ + r0 = x[0]; + r1 = -x[1]; + t0 += (v0 = (*V++)>>1); + t1 += (v1 = (*V++)>>1); + XPROD31( r0, r1, t0, t1, x, x+1 ); + + r0 = x[2]; + r1 = -x[3]; + v0 += (t0 = (*T++)>>1); + v1 += (t1 = (*T++)>>1); + XPROD31( r0, r1, v0, v1, x+2, x+3 ); + + x += 4; + }while(x<iX); + break; + } + + case 0: + { + /* linear interpolation between table values: offset=0.25, step=0.5 */ + REG_TYPE t0,t1,v0,v1,q0,q1,r0,r1; + T = sincos_lookup0; + V = sincos_lookup1; + t0 = *T++; + t1 = *T++; + do{ + + + v0 = *V++; + v1 = *V++; + t0 += (q0 = (v0-t0)>>2); + t1 += (q1 = (v1-t1)>>2); + r0 = x[0]; + r1 = -x[1]; + XPROD31( r0, r1, t0, t1, x, x+1 ); + t0 = v0-q0; + t1 = v1-q1; + r0 = x[2]; + r1 = -x[3]; + XPROD31( r0, r1, t0, t1, x+2, x+3 ); + + t0 = *T++; + t1 = *T++; + v0 += (q0 = (t0-v0)>>2); + v1 += (q1 = (t1-v1)>>2); + r0 = x[4]; + r1 = -x[5]; + XPROD31( r0, r1, v0, v1, x+4, x+5 ); + v0 = t0-q0; + v1 = t1-q1; + r0 = x[6]; + r1 = -x[7]; + XPROD31( r0, r1, v0, v1, x+5, x+6 ); + + x+=8; + }while(x<iX); + break; + } + } +} + +/* partial; doesn't perform last-step deinterleave/unrolling. That + can be done more efficiently during pcm output */ +void mdct_backward(int n, DATA_TYPE *in){ int shift; int step; - - for (shift=6;!(n&(1<<shift));shift++); + + for (shift=4;!(n&(1<<shift));shift++); shift=13-shift; step=2<<shift; - /* rotate */ - - iX = in+n2-7; - oX = out+n2+n4; - T = sincos_lookup0; - - do{ - oX-=4; - XPROD31( iX[4], iX[6], T[0], T[1], &oX[2], &oX[3] ); T+=step; - XPROD31( iX[0], iX[2], T[0], T[1], &oX[0], &oX[1] ); T+=step; - iX-=8; - }while(iX>=in+n4); - do{ - oX-=4; - XPROD31( iX[4], iX[6], T[1], T[0], &oX[2], &oX[3] ); T-=step; - XPROD31( iX[0], iX[2], T[1], T[0], &oX[0], &oX[1] ); T-=step; - iX-=8; - }while(iX>=in); - - iX = in+n2-8; - oX = out+n2+n4; - T = sincos_lookup0; - - do{ - T+=step; XNPROD31( iX[6], iX[4], T[0], T[1], &oX[0], &oX[1] ); - T+=step; XNPROD31( iX[2], iX[0], T[0], T[1], &oX[2], &oX[3] ); - iX-=8; - oX+=4; - }while(iX>=in+n4); - do{ - T-=step; XNPROD31( iX[6], iX[4], T[1], T[0], &oX[0], &oX[1] ); - T-=step; XNPROD31( iX[2], iX[0], T[1], T[0], &oX[2], &oX[3] ); - iX-=8; - oX+=4; - }while(iX>=in); + presymmetry(in,n>>1,step); + mdct_butterflies(in,n>>1,shift); + mdct_bitreverse(in,n,shift); + mdct_step7(in,n,step); + mdct_step8(in,n,step); +} - mdct_butterflies(out+n2,n2,shift); - mdct_bitreverse(out,n,step,shift); +void mdct_shift_right(int n, DATA_TYPE *in, DATA_TYPE *right){ + int i; + n>>=2; + in+=1; - /* rotate + window */ + for(i=0;i<n;i++) + right[i]=in[i<<1]; +} - step>>=2; - { - DATA_TYPE *oX1=out+n2+n4; - DATA_TYPE *oX2=out+n2+n4; - DATA_TYPE *iX =out; - - switch(step) { - default: { - T=(step>=4)?(sincos_lookup0+(step>>1)):sincos_lookup1; - do{ - oX1-=4; - XPROD31( iX[0], -iX[1], T[0], T[1], &oX1[3], &oX2[0] ); T+=step; - XPROD31( iX[2], -iX[3], T[0], T[1], &oX1[2], &oX2[1] ); T+=step; - XPROD31( iX[4], -iX[5], T[0], T[1], &oX1[1], &oX2[2] ); T+=step; - XPROD31( iX[6], -iX[7], T[0], T[1], &oX1[0], &oX2[3] ); T+=step; - oX2+=4; - iX+=8; - }while(iX<oX1); - break; - } - - case 1: { - /* linear interpolation between table values: offset=0.5, step=1 */ - REG_TYPE t0,t1,v0,v1; - T = sincos_lookup0; - V = sincos_lookup1; - t0 = (*T++)>>1; - t1 = (*T++)>>1; - do{ - oX1-=4; - - t0 += (v0 = (*V++)>>1); - t1 += (v1 = (*V++)>>1); - XPROD31( iX[0], -iX[1], t0, t1, &oX1[3], &oX2[0] ); - v0 += (t0 = (*T++)>>1); - v1 += (t1 = (*T++)>>1); - XPROD31( iX[2], -iX[3], v0, v1, &oX1[2], &oX2[1] ); - t0 += (v0 = (*V++)>>1); - t1 += (v1 = (*V++)>>1); - XPROD31( iX[4], -iX[5], t0, t1, &oX1[1], &oX2[2] ); - v0 += (t0 = (*T++)>>1); - v1 += (t1 = (*T++)>>1); - XPROD31( iX[6], -iX[7], v0, v1, &oX1[0], &oX2[3] ); - - oX2+=4; - iX+=8; - }while(iX<oX1); - break; - } - - case 0: { - /* linear interpolation between table values: offset=0.25, step=0.5 */ - REG_TYPE t0,t1,v0,v1,q0,q1; - T = sincos_lookup0; - V = sincos_lookup1; - t0 = *T++; - t1 = *T++; - do{ - oX1-=4; - - v0 = *V++; - v1 = *V++; - t0 += (q0 = (v0-t0)>>2); - t1 += (q1 = (v1-t1)>>2); - XPROD31( iX[0], -iX[1], t0, t1, &oX1[3], &oX2[0] ); - t0 = v0-q0; - t1 = v1-q1; - XPROD31( iX[2], -iX[3], t0, t1, &oX1[2], &oX2[1] ); - - t0 = *T++; - t1 = *T++; - v0 += (q0 = (t0-v0)>>2); - v1 += (q1 = (t1-v1)>>2); - XPROD31( iX[4], -iX[5], v0, v1, &oX1[1], &oX2[2] ); - v0 = t0-q0; - v1 = t1-q1; - XPROD31( iX[6], -iX[7], v0, v1, &oX1[0], &oX2[3] ); - - oX2+=4; - iX+=8; - }while(iX<oX1); - break; - } +void mdct_unroll_lap(int n0,int n1, + int lW,int W, + DATA_TYPE *in, + DATA_TYPE *right, + LOOKUP_T *w0, + LOOKUP_T *w1, + tremor_ogg_int16_t *out, + int step, + int start, /* samples, this frame */ + int end /* samples, this frame */){ + + DATA_TYPE *l=in+(W&&lW ? n1>>1 : n0>>1); + DATA_TYPE *r=right+(lW ? n1>>2 : n0>>2); + DATA_TYPE *post; + LOOKUP_T *wR=(W && lW ? w1+(n1>>1) : w0+(n0>>1)); + LOOKUP_T *wL=(W && lW ? w1 : w0 ); + + int preLap=(lW && !W ? (n1>>2)-(n0>>2) : 0 ); + int halfLap=(lW && W ? (n1>>2) : (n0>>2) ); + int postLap=(!lW && W ? (n1>>2)-(n0>>2) : 0 ); + int n,off; + + /* preceeding direct-copy lapping from previous frame, if any */ + if(preLap){ + n = (end<preLap?end:preLap); + off = (start<preLap?start:preLap); + post = r-n; + r -= off; + start -= off; + end -= n; + while(r>post){ + *out = CLIP_TO_15((*--r)>>9); + out+=step; } + } + + /* cross-lap; two halves due to wrap-around */ + n = (end<halfLap?end:halfLap); + off = (start<halfLap?start:halfLap); + post = r-n; + r -= off; + l -= off*2; + start -= off; + wR -= off; + wL += off; + end -= n; + while(r>post){ + l-=2; + *out = CLIP_TO_15((MULT31(*--r,*--wR) + MULT31(*l,*wL++))>>9); + out+=step; + } - iX=out+n2+n4; - oX1=out+n4; - oX2=oX1; - - do{ - oX1-=4; - iX-=4; - - oX2[0] = -(oX1[3] = iX[3]); - oX2[1] = -(oX1[2] = iX[2]); - oX2[2] = -(oX1[1] = iX[1]); - oX2[3] = -(oX1[0] = iX[0]); - - oX2+=4; - }while(oX2<iX); - - iX=out+n2+n4; - oX1=out+n2+n4; - oX2=out+n2; + n = (end<halfLap?end:halfLap); + off = (start<halfLap?start:halfLap); + post = r+n; + r += off; + l += off*2; + start -= off; + end -= n; + wR -= off; + wL += off; + while(r<post){ + *out = CLIP_TO_15((MULT31(*r++,*--wR) - MULT31(*l,*wL++))>>9); + out+=step; + l+=2; + } - do{ - oX1-=4; - oX1[0]= iX[3]; - oX1[1]= iX[2]; - oX1[2]= iX[1]; - oX1[3]= iX[0]; - iX+=4; - }while(oX1>oX2); + /* preceeding direct-copy lapping from previous frame, if any */ + if(postLap){ + n = (end<postLap?end:postLap); + off = (start<postLap?start:postLap); + post = l+n*2; + l += off*2; + while(l<post){ + *out = CLIP_TO_15((-*l)>>9); + out+=step; + l+=2; + } } } diff --git a/lib/tremor/mdct.h b/lib/tremor/mdct.h index 6d889072..3ddb8495 100644 --- a/lib/tremor/mdct.h +++ b/lib/tremor/mdct.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -21,8 +21,8 @@ #include "ivorbiscodec.h" #include "misc.h" -#define DATA_TYPE ogg_int32_t -#define REG_TYPE register ogg_int32_t +#define DATA_TYPE tremor_ogg_int32_t +#define REG_TYPE register tremor_ogg_int32_t #ifdef _LOW_ACCURACY_ #define cPI3_8 (0x0062) @@ -34,8 +34,15 @@ #define cPI1_8 (0x7641af3d) #endif -extern void mdct_forward(int n, DATA_TYPE *in, DATA_TYPE *out); -extern void mdct_backward(int n, DATA_TYPE *in, DATA_TYPE *out); +extern void mdct_backward(int n, DATA_TYPE *in); +extern void mdct_shift_right(int n, DATA_TYPE *in, DATA_TYPE *right); +extern void mdct_unroll_lap(int n0,int n1, + int lW,int W, + DATA_TYPE *in,DATA_TYPE *right, + LOOKUP_T *w0,LOOKUP_T *w1, + tremor_ogg_int16_t *out, + int step, + int start,int end /* samples, this frame */); #endif diff --git a/lib/tremor/mdct_lookup.h b/lib/tremor/mdct_lookup.h index ee4f101c..16a988e4 100644 --- a/lib/tremor/mdct_lookup.h +++ b/lib/tremor/mdct_lookup.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -15,10 +15,10 @@ ********************************************************************/ -#include "misc.h" +#include "os_types.h" /* {sin(2*i*PI/4096), cos(2*i*PI/4096)}, with i = 0 to 512 */ -static const LOOKUP_T sincos_lookup0[1026] = { +static LOOKUP_T sincos_lookup0[1026] = { X(0x00000000), X(0x7fffffff), X(0x003243f5), X(0x7ffff621), X(0x006487e3), X(0x7fffd886), X(0x0096cbc1), X(0x7fffa72c), X(0x00c90f88), X(0x7fff6216), X(0x00fb5330), X(0x7fff0943), @@ -279,7 +279,7 @@ static const LOOKUP_T sincos_lookup0[1026] = { }; /* {sin((2*i+1)*PI/4096), cos((2*i+1)*PI/4096)}, with i = 0 to 511 */ -static const LOOKUP_T sincos_lookup1[1024] = { +static LOOKUP_T sincos_lookup1[1024] = { X(0x001921fb), X(0x7ffffd88), X(0x004b65ee), X(0x7fffe9cb), X(0x007da9d4), X(0x7fffc251), X(0x00afeda8), X(0x7fff8719), X(0x00e23160), X(0x7fff3824), X(0x011474f6), X(0x7ffed572), diff --git a/lib/tremor/misc.c b/lib/tremor/misc.c new file mode 100644 index 00000000..8833e13c --- /dev/null +++ b/lib/tremor/misc.c @@ -0,0 +1,208 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE TremorOggVorbis 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 TremorOggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + * * + ********************************************************************/ + +#define HEAD_ALIGN 64 +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#define MISC_C +#include "misc.h" +#include <sys/time.h> + +static void **pointers=NULL; +static long *insertlist=NULL; /* We can't embed this in the pointer list; + a pointer can have any value... */ + +static char **files=NULL; +static long *file_bytes=NULL; +static int filecount=0; + +static int ptop=0; +static int palloced=0; +static int pinsert=0; + +typedef struct { + char *file; + long line; + long ptr; + long bytes; +} head; + +long global_bytes=0; +long start_time=-1; + +static void *_insert(void *ptr,long bytes,char *file,long line){ + ((head *)ptr)->file=file; + ((head *)ptr)->line=line; + ((head *)ptr)->ptr=pinsert; + ((head *)ptr)->bytes=bytes-HEAD_ALIGN; + + if(pinsert>=palloced){ + palloced+=64; + if(pointers){ + pointers=(void **)realloc(pointers,sizeof(void **)*palloced); + insertlist=(long *)realloc(insertlist,sizeof(long *)*palloced); + }else{ + pointers=(void **)malloc(sizeof(void **)*palloced); + insertlist=(long *)malloc(sizeof(long *)*palloced); + } + } + + pointers[pinsert]=ptr; + + if(pinsert==ptop) + pinsert=++ptop; + else + pinsert=insertlist[pinsert]; + +#ifdef _VDBG_GRAPHFILE + { + FILE *out; + struct timeval tv; + static struct timezone tz; + int i; + char buffer[80]; + gettimeofday(&tv,&tz); + + for(i=0;i<filecount;i++) + if(!strcmp(file,files[i]))break; + + if(i==filecount){ + filecount++; + if(!files){ + files=malloc(filecount*sizeof(*files)); + file_bytes=malloc(filecount*sizeof(*file_bytes)); + }else{ + files=realloc(files,filecount*sizeof(*files)); + file_bytes=realloc(file_bytes,filecount*sizeof(*file_bytes)); + } + files[i]=strdup(file); + file_bytes[i]=0; + } + + file_bytes[i]+=bytes-HEAD_ALIGN; + + if(start_time==-1)start_time=(tv.tv_sec*1000)+(tv.tv_usec/1000); + + snprintf(buffer,80,"%s",file); + if(strchr(buffer,'.'))strchr(buffer,'.')[0]=0; + strcat(buffer,_VDBG_GRAPHFILE); + out=fopen(buffer,"a"); + fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000), + file_bytes[i]-(bytes-HEAD_ALIGN)); + fprintf(out,"%ld, %ld # FILE %s LINE %ld\n", + -start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000), + file_bytes[i],file,line); + fclose(out); + + out=fopen("total"_VDBG_GRAPHFILE,"a"); + fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000), + global_bytes); + fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000), + global_bytes+(bytes-HEAD_ALIGN)); + fclose(out); + } +#endif + + global_bytes+=(bytes-HEAD_ALIGN); + + return(ptr+HEAD_ALIGN); +} + +static void _ripremove(void *ptr){ + int insert; + +#ifdef _VDBG_GRAPHFILE + { + FILE *out=fopen("total"_VDBG_GRAPHFILE,"a"); + struct timeval tv; + static struct timezone tz; + char buffer[80]; + char *file =((head *)ptr)->file; + long bytes =((head *)ptr)->bytes; + int i; + + gettimeofday(&tv,&tz); + fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000), + global_bytes); + fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000), + global_bytes-((head *)ptr)->bytes); + fclose(out); + + for(i=0;i<filecount;i++) + if(!strcmp(file,files[i]))break; + + snprintf(buffer,80,"%s",file); + if(strchr(buffer,'.'))strchr(buffer,'.')[0]=0; + strcat(buffer,_VDBG_GRAPHFILE); + out=fopen(buffer,"a"); + fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000), + file_bytes[i]); + fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000), + file_bytes[i]-bytes); + fclose(out); + + file_bytes[i]-=bytes; + + } +#endif + + global_bytes-=((head *)ptr)->bytes; + + insert=((head *)ptr)->ptr; + insertlist[insert]=pinsert; + pinsert=insert; + + if(pointers[insert]==NULL){ + fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing previously freed memory\n"); + fprintf(stderr,"\t%s %ld\n",((head *)ptr)->file,((head *)ptr)->line); + } + + if(global_bytes<0){ + fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing unmalloced memory\n"); + } + + pointers[insert]=NULL; +} + +void _VDBG_dump(void){ + int i; + for(i=0;i<ptop;i++){ + head *ptr=pointers[i]; + if(ptr) + fprintf(stderr,"unfreed bytes from %s:%ld\n", + ptr->file,ptr->line); + } + +} + +extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line){ + bytes+=HEAD_ALIGN; + if(ptr){ + ptr-=HEAD_ALIGN; + _ripremove(ptr); + ptr=realloc(ptr,bytes); + }else{ + ptr=malloc(bytes); + memset(ptr,0,bytes); + } + return _insert(ptr,bytes,file,line); +} + +extern void _VDBG_free(void *ptr,char *file,long line){ + if(ptr){ + ptr-=HEAD_ALIGN; + _ripremove(ptr); + free(ptr); + } +} + diff --git a/lib/tremor/misc.h b/lib/tremor/misc.h index 1ae4d2e8..d818e183 100644 --- a/lib/tremor/misc.h +++ b/lib/tremor/misc.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,18 +18,27 @@ #ifndef _V_RANDOM_H_ #define _V_RANDOM_H_ #include "ivorbiscodec.h" -#include "os.h" +#include "os_types.h" -#ifdef _LOW_ACCURACY_ -# define X(n) (((((n)>>22)+1)>>1) - ((((n)>>22)+1)>>9)) -# define LOOKUP_T const unsigned char -#else -# define X(n) (n) -# define LOOKUP_T const ogg_int32_t +/*#define _VDBG_GRAPHFILE "_0.m"*/ + + +#ifdef _VDBG_GRAPHFILE +extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line); +extern void _VDBG_free(void *ptr,char *file,long line); + +#undef _tremor_ogg_malloc +#undef _tremor_ogg_calloc +#undef _tremor_ogg_realloc +#undef _tremor_ogg_free + +#define _tremor_ogg_malloc(x) _VDBG_malloc(NULL,(x),__FILE__,__LINE__) +#define _tremor_ogg_calloc(x,y) _VDBG_malloc(NULL,(x)*(y),__FILE__,__LINE__) +#define _tremor_ogg_realloc(x,y) _VDBG_malloc((x),(y),__FILE__,__LINE__) +#define _tremor_ogg_free(x) _VDBG_free((x),__FILE__,__LINE__) #endif #include "asm_arm.h" -#include <stdlib.h> /* for abs() */ #ifndef _V_WIDE_MATH #define _V_WIDE_MATH @@ -37,44 +46,42 @@ #ifndef _LOW_ACCURACY_ /* 64 bit multiply */ -#if !(defined WIN32 && defined WINCE) #include <sys/types.h> -#endif #if BYTE_ORDER==LITTLE_ENDIAN union magic { struct { - ogg_int32_t lo; - ogg_int32_t hi; + tremor_ogg_int32_t lo; + tremor_ogg_int32_t hi; } halves; - ogg_int64_t whole; + tremor_ogg_int64_t whole; }; #endif #if BYTE_ORDER==BIG_ENDIAN union magic { struct { - ogg_int32_t hi; - ogg_int32_t lo; + tremor_ogg_int32_t hi; + tremor_ogg_int32_t lo; } halves; - ogg_int64_t whole; + tremor_ogg_int64_t whole; }; #endif -STIN ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT32(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { union magic magic; - magic.whole = (ogg_int64_t)x * y; + magic.whole = (tremor_ogg_int64_t)x * y; return magic.halves.hi; } -STIN ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT31(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { return MULT32(x,y)<<1; } -STIN ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT31_SHIFT15(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { union magic magic; - magic.whole = (ogg_int64_t)x * y; - return ((ogg_uint32_t)(magic.halves.lo)>>15) | ((magic.halves.hi)<<17); + magic.whole = (tremor_ogg_int64_t)x * y; + return ((tremor_ogg_uint32_t)(magic.halves.lo)>>15) | ((magic.halves.hi)<<17); } #else @@ -93,15 +100,15 @@ STIN ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { * tables in this case. */ -STIN ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT32(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { return (x >> 9) * y; /* y preshifted >>23 */ } -STIN ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT31(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { return (x >> 8) * y; /* y preshifted >>23 */ } -STIN ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { +static inline tremor_ogg_int32_t MULT31_SHIFT15(tremor_ogg_int32_t x, tremor_ogg_int32_t y) { return (x >> 6) * y; /* y preshifted >>9 */ } @@ -138,25 +145,25 @@ STIN ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { #else -STIN void XPROD32(ogg_int32_t a, ogg_int32_t b, - ogg_int32_t t, ogg_int32_t v, - ogg_int32_t *x, ogg_int32_t *y) +static inline void XPROD32(tremor_ogg_int32_t a, tremor_ogg_int32_t b, + tremor_ogg_int32_t t, tremor_ogg_int32_t v, + tremor_ogg_int32_t *x, tremor_ogg_int32_t *y) { *x = MULT32(a, t) + MULT32(b, v); *y = MULT32(b, t) - MULT32(a, v); } -STIN void XPROD31(ogg_int32_t a, ogg_int32_t b, - ogg_int32_t t, ogg_int32_t v, - ogg_int32_t *x, ogg_int32_t *y) +static inline void XPROD31(tremor_ogg_int32_t a, tremor_ogg_int32_t b, + tremor_ogg_int32_t t, tremor_ogg_int32_t v, + tremor_ogg_int32_t *x, tremor_ogg_int32_t *y) { *x = MULT31(a, t) + MULT31(b, v); *y = MULT31(b, t) - MULT31(a, v); } -STIN void XNPROD31(ogg_int32_t a, ogg_int32_t b, - ogg_int32_t t, ogg_int32_t v, - ogg_int32_t *x, ogg_int32_t *y) +static inline void XNPROD31(tremor_ogg_int32_t a, tremor_ogg_int32_t b, + tremor_ogg_int32_t t, tremor_ogg_int32_t v, + tremor_ogg_int32_t *x, tremor_ogg_int32_t *y) { *x = MULT31(a, t) - MULT31(b, v); *y = MULT31(b, t) + MULT31(a, v); @@ -169,7 +176,7 @@ STIN void XNPROD31(ogg_int32_t a, ogg_int32_t b, #ifndef _V_CLIP_MATH #define _V_CLIP_MATH -STIN ogg_int32_t CLIP_TO_15(ogg_int32_t x) { +static inline tremor_ogg_int32_t CLIP_TO_15(tremor_ogg_int32_t x) { int ret=x; ret-= ((x<=32767)-1)&(x-32767); ret-= ((x>=-32768)-1)&(x+32768); @@ -178,73 +185,6 @@ STIN ogg_int32_t CLIP_TO_15(ogg_int32_t x) { #endif -STIN ogg_int32_t VFLOAT_MULT(ogg_int32_t a,ogg_int32_t ap, - ogg_int32_t b,ogg_int32_t bp, - ogg_int32_t *p){ - if(a && b){ -#ifndef _LOW_ACCURACY_ - *p=ap+bp+32; - return MULT32(a,b); -#else - *p=ap+bp+31; - return (a>>15)*(b>>16); -#endif - }else - return 0; -} - -int _ilog(unsigned int); - -STIN ogg_int32_t VFLOAT_MULTI(ogg_int32_t a,ogg_int32_t ap, - ogg_int32_t i, - ogg_int32_t *p){ - - int ip=_ilog(abs(i))-31; - return VFLOAT_MULT(a,ap,i<<-ip,ip,p); -} - -STIN ogg_int32_t VFLOAT_ADD(ogg_int32_t a,ogg_int32_t ap, - ogg_int32_t b,ogg_int32_t bp, - ogg_int32_t *p){ - - if(!a){ - *p=bp; - return b; - }else if(!b){ - *p=ap; - return a; - } - - /* yes, this can leak a bit. */ - if(ap>bp){ - int shift=ap-bp+1; - *p=ap+1; - a>>=1; - if(shift<32){ - b=(b+(1<<(shift-1)))>>shift; - }else{ - b=0; - } - }else{ - int shift=bp-ap+1; - *p=bp+1; - b>>=1; - if(shift<32){ - a=(a+(1<<(shift-1)))>>shift; - }else{ - a=0; - } - } - - a+=b; - if((a&0xc0000000)==0xc0000000 || - (a&0xc0000000)==0){ - a<<=1; - (*p)--; - } - return(a); -} - #endif diff --git a/lib/tremor/os.h b/lib/tremor/os.h index 130d27de..5a556fd9 100644 --- a/lib/tremor/os.h +++ b/lib/tremor/os.h @@ -2,13 +2,13 @@ #define _OS_H /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,7 +18,7 @@ ********************************************************************/ #include <math.h> -#include <ogg/os_types.h> +#include "os_types.h" #ifndef _V_IFDEFJAIL_H_ # define _V_IFDEFJAIL_H_ @@ -41,8 +41,6 @@ # define rint(x) (floor((x)+0.5f)) # define NO_FLOAT_MATH_LIB # define FAST_HYPOT(a, b) sqrt((a)*(a) + (b)*(b)) -# define LITTLE_ENDIAN 1 -# define BYTE_ORDER LITTLE_ENDIAN #endif #ifdef HAVE_ALLOCA_H diff --git a/lib/tremor/os_types.h b/lib/tremor/os_types.h new file mode 100644 index 00000000..c09c993d --- /dev/null +++ b/lib/tremor/os_types.h @@ -0,0 +1,42 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + + ********************************************************************/ +#ifndef _TREMOR_OS_TYPES_H +#define _TREMOR_OS_TYPES_H + +#include <stdint.h> +#ifdef _LOW_ACCURACY_ +# define X(n) (((((n)>>22)+1)>>1) - ((((n)>>22)+1)>>9)) +# define LOOKUP_T const unsigned char +#else +# define X(n) (n) +# define LOOKUP_T const tremor_ogg_int32_t +#endif + +/* make it easy on the folks that want to compile the libs with a + different malloc than stdlib */ +#define _tremor_ogg_malloc malloc +#define _tremor_ogg_calloc calloc +#define _tremor_ogg_realloc realloc +#define _tremor_ogg_free free + +typedef int64_t tremor_ogg_int64_t; +typedef int32_t tremor_ogg_int32_t; +typedef uint32_t tremor_ogg_uint32_t; +typedef int16_t tremor_ogg_int16_t; +typedef uint16_t tremor_ogg_uint16_t; + +#endif /* _TREMOR_OS_TYPES_H */ diff --git a/lib/tremor/registry.c b/lib/tremor/registry.c deleted file mode 100644 index c0b5fec0..00000000 --- a/lib/tremor/registry.c +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: registry for floor, res backends and channel mappings - - ********************************************************************/ - -#include "ivorbiscodec.h" -#include "codec_internal.h" -#include "registry.h" -#include "misc.h" - - -/* seems like major overkill now; the backend numbers will grow into - the infrastructure soon enough */ - -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_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, -}; - - - diff --git a/lib/tremor/registry.h b/lib/tremor/registry.h deleted file mode 100644 index 2bc8068f..00000000 --- a/lib/tremor/registry.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: registry for time, floor, res backends and channel mappings - - ********************************************************************/ - -#ifndef _V_REG_H_ -#define _V_REG_H_ - -#define VI_TRANSFORMB 1 -#define VI_WINDOWB 1 -#define VI_TIMEB 1 -#define VI_FLOORB 2 -#define VI_RESB 3 -#define VI_MAPB 1 - -#include "backends.h" - -#if defined(_WIN32) && defined(VORBISDLL_IMPORT) -# define EXTERN __declspec(dllimport) extern -#else -# define EXTERN extern -#endif - -EXTERN vorbis_func_floor *_floor_P[]; -EXTERN vorbis_func_residue *_residue_P[]; -EXTERN vorbis_func_mapping *_mapping_P[]; - -#endif diff --git a/lib/tremor/res012.c b/lib/tremor/res012.c index f036caaa..e568dc10 100644 --- a/lib/tremor/res012.c +++ b/lib/tremor/res012.c @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -18,357 +18,208 @@ #include <stdlib.h> #include <string.h> #include <math.h> -#include <ogg/ogg.h> +#include "tremor_ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" -#include "registry.h" #include "codebook.h" #include "misc.h" #include "os.h" -#include "block.h" -typedef struct { - vorbis_info_residue0 *info; - int map; - - int parts; - int stages; - codebook *fullbooks; - codebook *phrasebook; - codebook ***partbooks; - - int partvals; - int **decodemap; - -} vorbis_look_residue0; - -void res0_free_info(vorbis_info_residue *i){ - vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; +void res_clear_info(vorbis_info_residue *info){ if(info){ + if(info->stagemasks)_tremor_ogg_free(info->stagemasks); + if(info->stagebooks)_tremor_ogg_free(info->stagebooks); memset(info,0,sizeof(*info)); - _ogg_free(info); } } -void res0_free_look(vorbis_look_residue *i){ - int j; - if(i){ - - vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; - - for(j=0;j<look->parts;j++) - if(look->partbooks[j])_ogg_free(look->partbooks[j]); - _ogg_free(look->partbooks); - for(j=0;j<look->partvals;j++) - _ogg_free(look->decodemap[j]); - _ogg_free(look->decodemap); - - memset(look,0,sizeof(*look)); - _ogg_free(look); - } -} - -static int ilog(unsigned int v){ - int ret=0; - while(v){ - ret++; - v>>=1; - } - return(ret); -} - -static int icount(unsigned int v){ - int ret=0; - while(v){ - ret+=v&1; - v>>=1; - } - return(ret); -} /* vorbis_info is for range checking */ -vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ - int j,acc=0; - vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info)); +int res_unpack(vorbis_info_residue *info, + vorbis_info *vi,tremor_oggpack_buffer *opb){ + int j,k; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; + memset(info,0,sizeof(*info)); + + info->type=tremor_oggpack_read(opb,16); + if(info->type>2 || info->type<0)goto errout; + info->begin=tremor_oggpack_read(opb,24); + info->end=tremor_oggpack_read(opb,24); + info->grouping=tremor_oggpack_read(opb,24)+1; + info->partitions=tremor_oggpack_read(opb,6)+1; + info->groupbook=tremor_oggpack_read(opb,8); + if(info->groupbook>=ci->books)goto errout; - info->begin=oggpack_read(opb,24); - info->end=oggpack_read(opb,24); - info->grouping=oggpack_read(opb,24)+1; - info->partitions=oggpack_read(opb,6)+1; - info->groupbook=oggpack_read(opb,8); - - /* check for premature EOP */ - if(info->groupbook<0)goto errout; + info->stagemasks=_tremor_ogg_malloc(info->partitions*sizeof(*info->stagemasks)); + info->stagebooks=_tremor_ogg_malloc(info->partitions*8*sizeof(*info->stagebooks)); for(j=0;j<info->partitions;j++){ - int cascade=oggpack_read(opb,3); - int cflag=oggpack_read(opb,1); - if(cflag<0) goto errout; - if(cflag){ - int c=oggpack_read(opb,5); - if(c<0) goto errout; - cascade|=(c<<3); - } - info->secondstages[j]=cascade; - - acc+=icount(cascade); - } - for(j=0;j<acc;j++){ - int book=oggpack_read(opb,8); - if(book<0) goto errout; - info->booklist[j]=book; + int cascade=tremor_oggpack_read(opb,3); + if(tremor_oggpack_read(opb,1)) + cascade|=(tremor_oggpack_read(opb,5)<<3); + info->stagemasks[j]=cascade; } - if(info->groupbook>=ci->books)goto errout; - for(j=0;j<acc;j++){ - if(info->booklist[j]>=ci->books)goto errout; - if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; - } - - /* verify the phrasebook is not specifying an impossible or - inconsistent partitioning scheme. */ - /* modify the phrasebook ranging check from r16327; an early beta - encoder had a bug where it used an oversized phrasebook by - accident. These files should continue to be playable, but don't - allow an exploit */ - { - int entries = ci->book_param[info->groupbook]->entries; - int dim = ci->book_param[info->groupbook]->dim; - int partvals = 1; - if (dim<1) goto errout; - while(dim>0){ - partvals *= info->partitions; - if(partvals > entries) goto errout; - dim--; + for(j=0;j<info->partitions;j++){ + for(k=0;k<8;k++){ + if((info->stagemasks[j]>>k)&1){ + unsigned char book=tremor_oggpack_read(opb,8); + if(book>=ci->books)goto errout; + info->stagebooks[j*8+k]=book; + if(k+1>info->stages)info->stages=k+1; + }else + info->stagebooks[j*8+k]=0xff; } - info->partvals = partvals; } - return(info); + if(tremor_oggpack_eop(opb))goto errout; + + return 0; errout: - res0_free_info(info); - return(NULL); + res_clear_info(info); + return 1; } -vorbis_look_residue *res0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, - vorbis_info_residue *vr){ - vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; - vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look)); +int res_inverse(vorbis_dsp_state *vd,vorbis_info_residue *info, + tremor_ogg_int32_t **in,int *nonzero,int ch){ + + int i,j,k,s,used=0; codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; - - int j,k,acc=0; - int dim; - int maxstage=0; - look->info=info; - look->map=vm->mapping; - - look->parts=info->partitions; - look->fullbooks=ci->fullbooks; - look->phrasebook=ci->fullbooks+info->groupbook; - dim=look->phrasebook->dim; - - look->partbooks=(codebook ***)_ogg_calloc(look->parts,sizeof(*look->partbooks)); - - for(j=0;j<look->parts;j++){ - int stages=ilog(info->secondstages[j]); - if(stages){ - if(stages>maxstage)maxstage=stages; - look->partbooks[j]=(codebook **)_ogg_calloc(stages,sizeof(*look->partbooks[j])); - for(k=0;k<stages;k++) - if(info->secondstages[j]&(1<<k)){ - look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; -#ifdef TRAIN_RES - look->training_data[k][j]=calloc(look->partbooks[j][k]->entries, - sizeof(***look->training_data)); -#endif - } - } - } - - look->partvals=look->parts; - for(j=1;j<dim;j++)look->partvals*=look->parts; - look->stages=maxstage; - look->decodemap=(int **)_ogg_malloc(look->partvals*sizeof(*look->decodemap)); - for(j=0;j<look->partvals;j++){ - long val=j; - long mult=look->partvals/look->parts; - look->decodemap[j]=(int *)_ogg_malloc(dim*sizeof(*look->decodemap[j])); - for(k=0;k<dim;k++){ - long deco=val/mult; - val-=deco*mult; - mult/=look->parts; - look->decodemap[j][k]=deco; - } - } - - return(look); -} - - -/* a truncated packet here just means 'stop working'; it's not an error */ -static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, - ogg_int32_t **in,int ch, - long (*decodepart)(codebook *, ogg_int32_t *, - oggpack_buffer *,int,int)){ - - long i,j,k,l,s; - vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; - vorbis_info_residue0 *info=look->info; - - /* move all this setup out later */ + codebook *phrasebook=ci->book_param+info->groupbook; int samples_per_partition=info->grouping; - int partitions_per_word=look->phrasebook->dim; - int max=vb->pcmend>>1; - int end=(info->end<max?info->end:max); - int n=end-info->begin; + int partitions_per_word=phrasebook->dim; + int pcmend=ci->blocksizes[vd->W]; - if(n>0){ - int partvals=n/samples_per_partition; - int partwords=(partvals+partitions_per_word-1)/partitions_per_word; - int ***partword=(int ***)alloca(ch*sizeof(*partword)); - - for(j=0;j<ch;j++) - partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); + if(info->type<2){ + int max=pcmend>>1; + int end=(info->end<max?info->end:max); + int n=end-info->begin; - for(s=0;s<look->stages;s++){ + if(n>0){ + int partvals=n/samples_per_partition; + int partwords=(partvals+partitions_per_word-1)/partitions_per_word; - /* each loop decodes on partition codeword containing - partitions_pre_word partitions */ - for(i=0,l=0;i<partvals;l++){ - if(s==0){ - /* fetch the partition word for each channel */ - for(j=0;j<ch;j++){ - int temp=vorbis_book_decode(look->phrasebook,&vb->opb); - if(temp==-1 || temp>=info->partvals)goto eopbreak; - partword[j][l]=look->decodemap[temp]; - if(partword[j][l]==NULL)goto errout; - } - } + for(i=0;i<ch;i++) + if(nonzero[i]) + in[used++]=in[i]; + ch=used; + + if(used){ + + char **partword=(char **)alloca(ch*sizeof(*partword)); + for(j=0;j<ch;j++) + partword[j]=(char *)alloca(partwords*partitions_per_word* + sizeof(*partword[j])); - /* now we decode residual values for the partitions */ - for(k=0;k<partitions_per_word && i<partvals;k++,i++) - for(j=0;j<ch;j++){ - long offset=info->begin+i*samples_per_partition; - if(info->secondstages[partword[j][l][k]]&(1<<s)){ - codebook *stagebook=look->partbooks[partword[j][l][k]][s]; - if(stagebook){ - if(decodepart(stagebook,in[j]+offset,&vb->opb, - samples_per_partition,-8)==-1)goto eopbreak; + for(s=0;s<info->stages;s++){ + + for(i=0;i<partvals;){ + if(s==0){ + /* fetch the partition word for each channel */ + + partword[0][i+partitions_per_word-1]=1; + for(k=partitions_per_word-2;k>=0;k--) + partword[0][i+k]=partword[0][i+k+1]*info->partitions; + + for(j=1;j<ch;j++) + for(k=partitions_per_word-1;k>=0;k--) + partword[j][i+k]=partword[j-1][i+k]; + + for(j=0;j<ch;j++){ + int temp=vorbis_book_decode(phrasebook,&vd->opb); + if(temp==-1)goto eopbreak; + + /* this can be done quickly in assembly due to the quotient + always being at most six bits */ + for(k=0;k<partitions_per_word;k++){ + tremor_ogg_uint32_t div=partword[j][i+k]; + partword[j][i+k]=temp/div; + temp-=partword[j][i+k]*div; + } + } } + + /* now we decode residual values for the partitions */ + for(k=0;k<partitions_per_word && i<partvals;k++,i++) + for(j=0;j<ch;j++){ + long offset=info->begin+i*samples_per_partition; + if(info->stagemasks[(int)partword[j][i]]&(1<<s)){ + codebook *stagebook=ci->book_param+ + info->stagebooks[(partword[j][i]<<3)+s]; + if(info->type){ + if(vorbis_book_decodev_add(stagebook,in[j]+offset,&vd->opb, + samples_per_partition,-8)==-1) + goto eopbreak; + }else{ + if(vorbis_book_decodevs_add(stagebook,in[j]+offset,&vd->opb, + samples_per_partition,-8)==-1) + goto eopbreak; + } + } + } } - } + } + } } - } - errout: - eopbreak: - return(0); -} - -int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, - ogg_int32_t **in,int *nonzero,int ch){ - int i,used=0; - for(i=0;i<ch;i++) - if(nonzero[i]) - in[used++]=in[i]; - if(used) - return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add)); - else - return(0); -} - -int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl, - ogg_int32_t **in,int *nonzero,int ch){ - int i,used=0; - for(i=0;i<ch;i++) - if(nonzero[i]) - in[used++]=in[i]; - if(used) - return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add)); - else - return(0); -} - -/* duplicate code here as speed is somewhat more important */ -int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, - ogg_int32_t **in,int *nonzero,int ch){ - long i,k,l,s; - vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; - vorbis_info_residue0 *info=look->info; - - /* move all this setup out later */ - int samples_per_partition=info->grouping; - int partitions_per_word=look->phrasebook->dim; - int max=(vb->pcmend*ch)>>1; - int end=(info->end<max?info->end:max); - int n=end-info->begin; - - if(n>0){ + }else{ + int max=(pcmend*ch)>>1; + int end=(info->end<max?info->end:max); + int n=end-info->begin; - int partvals=n/samples_per_partition; - int partwords=(partvals+partitions_per_word-1)/partitions_per_word; - int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword)); - int beginoff=info->begin/ch; - - for(i=0;i<ch;i++)if(nonzero[i])break; - if(i==ch)return(0); /* no nonzero vectors */ - - samples_per_partition/=ch; - - for(s=0;s<look->stages;s++){ - for(i=0,l=0;i<partvals;l++){ - - if(s==0){ - /* fetch the partition word */ - int temp=vorbis_book_decode(look->phrasebook,&vb->opb); - if(temp==-1 || temp>=info->partvals)goto eopbreak; - partword[l]=look->decodemap[temp]; - if(partword[l]==NULL)goto errout; - } - - /* now we decode residual values for the partitions */ - for(k=0;k<partitions_per_word && i<partvals;k++,i++) - if(info->secondstages[partword[l][k]]&(1<<s)){ - codebook *stagebook=look->partbooks[partword[l][k]][s]; + if(n>0){ + int partvals=n/samples_per_partition; + int partwords=(partvals+partitions_per_word-1)/partitions_per_word; + + char *partword= + (char *)alloca(partwords*partitions_per_word*sizeof(*partword)); + int beginoff=info->begin/ch; + + for(i=0;i<ch;i++)if(nonzero[i])break; + if(i==ch)return(0); /* no nonzero vectors */ + + samples_per_partition/=ch; + + for(s=0;s<info->stages;s++){ + for(i=0;i<partvals;){ + + if(s==0){ + int temp; + partword[i+partitions_per_word-1]=1; + for(k=partitions_per_word-2;k>=0;k--) + partword[i+k]=partword[i+k+1]*info->partitions; - if(stagebook){ + /* fetch the partition word */ + temp=vorbis_book_decode(phrasebook,&vd->opb); + if(temp==-1)goto eopbreak; + + /* this can be done quickly in assembly due to the quotient + always being at most six bits */ + for(k=0;k<partitions_per_word;k++){ + tremor_ogg_uint32_t div=partword[i+k]; + partword[i+k]=temp/div; + temp-=partword[i+k]*div; + } + } + + /* now we decode residual values for the partitions */ + for(k=0;k<partitions_per_word && i<partvals;k++,i++) + if(info->stagemasks[(int)partword[i]]&(1<<s)){ + codebook *stagebook=ci->book_param+ + info->stagebooks[(partword[i]<<3)+s]; if(vorbis_book_decodevv_add(stagebook,in, i*samples_per_partition+beginoff,ch, - &vb->opb, + &vd->opb, samples_per_partition,-8)==-1) goto eopbreak; } - } + } } } } errout: eopbreak: - return(0); -} - - -vorbis_func_residue residue0_exportbundle={ - &res0_unpack, - &res0_look, - &res0_free_info, - &res0_free_look, - &res0_inverse -}; - -vorbis_func_residue residue1_exportbundle={ - &res0_unpack, - &res0_look, - &res0_free_info, - &res0_free_look, - &res1_inverse -}; + + return 0; +} -vorbis_func_residue residue2_exportbundle={ - &res0_unpack, - &res0_look, - &res0_free_info, - &res0_free_look, - &res2_inverse -}; diff --git a/lib/tremor/sharedbook.c b/lib/tremor/sharedbook.c deleted file mode 100644 index 188485e3..00000000 --- a/lib/tremor/sharedbook.c +++ /dev/null @@ -1,447 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: basic shared codebook operations - - ********************************************************************/ - -#include <stdlib.h> -#include <math.h> -#include <string.h> -#include <ogg/ogg.h> -#include "misc.h" -#include "ivorbiscodec.h" -#include "codebook.h" - -/**** pack/unpack helpers ******************************************/ -int _ilog(unsigned int v){ - int ret=0; - while(v){ - ret++; - v>>=1; - } - return(ret); -} - -/* 32 bit float (not IEEE; nonnormalized mantissa + - biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm - Why not IEEE? It's just not that important here. */ - -#define VQ_FEXP 10 -#define VQ_FMAN 21 -#define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */ - -static ogg_int32_t _float32_unpack(long val,int *point){ - long mant=val&0x1fffff; - int sign=val&0x80000000; - long exp =(val&0x7fe00000L)>>VQ_FMAN; - - exp-=(VQ_FMAN-1)+VQ_FEXP_BIAS; - - if(mant){ - while(!(mant&0x40000000)){ - mant<<=1; - exp-=1; - } - - if(sign)mant= -mant; - }else{ - sign=0; - exp=-9999; - } - - *point=exp; - return mant; -} - -/* given a list of word lengths, generate a list of codewords. Works - for length ordered or unordered, always assigns the lowest valued - codewords first. Extended to handle unused entries (length 0) */ -ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ - long i,j,count=0; - ogg_uint32_t marker[33]; - ogg_uint32_t *r=(ogg_uint32_t *)_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r)); - memset(marker,0,sizeof(marker)); - - for(i=0;i<n;i++){ - long length=l[i]; - if(length>0){ - ogg_uint32_t entry=marker[length]; - - /* when we claim a node for an entry, we also claim the nodes - below it (pruning off the imagined tree that may have dangled - from it) as well as blocking the use of any nodes directly - above for leaves */ - - /* update ourself */ - if(length<32 && (entry>>length)){ - /* error condition; the lengths must specify an overpopulated tree */ - _ogg_free(r); - return(NULL); - } - r[count++]=entry; - - /* Look to see if the next shorter marker points to the node - above. if so, update it and repeat. */ - { - for(j=length;j>0;j--){ - - if(marker[j]&1){ - /* have to jump branches */ - if(j==1) - marker[1]++; - else - marker[j]=marker[j-1]<<1; - break; /* invariant says next upper marker would already - have been moved if it was on the same path */ - } - marker[j]++; - } - } - - /* prune the tree; the implicit invariant says all the longer - markers were dangling from our just-taken node. Dangle them - from our *new* node. */ - for(j=length+1;j<33;j++) - if((marker[j]>>1) == entry){ - entry=marker[j]; - marker[j]=marker[j-1]<<1; - }else - break; - }else - if(sparsecount==0)count++; - } - - /* sanity check the huffman tree; an underpopulated tree must be - rejected. The only exception is the one-node pseudo-nil tree, - which appears to be underpopulated because the tree doesn't - really exist; there's only one possible 'codeword' or zero bits, - but the above tree-gen code doesn't mark that. */ - if(sparsecount != 1){ - for(i=1;i<33;i++) - if(marker[i] & (0xffffffffUL>>(32-i))){ - _ogg_free(r); - return(NULL); - } - } - - /* bitreverse the words because our bitwise packer/unpacker is LSb - endian */ - for(i=0,count=0;i<n;i++){ - ogg_uint32_t temp=0; - for(j=0;j<l[i];j++){ - temp<<=1; - temp|=(r[count]>>j)&1; - } - - if(sparsecount){ - if(l[i]) - r[count++]=temp; - }else - r[count++]=temp; - } - - return(r); -} - -/* there might be a straightforward one-line way to do the below - that's portable and totally safe against roundoff, but I haven't - thought of it. Therefore, we opt on the side of caution */ -long _book_maptype1_quantvals(const static_codebook *b){ - /* get us a starting hint, we'll polish it below */ - int bits=_ilog(b->entries); - int vals=b->entries>>((bits-1)*(b->dim-1)/b->dim); - - while(1){ - long acc=1; - long acc1=1; - int i; - for(i=0;i<b->dim;i++){ - acc*=vals; - acc1*=vals+1; - } - if(acc<=b->entries && acc1>b->entries){ - return(vals); - }else{ - if(acc>b->entries){ - vals--; - }else{ - vals++; - } - } - } -} - -/* different than what _book_unquantize does for mainline: - we repack the book in a fixed point format that shares the same - binary point. Upon first use, we can shift point if needed */ - -/* we need to deal with two map types: in map type 1, the values are - generated algorithmically (each column of the vector counts through - the values in the quant vector). in map type 2, all the values came - in in an explicit list. Both value lists must be unpacked */ - -ogg_int32_t *_book_unquantize(const static_codebook *b,int n,int *sparsemap, - int *maxpoint){ - long j,k,count=0; - if(b->maptype==1 || b->maptype==2){ - int quantvals; - int minpoint,delpoint; - ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint); - ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint); - ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r)); - int *rp=(int *)_ogg_calloc(n*b->dim,sizeof(*rp)); - - *maxpoint=minpoint; - - /* maptype 1 and 2 both use a quantized value vector, but - different sizes */ - switch(b->maptype){ - case 1: - /* most of the time, entries%dimensions == 0, but we need to be - well defined. We define that the possible vales at each - scalar is values == entries/dim. If entries%dim != 0, we'll - have 'too few' values (values*dim<entries), which means that - we'll have 'left over' entries; left over entries use zeroed - values (and are wasted). So don't generate codebooks like - that */ - quantvals=_book_maptype1_quantvals(b); - for(j=0;j<b->entries;j++){ - if((sparsemap && b->lengthlist[j]) || !sparsemap){ - ogg_int32_t last=0; - int lastpoint=0; - int indexdiv=1; - for(k=0;k<b->dim;k++){ - int index= (j/indexdiv)%quantvals; - int point=0; - int val=VFLOAT_MULTI(delta,delpoint, - abs(b->quantlist[index]),&point); - - val=VFLOAT_ADD(mindel,minpoint,val,point,&point); - val=VFLOAT_ADD(last,lastpoint,val,point,&point); - - if(b->q_sequencep){ - last=val; - lastpoint=point; - } - - if(sparsemap){ - r[sparsemap[count]*b->dim+k]=val; - rp[sparsemap[count]*b->dim+k]=point; - }else{ - r[count*b->dim+k]=val; - rp[count*b->dim+k]=point; - } - if(*maxpoint<point)*maxpoint=point; - indexdiv*=quantvals; - } - count++; - } - - } - break; - case 2: - for(j=0;j<b->entries;j++){ - if((sparsemap && b->lengthlist[j]) || !sparsemap){ - ogg_int32_t last=0; - int lastpoint=0; - - for(k=0;k<b->dim;k++){ - int point=0; - int val=VFLOAT_MULTI(delta,delpoint, - abs(b->quantlist[j*b->dim+k]),&point); - - val=VFLOAT_ADD(mindel,minpoint,val,point,&point); - val=VFLOAT_ADD(last,lastpoint,val,point,&point); - - if(b->q_sequencep){ - last=val; - lastpoint=point; - } - - if(sparsemap){ - r[sparsemap[count]*b->dim+k]=val; - rp[sparsemap[count]*b->dim+k]=point; - }else{ - r[count*b->dim+k]=val; - rp[count*b->dim+k]=point; - } - if(*maxpoint<point)*maxpoint=point; - } - count++; - } - } - break; - } - - for(j=0;j<n*b->dim;j++) - if(rp[j]<*maxpoint) - r[j]>>=*maxpoint-rp[j]; - - _ogg_free(rp); - return(r); - } - return(NULL); -} - -void vorbis_staticbook_destroy(static_codebook *b){ - if(b->quantlist)_ogg_free(b->quantlist); - if(b->lengthlist)_ogg_free(b->lengthlist); - memset(b,0,sizeof(*b)); - _ogg_free(b); -} - -void vorbis_book_clear(codebook *b){ - /* static book is not cleared; we're likely called on the lookup and - the static codebook belongs to the info struct */ - if(b->valuelist)_ogg_free(b->valuelist); - if(b->codelist)_ogg_free(b->codelist); - - if(b->dec_index)_ogg_free(b->dec_index); - if(b->dec_codelengths)_ogg_free(b->dec_codelengths); - if(b->dec_firsttable)_ogg_free(b->dec_firsttable); - - memset(b,0,sizeof(*b)); -} - -static ogg_uint32_t bitreverse(ogg_uint32_t x){ - x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL); - x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL); - x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL); - x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL); - return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL); -} - -static int sort32a(const void *a,const void *b){ - return (**(ogg_uint32_t **)a>**(ogg_uint32_t **)b)- - (**(ogg_uint32_t **)a<**(ogg_uint32_t **)b); -} - -/* decode codebook arrangement is more heavily optimized than encode */ -int vorbis_book_init_decode(codebook *c,const static_codebook *s){ - int i,j,n=0,tabn; - int *sortindex; - memset(c,0,sizeof(*c)); - - /* count actually used entries */ - for(i=0;i<s->entries;i++) - if(s->lengthlist[i]>0) - n++; - - c->entries=s->entries; - c->used_entries=n; - c->dim=s->dim; - - if(n>0){ - /* two different remappings go on here. - - First, we collapse the likely sparse codebook down only to - actually represented values/words. This collapsing needs to be - indexed as map-valueless books are used to encode original entry - positions as integers. - - Second, we reorder all vectors, including the entry index above, - by sorted bitreversed codeword to allow treeless decode. */ - - /* perform sort */ - ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); - ogg_uint32_t **codep=(ogg_uint32_t **)alloca(sizeof(*codep)*n); - - if(codes==NULL)goto err_out; - - for(i=0;i<n;i++){ - codes[i]=bitreverse(codes[i]); - codep[i]=codes+i; - } - - qsort(codep,n,sizeof(*codep),sort32a); - - sortindex=(int *)alloca(n*sizeof(*sortindex)); - c->codelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist)); - /* the index is a reverse index */ - for(i=0;i<n;i++){ - int position=codep[i]-codes; - sortindex[position]=i; - } - - for(i=0;i<n;i++) - c->codelist[sortindex[i]]=codes[i]; - _ogg_free(codes); - - - - c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint); - c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index)); - - for(n=0,i=0;i<s->entries;i++) - if(s->lengthlist[i]>0) - c->dec_index[sortindex[n++]]=i; - - c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths)); - for(n=0,i=0;i<s->entries;i++) - if(s->lengthlist[i]>0) - c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; - - c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */ - if(c->dec_firsttablen<5)c->dec_firsttablen=5; - if(c->dec_firsttablen>8)c->dec_firsttablen=8; - - tabn=1<<c->dec_firsttablen; - c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable)); - c->dec_maxlength=0; - - for(i=0;i<n;i++){ - if(c->dec_maxlength<c->dec_codelengths[i]) - c->dec_maxlength=c->dec_codelengths[i]; - if(c->dec_codelengths[i]<=c->dec_firsttablen){ - ogg_uint32_t orig=bitreverse(c->codelist[i]); - for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) - c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1; - } - } - - /* now fill in 'unused' entries in the firsttable with hi/lo search - hints for the non-direct-hits */ - { - ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen); - long lo=0,hi=0; - - for(i=0;i<tabn;i++){ - ogg_uint32_t word=i<<(32-c->dec_firsttablen); - if(c->dec_firsttable[bitreverse(word)]==0){ - while((lo+1)<n && c->codelist[lo+1]<=word)lo++; - while( hi<n && word>=(c->codelist[hi]&mask))hi++; - - /* we only actually have 15 bits per hint to play with here. - In order to overflow gracefully (nothing breaks, efficiency - just drops), encode as the difference from the extremes. */ - { - unsigned long loval=lo; - unsigned long hival=n-hi; - - if(loval>0x7fff)loval=0x7fff; - if(hival>0x7fff)hival=0x7fff; - c->dec_firsttable[bitreverse(word)]= - 0x80000000UL | (loval<<15) | hival; - } - } - } - } - } - - return(0); - err_out: - vorbis_book_clear(c); - return(-1); -} - diff --git a/lib/tremor/synthesis.c b/lib/tremor/synthesis.c deleted file mode 100644 index d22cb823..00000000 --- a/lib/tremor/synthesis.c +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: single-block PCM synthesis - last mod: $Id: synthesis.c,v 1.4 2003/03/29 03:07:21 xiphmont Exp $ - - ********************************************************************/ - -#include <stdio.h> -#include <ogg/ogg.h> -#include "ivorbiscodec.h" -#include "codec_internal.h" -#include "registry.h" -#include "misc.h" -#include "block.h" - -static int _vorbis_synthesis1(vorbis_block *vb,ogg_packet *op,int decodep){ - vorbis_dsp_state *vd= vb ? vb->vd : 0; - private_state *b= vd ? (private_state *)vd->backend_state: 0; - vorbis_info *vi= vd ? vd->vi : 0; - codec_setup_info *ci= vi ? (codec_setup_info *)vi->codec_setup : 0; - oggpack_buffer *opb=vb ? &vb->opb : 0; - int type,mode,i; - - if (!vd || !b || !vi || !ci || !opb) { - return OV_EBADPACKET; - } - - /* first things first. Make sure decode is ready */ - _vorbis_block_ripcord(vb); - oggpack_readinit(opb,op->packet,op->bytes); - - /* Check the packet type */ - if(oggpack_read(opb,1)!=0){ - /* Oops. This is not an audio data packet */ - return(OV_ENOTAUDIO); - } - - /* read our mode and pre/post windowsize */ - mode=oggpack_read(opb,b->modebits); - if(mode==-1)return(OV_EBADPACKET); - - vb->mode=mode; - if(!ci->mode_param[mode]){ - return(OV_EBADPACKET); - } - - vb->W=ci->mode_param[mode]->blockflag; - if(vb->W){ - vb->lW=oggpack_read(opb,1); - vb->nW=oggpack_read(opb,1); - if(vb->nW==-1) return(OV_EBADPACKET); - }else{ - vb->lW=0; - vb->nW=0; - } - - /* more setup */ - vb->granulepos=op->granulepos; - vb->sequence=op->packetno; /* first block is third packet */ - vb->eofflag=op->e_o_s; - - if(decodep){ - /* alloc pcm passback storage */ - vb->pcmend=ci->blocksizes[vb->W]; - vb->pcm=(ogg_int32_t **)_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); - for(i=0;i<vi->channels;i++) - vb->pcm[i]=(ogg_int32_t *)_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); - - /* unpack_header enforces range checking */ - type=ci->map_type[ci->mode_param[mode]->mapping]; - - return(_mapping_P[type]->inverse(vb,b->mode[mode])); - }else{ - /* no pcm */ - vb->pcmend=0; - vb->pcm=NULL; - - return(0); - } -} - -int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ - return _vorbis_synthesis1(vb,op,1); -} - -/* used to track pcm position without actually performing decode. - Useful for sequential 'fast forward' */ -int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ - return _vorbis_synthesis1(vb,op,0); -} - -long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){ - codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; - oggpack_buffer opb; - int mode; - - oggpack_readinit(&opb,op->packet,op->bytes); - - /* Check the packet type */ - if(oggpack_read(&opb,1)!=0){ - /* Oops. This is not an audio data packet */ - return(OV_ENOTAUDIO); - } - - { - int modebits=0; - int v=ci->modes; - while(v>1){ - modebits++; - v>>=1; - } - - /* read our mode and pre/post windowsize */ - mode=oggpack_read(&opb,modebits); - } - if(mode==-1 || !ci->mode_param[mode])return(OV_EBADPACKET); - return(ci->blocksizes[ci->mode_param[mode]->blockflag]); -} - - diff --git a/lib/tremor/tremor_ogg.h b/lib/tremor/tremor_ogg.h new file mode 100644 index 00000000..758573c7 --- /dev/null +++ b/lib/tremor/tremor_ogg.h @@ -0,0 +1,206 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: subsumed libogg includes + + ********************************************************************/ +#ifndef _TREMOR_OGG_H +#define _TREMOR_OGG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "os_types.h" + +typedef struct tremor_ogg_buffer_state{ + struct tremor_ogg_buffer *unused_buffers; + struct tremor_ogg_reference *unused_references; + int outstanding; + int shutdown; +} tremor_ogg_buffer_state; + +typedef struct tremor_ogg_buffer { + unsigned char *data; + long size; + int refcount; + + union { + tremor_ogg_buffer_state *owner; + struct tremor_ogg_buffer *next; + } ptr; +} tremor_ogg_buffer; + +typedef struct tremor_ogg_reference { + tremor_ogg_buffer *buffer; + long begin; + long length; + + struct tremor_ogg_reference *next; +} tremor_ogg_reference; + +typedef struct tremor_oggpack_buffer { + int headbit; + unsigned char *headptr; + long headend; + + /* memory management */ + tremor_ogg_reference *head; + tremor_ogg_reference *tail; + + /* render the byte/bit counter API constant time */ + long count; /* doesn't count the tail */ +} tremor_oggpack_buffer; + +typedef struct oggbyte_buffer { + tremor_ogg_reference *baseref; + + tremor_ogg_reference *ref; + unsigned char *ptr; + long pos; + long end; +} oggbyte_buffer; + +typedef struct tremor_ogg_sync_state { + /* decode memory management pool */ + tremor_ogg_buffer_state *bufferpool; + + /* stream buffers */ + tremor_ogg_reference *fifo_head; + tremor_ogg_reference *fifo_tail; + long fifo_fill; + + /* stream sync management */ + int unsynced; + int headerbytes; + int bodybytes; + +} tremor_ogg_sync_state; + +typedef struct tremor_ogg_stream_state { + tremor_ogg_reference *header_head; + tremor_ogg_reference *header_tail; + tremor_ogg_reference *body_head; + tremor_ogg_reference *body_tail; + + int e_o_s; /* set when we have buffered the last + packet in the logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + long serialno; + long pageno; + tremor_ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ + tremor_ogg_int64_t granulepos; + + int lacing_fill; + tremor_ogg_uint32_t body_fill; + + /* decode-side state data */ + int holeflag; + int spanflag; + int clearflag; + int laceptr; + tremor_ogg_uint32_t body_fill_next; + +} tremor_ogg_stream_state; + +typedef struct { + tremor_ogg_reference *packet; + long bytes; + long b_o_s; + long e_o_s; + tremor_ogg_int64_t granulepos; + tremor_ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ +} tremor_ogg_packet; + +typedef struct { + tremor_ogg_reference *header; + int header_len; + tremor_ogg_reference *body; + long body_len; +} tremor_ogg_page; + +/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ + +extern void tremor_oggpack_readinit(tremor_oggpack_buffer *b,tremor_ogg_reference *r); +extern long tremor_oggpack_look(tremor_oggpack_buffer *b,int bits); +extern void tremor_oggpack_adv(tremor_oggpack_buffer *b,int bits); +extern long tremor_oggpack_read(tremor_oggpack_buffer *b,int bits); +extern long tremor_oggpack_bytes(tremor_oggpack_buffer *b); +extern long tremor_oggpack_bits(tremor_oggpack_buffer *b); +extern int tremor_oggpack_eop(tremor_oggpack_buffer *b); + +/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ + +extern tremor_ogg_sync_state *tremor_ogg_sync_create(void); +extern int tremor_ogg_sync_destroy(tremor_ogg_sync_state *oy); +extern int tremor_ogg_sync_reset(tremor_ogg_sync_state *oy); + +extern unsigned char *tremor_ogg_sync_bufferin(tremor_ogg_sync_state *oy, long size); +extern int tremor_ogg_sync_wrote(tremor_ogg_sync_state *oy, long bytes); +extern long tremor_ogg_sync_pageseek(tremor_ogg_sync_state *oy,tremor_ogg_page *og); +extern int tremor_ogg_sync_pageout(tremor_ogg_sync_state *oy, tremor_ogg_page *og); +extern int tremor_ogg_stream_pagein(tremor_ogg_stream_state *os, tremor_ogg_page *og); +extern int tremor_ogg_stream_packetout(tremor_ogg_stream_state *os,tremor_ogg_packet *op); +extern int tremor_ogg_stream_packetpeek(tremor_ogg_stream_state *os,tremor_ogg_packet *op); + +/* Ogg BITSTREAM PRIMITIVES: general ***************************/ + +extern tremor_ogg_stream_state *tremor_ogg_stream_create(int serialno); +extern int tremor_ogg_stream_destroy(tremor_ogg_stream_state *os); +extern int tremor_ogg_stream_reset(tremor_ogg_stream_state *os); +extern int tremor_ogg_stream_reset_serialno(tremor_ogg_stream_state *os,int serialno); +extern int tremor_ogg_stream_eos(tremor_ogg_stream_state *os); + +extern int tremor_ogg_page_checksum_set(tremor_ogg_page *og); + +extern int tremor_ogg_page_version(tremor_ogg_page *og); +extern int tremor_ogg_page_continued(tremor_ogg_page *og); +extern int tremor_ogg_page_bos(tremor_ogg_page *og); +extern int tremor_ogg_page_eos(tremor_ogg_page *og); +extern tremor_ogg_int64_t tremor_ogg_page_granulepos(tremor_ogg_page *og); +extern tremor_ogg_uint32_t tremor_ogg_page_serialno(tremor_ogg_page *og); +extern tremor_ogg_uint32_t tremor_ogg_page_pageno(tremor_ogg_page *og); +extern int tremor_ogg_page_packets(tremor_ogg_page *og); +extern int tremor_ogg_page_getbuffer(tremor_ogg_page *og, unsigned char **buffer); + +extern int tremor_ogg_packet_release(tremor_ogg_packet *op); +extern int tremor_ogg_page_release(tremor_ogg_page *og); + +extern void tremor_ogg_page_dup(tremor_ogg_page *d, tremor_ogg_page *s); + +/* Ogg BITSTREAM PRIMITIVES: return codes ***************************/ + +#define OGG_SUCCESS 0 + +#define OGG_HOLE -10 +#define OGG_SPAN -11 +#define OGG_EVERSION -12 +#define OGG_ESERIAL -13 +#define OGG_EINVAL -14 +#define OGG_EEOS -15 + + +#ifdef __cplusplus +} +#endif + +#endif /* _TREMOR_OGG_H */ diff --git a/lib/tremor/vorbisfile.c b/lib/tremor/vorbisfile.c index cd4814df..79cdefcd 100644 --- a/lib/tremor/vorbisfile.c +++ b/lib/tremor/vorbisfile.c @@ -1,18 +1,18 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2014 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: stdio-based convenience library for opening/seeking/decoding - last mod: $Id$ + last mod: $Id: vorbisfile.c,v 1.6.2.5 2003/11/20 06:16:17 xiphmont Exp $ ********************************************************************/ @@ -22,12 +22,19 @@ #include <string.h> #include <math.h> -#include "ivorbiscodec.h" +#include "codec_internal.h" #include "ivorbisfile.h" #include "os.h" #include "misc.h" +#define NOTOPEN 0 +#define PARTOPEN 1 +#define OPENED 2 +#define STREAMSET 3 /* serialno and link set, but not to current link */ +#define LINKSET 4 /* serialno and link set to current link */ +#define INITSET 5 + /* A 'chained bitstream' is a Vorbis bitstream that contains more than one logical bitstream arranged end to end (the only form of Ogg multiplexing allowed in a Vorbis bitstream; grouping [parallel @@ -52,42 +59,35 @@ we only want coarse navigation through the stream. */ /************************************************************************* - * Many, many internal helpers. The intention is not to be confusing; - * rampant duplication and monolithic function implementation would be + * Many, many internal helpers. The intention is not to be confusing; + * rampant duplication and monolithic function implementation would be * harder to understand anyway. The high level functions are last. Begin * grokking near the end of the file */ -/* read a little more data from the file/pipe into the ogg_sync framer */ -static long _get_data(OggVorbis_File *vf){ +/* read a little more data from the file/pipe into the tremor_ogg_sync framer */ +static long _get_data(TremorOggVorbis_File *vf){ errno=0; - if(!(vf->callbacks.read_func))return(-1); if(vf->datasource){ - char *buffer=ogg_sync_buffer(&vf->oy,READSIZE); - long bytes=(vf->callbacks.read_func)(buffer,1,READSIZE,vf->datasource); - if(bytes>0)ogg_sync_wrote(&vf->oy,bytes); - if(bytes==0 && errno)return(-1); - return(bytes); + unsigned char *buffer=tremor_ogg_sync_bufferin(vf->oy,CHUNKSIZE); + long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource); + if(bytes>0)tremor_ogg_sync_wrote(vf->oy,bytes); + if(bytes==0 && errno)return -1; + return bytes; }else - return(0); + return 0; } /* save a tiny smidge of verbosity to make the code more readable */ -static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){ - if(vf->datasource){ - /* only seek if the file position isn't already there */ - if(vf->offset != offset){ - if(!(vf->callbacks.seek_func)|| - (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1) - return OV_EREAD; - vf->offset=offset; - ogg_sync_reset(&vf->oy); - } +static void _seek_helper(TremorOggVorbis_File *vf,tremor_ogg_int64_t offset){ + if(vf->datasource){ + (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET); + vf->offset=offset; + tremor_ogg_sync_reset(vf->oy); }else{ /* shouldn't happen unless someone writes a broken callback */ - return OV_EFAULT; + return; } - return 0; } /* The read/seek functions track absolute position within the stream */ @@ -98,310 +98,221 @@ static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){ boundary: -1) unbounded search 0) read no additional data; use cached only - n) search for a new page beginning for n bytes + n) search for a new page beginning for n bytes return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD) - n) found a page at absolute offset n */ + n) found a page at absolute offset n + + produces a refcounted page */ -static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og, - ogg_int64_t boundary){ +static tremor_ogg_int64_t _get_next_page(TremorOggVorbis_File *vf,tremor_ogg_page *og, + tremor_ogg_int64_t boundary){ if(boundary>0)boundary+=vf->offset; while(1){ long more; - if(boundary>0 && vf->offset>=boundary)return(OV_FALSE); - more=ogg_sync_pageseek(&vf->oy,og); - + if(boundary>0 && vf->offset>=boundary)return OV_FALSE; + more=tremor_ogg_sync_pageseek(vf->oy,og); + if(more<0){ /* skipped n bytes */ vf->offset-=more; }else{ if(more==0){ - /* send more paramedics */ - if(!boundary)return(OV_FALSE); - { - long ret=_get_data(vf); - if(ret==0)return(OV_EOF); - if(ret<0)return(OV_EREAD); - } + /* send more paramedics */ + if(!boundary)return OV_FALSE; + { + long ret=_get_data(vf); + if(ret==0)return OV_EOF; + if(ret<0)return OV_EREAD; + } }else{ - /* got a page. Return the offset at the page beginning, + /* got a page. Return the offset at the page beginning, advance the internal offset past the page end */ - ogg_int64_t ret=vf->offset; - vf->offset+=more; - return(ret); - + tremor_ogg_int64_t ret=vf->offset; + vf->offset+=more; + return ret; + } } } } -/* find the latest page beginning before the passed in position. Much - dirtier than the above as Ogg doesn't have any backward search - linkage. no 'readp' as it will certainly have to read. */ -/* returns offset or OV_EREAD, OV_FAULT */ -static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_int64_t begin,ogg_page *og){ - ogg_int64_t end = begin; - ogg_int64_t ret; - ogg_int64_t offset=-1; +/* find the latest page beginning before the current stream cursor + position. Much dirtier than the above as Ogg doesn't have any + backward search linkage. no 'readp' as it will certainly have to + read. */ +/* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */ + +static tremor_ogg_int64_t _get_prev_page(TremorOggVorbis_File *vf,tremor_ogg_page *og){ + tremor_ogg_int64_t begin=vf->offset; + tremor_ogg_int64_t end=begin; + tremor_ogg_int64_t ret; + tremor_ogg_int64_t offset=-1; while(offset==-1){ begin-=CHUNKSIZE; if(begin<0) begin=0; - - ret=_seek_helper(vf,begin); - if(ret)return(ret); - + _seek_helper(vf,begin); while(vf->offset<end){ - memset(og,0,sizeof(*og)); ret=_get_next_page(vf,og,end-vf->offset); - if(ret==OV_EREAD)return(OV_EREAD); + if(ret==OV_EREAD)return OV_EREAD; if(ret<0){ - break; + break; }else{ - offset=ret; + offset=ret; } } } - /* In a fully compliant, non-multiplexed stream, we'll still be - holding the last page. In multiplexed (or noncompliant streams), - we will probably have to re-read the last page we saw */ - if(og->header_len==0){ - ret=_seek_helper(vf,offset); - if(ret)return(ret); - - ret=_get_next_page(vf,og,CHUNKSIZE); - if(ret<0) - /* this shouldn't be possible */ - return(OV_EFAULT); - } + /* we have the offset. Actually snork and hold the page now */ + _seek_helper(vf,offset); + ret=_get_next_page(vf,og,CHUNKSIZE); + if(ret<0) + /* this shouldn't be possible */ + return OV_EFAULT; - return(offset); + return offset; } -static void _add_serialno(ogg_page *og,ogg_uint32_t **serialno_list, int *n){ - ogg_uint32_t s = ogg_page_serialno(og); - (*n)++; - - if(*serialno_list){ - *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n)); - }else{ - *serialno_list = _ogg_malloc(sizeof(**serialno_list)); +/* finds each bitstream link one at a time using a bisection search + (has to begin by knowing the offset of the lb's initial page). + Recurses for each link so it can alloc the link storage after + finding them all, then unroll and fill the cache at the same time */ +static int _bisect_forward_serialno(TremorOggVorbis_File *vf, + tremor_ogg_int64_t begin, + tremor_ogg_int64_t searched, + tremor_ogg_int64_t end, + tremor_ogg_uint32_t currentno, + long m){ + tremor_ogg_int64_t endsearched=end; + tremor_ogg_int64_t next=end; + tremor_ogg_page og={0,0,0,0}; + tremor_ogg_int64_t ret; + + /* the below guards against garbage seperating the last and + first pages of two links. */ + while(searched<endsearched){ + tremor_ogg_int64_t bisect; + + if(endsearched-searched<CHUNKSIZE){ + bisect=searched; + }else{ + bisect=(searched+endsearched)/2; + } + + _seek_helper(vf,bisect); + ret=_get_next_page(vf,&og,-1); + if(ret==OV_EREAD)return OV_EREAD; + if(ret<0 || tremor_ogg_page_serialno(&og)!=currentno){ + endsearched=bisect; + if(ret>=0)next=ret; + }else{ + searched=ret+og.header_len+og.body_len; + } + tremor_ogg_page_release(&og); } - (*serialno_list)[(*n)-1] = s; -} - -/* returns nonzero if found */ -static int _lookup_serialno(ogg_uint32_t s, ogg_uint32_t *serialno_list, int n){ - if(serialno_list){ - while(n--){ - if(*serialno_list == s) return 1; - serialno_list++; - } + _seek_helper(vf,next); + ret=_get_next_page(vf,&og,-1); + if(ret==OV_EREAD)return OV_EREAD; + + if(searched>=end || ret<0){ + tremor_ogg_page_release(&og); + vf->links=m+1; + vf->offsets=_tremor_ogg_malloc((vf->links+1)*sizeof(*vf->offsets)); + vf->serialnos=_tremor_ogg_malloc(vf->links*sizeof(*vf->serialnos)); + vf->offsets[m+1]=searched; + }else{ + ret=_bisect_forward_serialno(vf,next,vf->offset, + end,tremor_ogg_page_serialno(&og),m+1); + tremor_ogg_page_release(&og); + if(ret==OV_EREAD)return OV_EREAD; } + + vf->offsets[m]=begin; + vf->serialnos[m]=currentno; return 0; } -static int _lookup_page_serialno(ogg_page *og, ogg_uint32_t *serialno_list, int n){ - ogg_uint32_t s = ogg_page_serialno(og); - return _lookup_serialno(s,serialno_list,n); -} - -/* performs the same search as _get_prev_page, but prefers pages of - the specified serial number. If a page of the specified serialno is - spotted during the seek-back-and-read-forward, it will return the - info of last page of the matching serial number instead of the very - last page. If no page of the specified serialno is seen, it will - return the info of last page and alter *serialno. */ -static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf, ogg_int64_t begin, - ogg_uint32_t *serial_list, int serial_n, - int *serialno, ogg_int64_t *granpos){ - ogg_page og; - ogg_int64_t end=begin; - ogg_int64_t ret; - - ogg_int64_t prefoffset=-1; - ogg_int64_t offset=-1; - ogg_int64_t ret_serialno=-1; - ogg_int64_t ret_gran=-1; - - while(offset==-1){ - begin-=CHUNKSIZE; - if(begin<0) - begin=0; - - ret=_seek_helper(vf,begin); - if(ret)return(ret); - - while(vf->offset<end){ - ret=_get_next_page(vf,&og,end-vf->offset); - if(ret==OV_EREAD)return(OV_EREAD); - if(ret<0){ - break; - }else{ - ret_serialno=ogg_page_serialno(&og); - ret_gran=ogg_page_granulepos(&og); - offset=ret; - - if((ogg_uint32_t)ret_serialno == *serialno){ - prefoffset=ret; - *granpos=ret_gran; - } - - if(!_lookup_serialno((ogg_uint32_t)ret_serialno,serial_list,serial_n)){ - /* we fell off the end of the link, which means we seeked - back too far and shouldn't have been looking in that link - to begin with. If we found the preferred serial number, - forget that we saw it. */ - prefoffset=-1; - } - } - } +static int _decode_clear(TremorOggVorbis_File *vf){ + if(vf->ready_state==INITSET){ + vorbis_dsp_destroy(vf->vd); + vf->vd=0; + vf->ready_state=STREAMSET; } - - /* we're not interested in the page... just the serialno and granpos. */ - if(prefoffset>=0)return(prefoffset); - - *serialno = ret_serialno; - *granpos = ret_gran; - return(offset); - + + if(vf->ready_state>=STREAMSET){ + vorbis_info_clear(&vf->vi); + vorbis_comment_clear(&vf->vc); + vf->ready_state=OPENED; + } + return 0; } -/* uses the local ogg_stream storage in vf; this is important for +/* uses the local tremor_ogg_stream storage in vf; this is important for non-streaming input sources */ -static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc, - ogg_uint32_t **serialno_list, int *serialno_n, - ogg_page *og_ptr){ - ogg_page og; - ogg_packet op; +/* consumes the page that's passed in (if any) */ +/* state is LINKSET upon successful return */ + +static int _fetch_headers(TremorOggVorbis_File *vf, + vorbis_info *vi, + vorbis_comment *vc, + tremor_ogg_uint32_t *serialno, + tremor_ogg_page *og_ptr){ + tremor_ogg_page og={0,0,0,0}; + tremor_ogg_packet op={0,0,0,0,0,0}; int i,ret; - int allbos=0; + + if(vf->ready_state>OPENED)_decode_clear(vf); if(!og_ptr){ - ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); - if(llret==OV_EREAD)return(OV_EREAD); - if(llret<0)return(OV_ENOTVORBIS); + tremor_ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); + if(llret==OV_EREAD)return OV_EREAD; + if(llret<0)return OV_ENOTVORBIS; og_ptr=&og; } + tremor_ogg_stream_reset_serialno(vf->os,tremor_ogg_page_serialno(og_ptr)); + if(serialno)*serialno=vf->os->serialno; + + /* extract the initial header from the first page and verify that the + Ogg bitstream is in fact Vorbis data */ + vorbis_info_init(vi); vorbis_comment_init(vc); - vf->ready_state=OPENED; - - /* extract the serialnos of all BOS pages + the first set of vorbis - headers we see in the link */ - - while(ogg_page_bos(og_ptr)){ - if(serialno_list){ - if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){ - /* a dupe serialnumber in an initial header packet set == invalid stream */ - if(*serialno_list)_ogg_free(*serialno_list); - *serialno_list=0; - *serialno_n=0; - ret=OV_EBADHEADER; - goto bail_header; + + i=0; + while(i<3){ + tremor_ogg_stream_pagein(vf->os,og_ptr); + while(i<3){ + int result=tremor_ogg_stream_packetout(vf->os,&op); + if(result==0)break; + if(result==-1){ + ret=OV_EBADHEADER; + goto bail_header; } - - _add_serialno(og_ptr,serialno_list,serialno_n); - } - - if(vf->ready_state<STREAMSET){ - /* we don't have a vorbis stream in this link yet, so begin - prospective stream setup. We need a stream to get packets */ - ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr)); - ogg_stream_pagein(&vf->os,og_ptr); - - if(ogg_stream_packetout(&vf->os,&op) > 0 && - vorbis_synthesis_idheader(&op)){ - /* vorbis header; continue setup */ - vf->ready_state=STREAMSET; - if((ret=vorbis_synthesis_headerin(vi,vc,&op))){ - ret=OV_EBADHEADER; - goto bail_header; - } + if((ret=vorbis_dsp_headerin(vi,vc,&op))){ + goto bail_header; } + i++; } - - /* get next page */ - { - ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE); - if(llret==OV_EREAD){ - ret=OV_EREAD; - goto bail_header; - } - if(llret<0){ - ret=OV_ENOTVORBIS; - goto bail_header; + if(i<3) + if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){ + ret=OV_EBADHEADER; + goto bail_header; } - - /* if this page also belongs to our vorbis stream, submit it and break */ - if(vf->ready_state==STREAMSET && - vf->os.serialno == ogg_page_serialno(og_ptr)){ - ogg_stream_pagein(&vf->os,og_ptr); - break; - } - } } - if(vf->ready_state!=STREAMSET){ - ret = OV_ENOTVORBIS; - goto bail_header; - } - - while(1){ - - i=0; - while(i<2){ /* get a page loop */ - - while(i<2){ /* get a packet loop */ - - int result=ogg_stream_packetout(&vf->os,&op); - if(result==0)break; - if(result==-1){ - ret=OV_EBADHEADER; - goto bail_header; - } - - if((ret=vorbis_synthesis_headerin(vi,vc,&op))) - goto bail_header; - - i++; - } - - while(i<2){ - if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){ - ret=OV_EBADHEADER; - goto bail_header; - } - - /* if this page belongs to the correct stream, go parse it */ - if(vf->os.serialno == ogg_page_serialno(og_ptr)){ - ogg_stream_pagein(&vf->os,og_ptr); - break; - } - - /* if we never see the final vorbis headers before the link - ends, abort */ - if(ogg_page_bos(og_ptr)){ - if(allbos){ - ret = OV_EBADHEADER; - goto bail_header; - }else - allbos=1; - } - - /* otherwise, keep looking */ - } - } - - return 0; - } + tremor_ogg_packet_release(&op); + tremor_ogg_page_release(&og); + vf->ready_state=LINKSET; + return 0; bail_header: + tremor_ogg_packet_release(&op); + tremor_ogg_page_release(&og); vorbis_info_clear(vi); vorbis_comment_clear(vc); vf->ready_state=OPENED; @@ -409,401 +320,321 @@ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc, return ret; } -/* Starting from current cursor position, get initial PCM offset of - next page. Consumes the page in the process without decoding - audio, however this is only called during stream parsing upon - seekable open. */ -static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){ - ogg_page og; - ogg_int64_t accumulated=0; - long lastblock=-1; - int result; - int serialno = vf->os.serialno; - - while(1){ - ogg_packet op; - if(_get_next_page(vf,&og,-1)<0) - break; /* should not be possible unless the file is truncated/mangled */ - - if(ogg_page_bos(&og)) break; - if(ogg_page_serialno(&og)!=serialno) continue; - - /* count blocksizes of all frames in the page */ - ogg_stream_pagein(&vf->os,&og); - while((result=ogg_stream_packetout(&vf->os,&op))){ - if(result>0){ /* ignore holes */ - long thisblock=vorbis_packet_blocksize(vi,&op); - if(lastblock!=-1) - accumulated+=(lastblock+thisblock)>>2; - lastblock=thisblock; - } - } - - if(ogg_page_granulepos(&og)!=-1){ - /* pcm offset of last packet on the first audio page */ - accumulated= ogg_page_granulepos(&og)-accumulated; - break; - } +/* we no longer preload all vorbis_info (and the associated + codec_setup) structs. Call this to seek and fetch the info from + the bitstream, if needed */ +static int _set_link_number(TremorOggVorbis_File *vf,int link){ + if(link != vf->current_link) _decode_clear(vf); + if(vf->ready_state<STREAMSET){ + _seek_helper(vf,vf->offsets[link]); + tremor_ogg_stream_reset_serialno(vf->os,vf->serialnos[link]); + vf->current_serialno=vf->serialnos[link]; + vf->current_link=link; + return _fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,NULL); } - - /* less than zero? This is a stream with samples trimmed off - the beginning, a normal occurrence; set the offset to zero */ - if(accumulated<0)accumulated=0; - - return accumulated; + return 0; } -/* finds each bitstream link one at a time using a bisection search - (has to begin by knowing the offset of the lb's initial page). - Recurses for each link so it can alloc the link storage after - finding them all, then unroll and fill the cache at the same time */ -static int _bisect_forward_serialno(OggVorbis_File *vf, - ogg_int64_t begin, - ogg_int64_t searched, - ogg_int64_t end, - ogg_int64_t endgran, - int endserial, - ogg_uint32_t *currentno_list, - int currentnos, - long m){ - ogg_int64_t pcmoffset; - ogg_int64_t dataoffset=searched; - ogg_int64_t endsearched=end; - ogg_int64_t next=end; - ogg_int64_t searchgran=-1; - ogg_page og; - ogg_int64_t ret,last; - int serialno = vf->os.serialno; - - /* invariants: - we have the headers and serialnos for the link beginning at 'begin' - we have the offset and granpos of the last page in the file (potentially - not a page we care about) - */ - - /* Is the last page in our list of current serialnumbers? */ - if(_lookup_serialno(endserial,currentno_list,currentnos)){ - - /* last page is in the starting serialno list, so we've bisected - down to (or just started with) a single link. Now we need to - find the last vorbis page belonging to the first vorbis stream - for this link. */ - searched = end; - while(endserial != serialno){ - endserial = serialno; - searched=_get_prev_page_serial(vf,searched,currentno_list,currentnos,&endserial,&endgran); - } - - vf->links=m+1; - if(vf->offsets)_ogg_free(vf->offsets); - if(vf->serialnos)_ogg_free(vf->serialnos); - if(vf->dataoffsets)_ogg_free(vf->dataoffsets); - - vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets)); - vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi)); - vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc)); - vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos)); - vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets)); - vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths)); - - vf->offsets[m+1]=end; - vf->offsets[m]=begin; - vf->pcmlengths[m*2+1]=(endgran<0?0:endgran); - - }else{ - - /* last page is not in the starting stream's serial number list, - so we have multiple links. Find where the stream that begins - our bisection ends. */ - - ogg_uint32_t *next_serialno_list=NULL; - int next_serialnos=0; - vorbis_info vi; - vorbis_comment vc; - int testserial = serialno+1; +static int _set_link_number_preserve_pos(TremorOggVorbis_File *vf,int link){ + tremor_ogg_int64_t pos=vf->offset; + int ret=_set_link_number(vf,link); + if(ret)return ret; + _seek_helper(vf,pos); + if(pos<vf->offsets[link] || pos>=vf->offsets[link+1]) + vf->ready_state=STREAMSET; + return 0; +} - /* the below guards against garbage seperating the last and - first pages of two links. */ - while(searched<endsearched){ - ogg_int64_t bisect; +/* last step of the TremorOggVorbis_File initialization; get all the offset + positions. Only called by the seekable initialization (local + stream storage is hacked slightly; pay attention to how that's + done) */ + +/* this is void and does not propogate errors up because we want to be + able to open and use damaged bitstreams as well as we can. Just + watch out for missing information for links in the TremorOggVorbis_File + struct */ +static void _prefetch_all_offsets(TremorOggVorbis_File *vf, tremor_ogg_int64_t dataoffset){ + tremor_ogg_page og={0,0,0,0}; + int i; + tremor_ogg_int64_t ret; + + vf->dataoffsets=_tremor_ogg_malloc(vf->links*sizeof(*vf->dataoffsets)); + vf->pcmlengths=_tremor_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths)); + + for(i=0;i<vf->links;i++){ + if(i==0){ + /* we already grabbed the initial header earlier. Just set the offset */ + vf->dataoffsets[i]=dataoffset; + _seek_helper(vf,dataoffset); - if(endsearched-searched<CHUNKSIZE){ - bisect=searched; - }else{ - bisect=(searched+endsearched)/2; - } + }else{ - ret=_seek_helper(vf,bisect); - if(ret)return(ret); + /* seek to the location of the initial header */ - last=_get_next_page(vf,&og,-1); - if(last==OV_EREAD)return(OV_EREAD); - if(last<0 || !_lookup_page_serialno(&og,currentno_list,currentnos)){ - endsearched=bisect; - if(last>=0)next=last; + _seek_helper(vf,vf->offsets[i]); + if(_fetch_headers(vf,&vf->vi,&vf->vc,NULL,NULL)<0){ + vf->dataoffsets[i]=-1; }else{ - searched=vf->offset; + vf->dataoffsets[i]=vf->offset; } } - /* Bisection point found */ - /* for the time being, fetch end PCM offset the simple way */ - searched = next; - while(testserial != serialno){ - testserial = serialno; - searched = _get_prev_page_serial(vf,searched,currentno_list,currentnos,&testserial,&searchgran); - } - - ret=_seek_helper(vf,next); - if(ret)return(ret); + /* fetch beginning PCM offset */ - ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL); - if(ret)return(ret); - serialno = vf->os.serialno; - dataoffset = vf->offset; + if(vf->dataoffsets[i]!=-1){ + tremor_ogg_int64_t accumulated=0,pos; + long lastblock=-1; + int result; - /* this will consume a page, however the next bisection always - starts with a raw seek */ - pcmoffset = _initial_pcmoffset(vf,&vi); + tremor_ogg_stream_reset_serialno(vf->os,vf->serialnos[i]); - ret=_bisect_forward_serialno(vf,next,vf->offset,end,endgran,endserial, - next_serialno_list,next_serialnos,m+1); - if(ret)return(ret); - - if(next_serialno_list)_ogg_free(next_serialno_list); + while(1){ + tremor_ogg_packet op={0,0,0,0,0,0}; + + ret=_get_next_page(vf,&og,-1); + if(ret<0) + /* this should not be possible unless the file is + truncated/mangled */ + break; + + if(tremor_ogg_page_serialno(&og)!=vf->serialnos[i]) + break; + + pos=tremor_ogg_page_granulepos(&og); + + /* count blocksizes of all frames in the page */ + tremor_ogg_stream_pagein(vf->os,&og); + while((result=tremor_ogg_stream_packetout(vf->os,&op))){ + if(result>0){ /* ignore holes */ + long thisblock=vorbis_packet_blocksize(&vf->vi,&op); + if(lastblock!=-1) + accumulated+=(lastblock+thisblock)>>2; + lastblock=thisblock; + } + } + tremor_ogg_packet_release(&op); + + if(pos!=-1){ + /* pcm offset of last packet on the first audio page */ + accumulated= pos-accumulated; + break; + } + } - vf->offsets[m+1]=next; - vf->serialnos[m+1]=serialno; - vf->dataoffsets[m+1]=dataoffset; + /* less than zero? This is a stream with samples trimmed off + the beginning, a normal occurrence; set the offset to zero */ + if(accumulated<0)accumulated=0; - vf->vi[m+1]=vi; - vf->vc[m+1]=vc; + vf->pcmlengths[i*2]=accumulated; + } - vf->pcmlengths[m*2+1]=searchgran; - vf->pcmlengths[m*2+2]=pcmoffset; - vf->pcmlengths[m*2+3]-=pcmoffset; - if(vf->pcmlengths[m*2+3]<0)vf->pcmlengths[m*2+3]=0; + /* get the PCM length of this link. To do this, + get the last page of the stream */ + { + tremor_ogg_int64_t end=vf->offsets[i+1]; + _seek_helper(vf,end); + while(1){ + ret=_get_prev_page(vf,&og); + if(ret<0){ + /* this should not be possible */ + vorbis_info_clear(&vf->vi); + vorbis_comment_clear(&vf->vc); + break; + } + if(tremor_ogg_page_granulepos(&og)!=-1){ + vf->pcmlengths[i*2+1]=tremor_ogg_page_granulepos(&og)-vf->pcmlengths[i*2]; + break; + } + vf->offset=ret; + } + } } - return(0); + tremor_ogg_page_release(&og); } -static int _make_decode_ready(OggVorbis_File *vf){ - if(vf->ready_state>STREAMSET)return 0; - if(vf->ready_state<STREAMSET)return OV_EFAULT; - if(vf->seekable){ - if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link)) - return OV_EBADLINK; - }else{ - if(vorbis_synthesis_init(&vf->vd,vf->vi)) - return OV_EBADLINK; +static int _make_decode_ready(TremorOggVorbis_File *vf){ + int i; + switch(vf->ready_state){ + case OPENED: + case STREAMSET: + for(i=0;i<vf->links;i++) + if(vf->offsets[i+1]>=vf->offset)break; + if(i==vf->links)return -1; + i=_set_link_number_preserve_pos(vf,i); + if(i)return i; + /* fall through */ + case LINKSET: + vf->vd=vorbis_dsp_create(&vf->vi); + vf->ready_state=INITSET; + vf->bittrack=0; + vf->samptrack=0; + case INITSET: + return 0; + default: + return -1; } - vorbis_block_init(&vf->vd,&vf->vb); - vf->ready_state=INITSET; - vf->bittrack=0; - vf->samptrack=0; - return 0; + } -static int _open_seekable2(OggVorbis_File *vf){ - ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1; - int endserial=vf->os.serialno; - int serialno=vf->os.serialno; +static int _open_seekable2(TremorOggVorbis_File *vf){ + tremor_ogg_uint32_t serialno=vf->current_serialno; + tremor_ogg_uint32_t tempserialno; + tremor_ogg_int64_t dataoffset=vf->offset, end; + tremor_ogg_page og={0,0,0,0}; /* we're partially open and have a first link header state in storage in vf */ - - /* fetch initial PCM offset */ - ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi); - /* we can seek, so set out learning all about this file */ - if(vf->callbacks.seek_func && vf->callbacks.tell_func){ - (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END); - vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); - }else{ - vf->offset=vf->end=-1; - } + (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END); + vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); + + /* We get the offset for the last page of the physical bitstream. + Most TremorOggVorbis files will contain a single logical bitstream */ + end=_get_prev_page(vf,&og); + if(end<0)return end; - /* If seek_func is implemented, tell_func must also be implemented */ - if(vf->end==-1) return(OV_EINVAL); + /* more than one logical bitstream? */ + tempserialno=tremor_ogg_page_serialno(&og); + tremor_ogg_page_release(&og); - /* Get the offset of the last page of the physical bitstream, or, if - we're lucky the last vorbis page of this link as most OggVorbis - files will contain a single logical bitstream */ - end=_get_prev_page_serial(vf,vf->end,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran); - if(end<0)return(end); + if(tempserialno!=serialno){ - /* now determine bitstream structure recursively */ - if(_bisect_forward_serialno(vf,0,dataoffset,end,endgran,endserial, - vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD); + /* Chained bitstream. Bisect-search each logical bitstream + section. Do so based on serial number only */ + if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return OV_EREAD; - vf->offsets[0]=0; - vf->serialnos[0]=serialno; - vf->dataoffsets[0]=dataoffset; - vf->pcmlengths[0]=pcmoffset; - vf->pcmlengths[1]-=pcmoffset; - if(vf->pcmlengths[1]<0)vf->pcmlengths[1]=0; + }else{ - return(ov_raw_seek(vf,dataoffset)); -} + /* Only one logical bitstream */ + if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return OV_EREAD; -/* clear out the current logical bitstream decoder */ -static void _decode_clear(OggVorbis_File *vf){ - vorbis_dsp_clear(&vf->vd); - vorbis_block_clear(&vf->vb); - vf->ready_state=OPENED; + } + + /* the initial header memory is referenced by vf after; don't free it */ + _prefetch_all_offsets(vf,dataoffset); + return ov_raw_seek(vf,0); } /* fetch and process a packet. Handles the case where we're at a bitstream boundary and dumps the decoding machine. If the decoding machine is unloaded, it loads it. It also keeps pcm_offset up to date (seek and read both use this. seek uses a special hack with - readp). + readp). return: <0) error, OV_HOLE (lost packet) or OV_EOF 0) need more data (only if readp==0) - 1) got a packet + 1) got a packet */ -static int _fetch_and_process_packet(OggVorbis_File *vf, - ogg_packet *op_in, - int readp, - int spanp){ - ogg_page og; +static int _fetch_and_process_packet(TremorOggVorbis_File *vf, + int readp, + int spanp){ + tremor_ogg_page og={0,0,0,0}; + tremor_ogg_packet op={0,0,0,0,0,0}; + int ret=0; /* handle one packet. Try to fetch it from current stream state */ /* extract packets from page */ while(1){ - - if(vf->ready_state==STREAMSET){ - int ret=_make_decode_ready(vf); - if(ret<0)return ret; - } - + /* process a packet if we can. If the machine isn't loaded, neither is a page */ if(vf->ready_state==INITSET){ while(1) { - ogg_packet op; - ogg_packet *op_ptr=(op_in?op_in:&op); - int result=ogg_stream_packetout(&vf->os,op_ptr); - ogg_int64_t granulepos; - - op_in=NULL; - if(result==-1)return(OV_HOLE); /* hole in the data. */ - if(result>0){ - /* got a packet. process it */ - granulepos=op_ptr->granulepos; - if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy - header handling. The - header packets aren't - audio, so if/when we - submit them, - vorbis_synthesis will - reject them */ - - /* suck in the synthesis data and track bitrate */ - { - int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL); - /* for proper use of libvorbis within libvorbisfile, - oldsamples will always be zero. */ - if(oldsamples)return(OV_EFAULT); - - vorbis_synthesis_blockin(&vf->vd,&vf->vb); - vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL); - vf->bittrack+=op_ptr->bytes*8; - } - - /* update the pcm offset. */ - if(granulepos!=-1 && !op_ptr->e_o_s){ - int link=(vf->seekable?vf->current_link:0); - int i,samples; - - /* this packet has a pcm_offset on it (the last packet - completed on a page carries the offset) After processing - (above), we know the pcm position of the *last* sample - ready to be returned. Find the offset of the *first* - - As an aside, this trick is inaccurate if we begin - reading anew right at the last page; the end-of-stream - granulepos declares the last frame in the stream, and the - last packet of the last page may be a partial frame. - So, we need a previous granulepos from an in-sequence page - to have a reference point. Thus the !op_ptr->e_o_s clause - above */ - - if(vf->seekable && link>0) - granulepos-=vf->pcmlengths[link*2]; - if(granulepos<0)granulepos=0; /* actually, this - shouldn't be possible - here unless the stream - is very broken */ - - samples=vorbis_synthesis_pcmout(&vf->vd,NULL); - - granulepos-=samples; - for(i=0;i<link;i++) - granulepos+=vf->pcmlengths[i*2+1]; - vf->pcm_offset=granulepos; - } - return(1); - } - } - else - break; + int result=tremor_ogg_stream_packetout(vf->os,&op); + tremor_ogg_int64_t granulepos; + + if(result<0){ + ret=OV_HOLE; /* hole in the data. */ + goto cleanup; + } + if(result>0){ + /* got a packet. process it */ + granulepos=op.granulepos; + if(!vorbis_dsp_synthesis(vf->vd,&op,1)){ /* lazy check for lazy + header handling. The + header packets aren't + audio, so if/when we + submit them, + vorbis_synthesis will + reject them */ + + vf->samptrack+=vorbis_dsp_pcmout(vf->vd,NULL,0); + vf->bittrack+=op.bytes*8; + + /* update the pcm offset. */ + if(granulepos!=-1 && !op.e_o_s){ + int link=(vf->seekable?vf->current_link:0); + int i,samples; + + /* this packet has a pcm_offset on it (the last packet + completed on a page carries the offset) After processing + (above), we know the pcm position of the *last* sample + ready to be returned. Find the offset of the *first* + + As an aside, this trick is inaccurate if we begin + reading anew right at the last page; the end-of-stream + granulepos declares the last frame in the stream, and the + last packet of the last page may be a partial frame. + So, we need a previous granulepos from an in-sequence page + to have a reference point. Thus the !op.e_o_s clause + above */ + + if(vf->seekable && link>0) + granulepos-=vf->pcmlengths[link*2]; + if(granulepos<0)granulepos=0; /* actually, this + shouldn't be possible + here unless the stream + is very broken */ + + samples=vorbis_dsp_pcmout(vf->vd,NULL,0); + + granulepos-=samples; + for(i=0;i<link;i++) + granulepos+=vf->pcmlengths[i*2+1]; + vf->pcm_offset=granulepos; + } + ret=1; + goto cleanup; + } + } + else + break; } } if(vf->ready_state>=OPENED){ - ogg_int64_t ret; + int ret; + if(!readp){ + ret=0; + goto cleanup; + } + if((ret=_get_next_page(vf,&og,-1))<0){ + ret=OV_EOF; /* eof. leave unitialized */ + goto cleanup; + } - while(1){ - /* the loop is not strictly necessary, but there's no sense in - doing the extra checks of the larger loop for the common - case in a multiplexed bistream where the page is simply - part of a different logical bitstream; keep reading until - we get one with the correct serialno */ - - if(!readp)return(0); - if((ret=_get_next_page(vf,&og,-1))<0){ - return(OV_EOF); /* eof. leave unitialized */ - } - - /* bitrate tracking; add the header's bytes here, the body bytes - are done by packet above */ - vf->bittrack+=og.header_len*8; - - if(vf->ready_state==INITSET){ - if(vf->current_serialno!=ogg_page_serialno(&og)){ - - /* two possibilities: - 1) our decoding just traversed a bitstream boundary - 2) another stream is multiplexed into this logical section */ - - if(ogg_page_bos(&og)){ - /* boundary case */ - if(!spanp) - return(OV_EOF); - - _decode_clear(vf); - - if(!vf->seekable){ - vorbis_info_clear(vf->vi); - vorbis_comment_clear(vf->vc); - } - break; - - }else - continue; /* possibility #2 */ - } - } - - break; + /* bitrate tracking; add the header's bytes here, the body bytes + are done by packet above */ + vf->bittrack+=og.header_len*8; + + /* has our decoding just traversed a bitstream boundary? */ + if(vf->ready_state==INITSET){ + if(vf->current_serialno!=tremor_ogg_page_serialno(&og)){ + if(!spanp){ + ret=OV_EOF; + goto cleanup; + } + + _decode_clear(vf); + } } } /* Do we need to load a new machine before submitting the page? */ - /* This is different in the seekable and non-seekable cases. + /* This is different in the seekable and non-seekable cases. In the seekable case, we already have all the header information loaded and cached; we just initialize the machine @@ -814,79 +645,80 @@ static int _fetch_and_process_packet(OggVorbis_File *vf, we're now nominally at the header of the next bitstream */ - if(vf->ready_state!=INITSET){ - int link; + if(vf->ready_state!=INITSET){ + int link,ret; if(vf->ready_state<STREAMSET){ - if(vf->seekable){ - ogg_uint32_t serialno = ogg_page_serialno(&og); - - /* match the serialno to bitstream section. We use this rather than - offset positions to avoid problems near logical bitstream - boundaries */ - - for(link=0;link<vf->links;link++) - if(vf->serialnos[link]==serialno)break; - - if(link==vf->links) continue; /* not the desired Vorbis - bitstream section; keep - trying */ - - vf->current_serialno=serialno; - vf->current_link=link; - - ogg_stream_reset_serialno(&vf->os,vf->current_serialno); - vf->ready_state=STREAMSET; - - }else{ - /* we're streaming */ - /* fetch the three header packets, build the info struct */ - - int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og); - if(ret)return(ret); - vf->current_serialno=vf->os.serialno; - vf->current_link++; - link=0; - } + if(vf->seekable){ + vf->current_serialno=tremor_ogg_page_serialno(&og); + + /* match the serialno to bitstream section. We use this rather than + offset positions to avoid problems near logical bitstream + boundaries */ + for(link=0;link<vf->links;link++) + if(vf->serialnos[link]==vf->current_serialno)break; + if(link==vf->links){ + ret=OV_EBADLINK; /* sign of a bogus stream. error out, + leave machine uninitialized */ + goto cleanup; + } + + vf->current_link=link; + ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); + if(ret) goto cleanup; + + }else{ + /* we're streaming */ + /* fetch the three header packets, build the info struct */ + + int ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); + if(ret) goto cleanup; + vf->current_link++; + } } + + if(_make_decode_ready(vf)) return OV_EBADLINK; } - - /* the buffered page is the data we want, and we're ready for it; - add it to the stream state */ - ogg_stream_pagein(&vf->os,&og); - + tremor_ogg_stream_pagein(vf->os,&og); } + cleanup: + tremor_ogg_packet_release(&op); + tremor_ogg_page_release(&og); + return ret; } /* if, eg, 64 bit stdio is configured by default, this will build with fseek64 */ -static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){ - if(f==NULL)return(-1); +static int _fseek64_wrap(FILE *f,tremor_ogg_int64_t off,int whence){ + if(f==NULL)return -1; return fseek(f,off,whence); } -static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial, - long ibytes, ov_callbacks callbacks){ - int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1); - ogg_uint32_t *serialno_list=NULL; - int serialno_list_size=0; +static int _ov_open1(void *f,TremorOggVorbis_File *vf,char *initial, + long ibytes, ov_callbacks callbacks){ + int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1); int ret; memset(vf,0,sizeof(*vf)); + + /* Tremor assumes in multiple places that right shift of a signed + integer is an arithmetic shift */ + if( (-1>>1) != -1) return OV_EIMPL; + vf->datasource=f; vf->callbacks = callbacks; /* init the framing state */ - ogg_sync_init(&vf->oy); + vf->oy=tremor_ogg_sync_create(); /* perhaps some data was previously read into a buffer for testing against other stream types. Allow initialization from this - previously read data (especially as we may be reading from a - non-seekable stream) */ + previously read data (as we may be reading from a non-seekable + stream) */ if(initial){ - char *buffer=ogg_sync_buffer(&vf->oy,ibytes); + unsigned char *buffer=tremor_ogg_sync_bufferin(vf->oy,ibytes); memcpy(buffer,initial,ibytes); - ogg_sync_wrote(&vf->oy,ibytes); + tremor_ogg_sync_wrote(vf->oy,ibytes); } /* can we seek? Stevens suggests the seek test was portable */ @@ -895,154 +727,115 @@ static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial, /* No seeking yet; Set up a 'single' (current) logical bitstream entry for partial open */ vf->links=1; - vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi)); - vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc)); - ogg_stream_init(&vf->os,-1); /* fill in the serialno later */ + vf->os=tremor_ogg_stream_create(-1); /* fill in the serialno later */ - /* Fetch all BOS pages, store the vorbis header and all seen serial - numbers, load subsequent vorbis setup headers */ - if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){ + /* Try to fetch the headers, maintaining all the storage */ + if((ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,NULL))<0){ vf->datasource=NULL; ov_clear(vf); - }else{ - /* serial number list for first link needs to be held somewhere - for second stage of seekable stream open; this saves having to - seek/reread first link's serialnumber data then. */ - vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos)); - vf->serialnos[0]=vf->current_serialno=vf->os.serialno; - vf->serialnos[1]=serialno_list_size; - memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos)); - - vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets)); - vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets)); - vf->offsets[0]=0; - vf->dataoffsets[0]=vf->offset; - + }else if(vf->ready_state < PARTOPEN) vf->ready_state=PARTOPEN; - } - if(serialno_list)_ogg_free(serialno_list); - return(ret); + return ret; } -static int _ov_open2(OggVorbis_File *vf){ - if(vf->ready_state != PARTOPEN) return OV_EINVAL; - vf->ready_state=OPENED; +static int _ov_open2(TremorOggVorbis_File *vf){ + if(vf->ready_state < OPENED) + vf->ready_state=OPENED; if(vf->seekable){ int ret=_open_seekable2(vf); if(ret){ vf->datasource=NULL; ov_clear(vf); } - return(ret); - }else - vf->ready_state=STREAMSET; - + return ret; + } return 0; } -/* clear out the OggVorbis_File struct */ -int ov_clear(OggVorbis_File *vf){ +/* clear out the TremorOggVorbis_File struct */ +int ov_clear(TremorOggVorbis_File *vf){ if(vf){ - vorbis_block_clear(&vf->vb); - vorbis_dsp_clear(&vf->vd); - ogg_stream_clear(&vf->os); - - if(vf->vi && vf->links){ - int i; - for(i=0;i<vf->links;i++){ - vorbis_info_clear(vf->vi+i); - vorbis_comment_clear(vf->vc+i); - } - _ogg_free(vf->vi); - _ogg_free(vf->vc); - } - if(vf->dataoffsets)_ogg_free(vf->dataoffsets); - if(vf->pcmlengths)_ogg_free(vf->pcmlengths); - if(vf->serialnos)_ogg_free(vf->serialnos); - if(vf->offsets)_ogg_free(vf->offsets); - ogg_sync_clear(&vf->oy); - if(vf->datasource && vf->callbacks.close_func) - (vf->callbacks.close_func)(vf->datasource); + vorbis_dsp_destroy(vf->vd); + vf->vd=0; + tremor_ogg_stream_destroy(vf->os); + vorbis_info_clear(&vf->vi); + vorbis_comment_clear(&vf->vc); + if(vf->dataoffsets)_tremor_ogg_free(vf->dataoffsets); + if(vf->pcmlengths)_tremor_ogg_free(vf->pcmlengths); + if(vf->serialnos)_tremor_ogg_free(vf->serialnos); + if(vf->offsets)_tremor_ogg_free(vf->offsets); + tremor_ogg_sync_destroy(vf->oy); + + if(vf->datasource)(vf->callbacks.close_func)(vf->datasource); memset(vf,0,sizeof(*vf)); } #ifdef DEBUG_LEAKS _VDBG_dump(); #endif - return(0); + return 0; } -/* inspects the OggVorbis file and finds/documents all the logical +/* inspects the TremorOggVorbis file and finds/documents all the logical bitstreams contained in it. Tries to be tolerant of logical - bitstream sections that are truncated/woogie. + bitstream sections that are truncated/woogie. return: -1) error 0) OK */ -int ov_open_callbacks(void *f,OggVorbis_File *vf, - const char *initial,long ibytes,ov_callbacks callbacks){ +int ov_open_callbacks(void *f,TremorOggVorbis_File *vf,char *initial,long ibytes, + ov_callbacks callbacks){ int ret=_ov_open1(f,vf,initial,ibytes,callbacks); if(ret)return ret; return _ov_open2(vf); } -int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){ +int ov_open(FILE *f,TremorOggVorbis_File *vf,char *initial,long ibytes){ ov_callbacks callbacks = { (size_t (*)(void *, size_t, size_t, void *)) fread, - (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, + (int (*)(void *, tremor_ogg_int64_t, int)) _fseek64_wrap, (int (*)(void *)) fclose, (long (*)(void *)) ftell }; return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks); } - -int ov_fopen(const char *path,OggVorbis_File *vf){ - int ret; - FILE *f = fopen(path,"rb"); - if(!f) return -1; - - ret = ov_open(f,vf,NULL,0); - if(ret) fclose(f); - return ret; -} - - + /* Only partially open the vorbis file; test for Vorbisness, and load the headers for the first chain. Do not seek (although test for seekability). Use ov_test_open to finish opening the file, else ov_clear to close/free it. Same return codes as open. */ -int ov_test_callbacks(void *f,OggVorbis_File *vf, - const char *initial,long ibytes,ov_callbacks callbacks) +int ov_test_callbacks(void *f,TremorOggVorbis_File *vf,char *initial,long ibytes, + ov_callbacks callbacks) { return _ov_open1(f,vf,initial,ibytes,callbacks); } -int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){ +int ov_test(FILE *f,TremorOggVorbis_File *vf,char *initial,long ibytes){ ov_callbacks callbacks = { (size_t (*)(void *, size_t, size_t, void *)) fread, - (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, + (int (*)(void *, tremor_ogg_int64_t, int)) _fseek64_wrap, (int (*)(void *)) fclose, (long (*)(void *)) ftell }; return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks); } - -int ov_test_open(OggVorbis_File *vf){ - if(vf->ready_state!=PARTOPEN)return(OV_EINVAL); + +int ov_test_open(TremorOggVorbis_File *vf){ + if(vf->ready_state!=PARTOPEN)return OV_EINVAL; return _ov_open2(vf); } /* How many logical bitstreams in this physical bitstream? */ -long ov_streams(OggVorbis_File *vf){ +long ov_streams(TremorOggVorbis_File *vf){ return vf->links; } /* Is the FILE * associated with vf seekable? */ -long ov_seekable(OggVorbis_File *vf){ +long ov_seekable(TremorOggVorbis_File *vf){ return vf->seekable; } @@ -1055,12 +848,12 @@ long ov_seekable(OggVorbis_File *vf){ If you want the actual bitrate field settings, get them from the vorbis_info structs */ -long ov_bitrate(OggVorbis_File *vf,int i){ - if(vf->ready_state<OPENED)return(OV_EINVAL); - if(i>=vf->links)return(OV_EINVAL); - if(!vf->seekable && i!=0)return(ov_bitrate(vf,0)); +long ov_bitrate(TremorOggVorbis_File *vf,int i){ + if(vf->ready_state<OPENED)return OV_EINVAL; + if(i>=vf->links)return OV_EINVAL; + if(!vf->seekable && i!=0)return ov_bitrate(vf,0); if(i<0){ - ogg_int64_t bits=0; + tremor_ogg_int64_t bits=0; int i; for(i=0;i<vf->links;i++) bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8; @@ -1068,24 +861,24 @@ long ov_bitrate(OggVorbis_File *vf,int i){ * gcc 3.x on x86 miscompiled this at optimisation level 2 and above, * so this is slightly transformed to make it work. */ - return(bits*1000/ov_time_total(vf,-1)); + return bits*1000/ov_time_total(vf,-1); }else{ if(vf->seekable){ /* return the actual bitrate */ - return((vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i)); + return (vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i); }else{ /* return nominal if set */ - if(vf->vi[i].bitrate_nominal>0){ - return vf->vi[i].bitrate_nominal; + if(vf->vi.bitrate_nominal>0){ + return vf->vi.bitrate_nominal; }else{ - if(vf->vi[i].bitrate_upper>0){ - if(vf->vi[i].bitrate_lower>0){ - return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2; - }else{ - return vf->vi[i].bitrate_upper; - } - } - return(OV_FALSE); + if(vf->vi.bitrate_upper>0){ + if(vf->vi.bitrate_lower>0){ + return (vf->vi.bitrate_upper+vf->vi.bitrate_lower)/2; + }else{ + return vf->vi.bitrate_upper; + } + } + return OV_FALSE; } } } @@ -1093,84 +886,83 @@ long ov_bitrate(OggVorbis_File *vf,int i){ /* returns the actual bitrate since last call. returns -1 if no additional data to offer since last call (or at beginning of stream), - EINVAL if stream is only partially open + EINVAL if stream is only partially open */ -long ov_bitrate_instant(OggVorbis_File *vf){ - int link=(vf->seekable?vf->current_link:0); +long ov_bitrate_instant(TremorOggVorbis_File *vf){ long ret; - if(vf->ready_state<OPENED)return(OV_EINVAL); - if(vf->samptrack==0)return(OV_FALSE); - ret=vf->bittrack/vf->samptrack*vf->vi[link].rate; + if(vf->ready_state<OPENED)return OV_EINVAL; + if(vf->samptrack==0)return OV_FALSE; + ret=vf->bittrack/vf->samptrack*vf->vi.rate; vf->bittrack=0; vf->samptrack=0; - return(ret); + return ret; } /* Guess */ -long ov_serialnumber(OggVorbis_File *vf,int i){ - if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1)); - if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1)); +long ov_serialnumber(TremorOggVorbis_File *vf,int i){ + if(i>=vf->links)return ov_serialnumber(vf,vf->links-1); + if(!vf->seekable && i>=0)return ov_serialnumber(vf,-1); if(i<0){ - return(vf->current_serialno); + return vf->current_serialno; }else{ - return(vf->serialnos[i]); + return vf->serialnos[i]; } } /* returns: total raw (compressed) length of content if i==-1 raw (compressed) length of that logical bitstream for i==0 to n - OV_EINVAL if the stream is not seekable (we can't know the length) - or if stream is only partially open + OV_EINVAL if the stream is not seekable (we can't know the length) + or if stream is only partially open */ -ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){ - if(vf->ready_state<OPENED)return(OV_EINVAL); - if(!vf->seekable || i>=vf->links)return(OV_EINVAL); +tremor_ogg_int64_t ov_raw_total(TremorOggVorbis_File *vf,int i){ + if(vf->ready_state<OPENED)return OV_EINVAL; + if(!vf->seekable || i>=vf->links)return OV_EINVAL; if(i<0){ - ogg_int64_t acc=0; + tremor_ogg_int64_t acc=0; int i; for(i=0;i<vf->links;i++) acc+=ov_raw_total(vf,i); - return(acc); + return acc; }else{ - return(vf->offsets[i+1]-vf->offsets[i]); + return vf->offsets[i+1]-vf->offsets[i]; } } /* returns: total PCM length (samples) of content if i==-1 PCM length - (samples) of that logical bitstream for i==0 to n - OV_EINVAL if the stream is not seekable (we can't know the - length) or only partially open + (samples) of that logical bitstream for i==0 to n + OV_EINVAL if the stream is not seekable (we can't know the + length) or only partially open */ -ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){ - if(vf->ready_state<OPENED)return(OV_EINVAL); - if(!vf->seekable || i>=vf->links)return(OV_EINVAL); +tremor_ogg_int64_t ov_pcm_total(TremorOggVorbis_File *vf,int i){ + if(vf->ready_state<OPENED)return OV_EINVAL; + if(!vf->seekable || i>=vf->links)return OV_EINVAL; if(i<0){ - ogg_int64_t acc=0; + tremor_ogg_int64_t acc=0; int i; for(i=0;i<vf->links;i++) acc+=ov_pcm_total(vf,i); - return(acc); + return acc; }else{ - return(vf->pcmlengths[i*2+1]); + return vf->pcmlengths[i*2+1]; } } /* returns: total milliseconds of content if i==-1 milliseconds in that logical bitstream for i==0 to n - OV_EINVAL if the stream is not seekable (we can't know the - length) or only partially open + OV_EINVAL if the stream is not seekable (we can't know the + length) or only partially open */ -ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){ - if(vf->ready_state<OPENED)return(OV_EINVAL); - if(!vf->seekable || i>=vf->links)return(OV_EINVAL); +tremor_ogg_int64_t ov_time_total(TremorOggVorbis_File *vf,int i){ + if(vf->ready_state<OPENED)return OV_EINVAL; + if(!vf->seekable || i>=vf->links)return OV_EINVAL; if(i<0){ - ogg_int64_t acc=0; + tremor_ogg_int64_t acc=0; int i; for(i=0;i<vf->links;i++) acc+=ov_time_total(vf,i); - return(acc); + return acc; }else{ - return(((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi[i].rate); + return ((tremor_ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi.rate; } } @@ -1181,33 +973,27 @@ ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){ returns zero on success, nonzero on failure */ -int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ - ogg_stream_state work_os; - int ret; - - if(vf->ready_state<OPENED)return(OV_EINVAL); +int ov_raw_seek(TremorOggVorbis_File *vf,tremor_ogg_int64_t pos){ + tremor_ogg_stream_state *work_os=NULL; + tremor_ogg_page og={0,0,0,0}; + tremor_ogg_packet op={0,0,0,0,0,0}; + + if(vf->ready_state<OPENED)return OV_EINVAL; if(!vf->seekable) - return(OV_ENOSEEK); /* don't dump machine if we can't seek */ - - if(pos<0 || pos>vf->end)return(OV_EINVAL); + return OV_ENOSEEK; /* don't dump machine if we can't seek */ - /* is the seek position outside our current link [if any]? */ - if(vf->ready_state>=STREAMSET){ - if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1]) - _decode_clear(vf); /* clear out stream state */ - } + if(pos<0 || pos>vf->end)return OV_EINVAL; /* don't yet clear out decoding machine (if it's initialized), in the case we're in the same link. Restart the decode lapping, and let _fetch_and_process_packet deal with a potential bitstream boundary */ vf->pcm_offset=-1; - ogg_stream_reset_serialno(&vf->os, - vf->current_serialno); /* must set serialno */ - vorbis_synthesis_restart(&vf->vd); - - ret=_seek_helper(vf,pos); - if(ret)goto seek_error; + tremor_ogg_stream_reset_serialno(vf->os, + vf->current_serialno); /* must set serialno */ + vorbis_dsp_restart(vf->vd); + + _seek_helper(vf,pos); /* we need to make sure the pcm_offset is set, but we don't want to advance the raw cursor past good packets just to get to the first @@ -1216,428 +1002,281 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ So, a hack. We use two stream states; a local scratch state and the shared vf->os stream state. We use the local state to - scan, and the shared state as a buffer for later decode. + scan, and the shared state as a buffer for later decode. Unfortuantely, on the last page we still advance to last packet because the granulepos on the last page is not necessarily on a packet boundary, and we need to make sure the granpos is - correct. + correct. */ { - ogg_page og; - ogg_packet op; int lastblock=0; int accblock=0; - int thisblock=0; - int lastflag=0; - int firstflag=0; - ogg_int64_t pagepos=-1; - - ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */ - ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE - return from not necessarily - starting from the beginning */ + int thisblock; + int eosflag; + work_os=tremor_ogg_stream_create(vf->current_serialno); /* get the memory ready */ while(1){ if(vf->ready_state>=STREAMSET){ - /* snarf/scan a packet if we can */ - int result=ogg_stream_packetout(&work_os,&op); - - if(result>0){ - - if(vf->vi[vf->current_link].codec_setup){ - thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); - if(thisblock<0){ - ogg_stream_packetout(&vf->os,NULL); - thisblock=0; - }else{ - - /* We can't get a guaranteed correct pcm position out of the - last page in a stream because it might have a 'short' - granpos, which can only be detected in the presence of a - preceding page. However, if the last page is also the first - page, the granpos rules of a first page take precedence. Not - only that, but for first==last, the EOS page must be treated - as if its a normal first page for the stream to open/play. */ - if(lastflag && !firstflag) - ogg_stream_packetout(&vf->os,NULL); - else - if(lastblock)accblock+=(lastblock+thisblock)>>2; - } - - if(op.granulepos!=-1){ - int i,link=vf->current_link; - ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2]; - if(granulepos<0)granulepos=0; - - for(i=0;i<link;i++) - granulepos+=vf->pcmlengths[i*2+1]; - vf->pcm_offset=granulepos-accblock; - if(vf->pcm_offset<0)vf->pcm_offset=0; - break; - } - lastblock=thisblock; - continue; - }else - ogg_stream_packetout(&vf->os,NULL); - } + /* snarf/scan a packet if we can */ + int result=tremor_ogg_stream_packetout(work_os,&op); + + if(result>0){ + + if(vf->vi.codec_setup){ + thisblock=vorbis_packet_blocksize(&vf->vi,&op); + if(thisblock<0){ + tremor_ogg_stream_packetout(vf->os,NULL); + thisblock=0; + }else{ + + if(eosflag) + tremor_ogg_stream_packetout(vf->os,NULL); + else + if(lastblock)accblock+=(lastblock+thisblock)>>2; + } + + if(op.granulepos!=-1){ + int i,link=vf->current_link; + tremor_ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2]; + if(granulepos<0)granulepos=0; + + for(i=0;i<link;i++) + granulepos+=vf->pcmlengths[i*2+1]; + vf->pcm_offset=granulepos-accblock; + break; + } + lastblock=thisblock; + continue; + }else + tremor_ogg_stream_packetout(vf->os,NULL); + } } - + if(!lastblock){ - pagepos=_get_next_page(vf,&og,-1); - if(pagepos<0){ - vf->pcm_offset=ov_pcm_total(vf,-1); - break; - } + if(_get_next_page(vf,&og,-1)<0){ + vf->pcm_offset=ov_pcm_total(vf,-1); + break; + } }else{ - /* huh? Bogus stream with packets but no granulepos */ - vf->pcm_offset=-1; - break; - } - - /* has our decoding just traversed a bitstream boundary? */ - if(vf->ready_state>=STREAMSET){ - if(vf->current_serialno!=ogg_page_serialno(&og)){ - - /* two possibilities: - 1) our decoding just traversed a bitstream boundary - 2) another stream is multiplexed into this logical section? */ - - if(ogg_page_bos(&og)){ - /* we traversed */ - _decode_clear(vf); /* clear out stream state */ - ogg_stream_clear(&work_os); - } /* else, do nothing; next loop will scoop another page */ - } + /* huh? Bogus stream with packets but no granulepos */ + vf->pcm_offset=-1; + break; } + + /* did we just grab a page from other than current link? */ + if(vf->ready_state>=STREAMSET) + if(vf->current_serialno!=tremor_ogg_page_serialno(&og)){ + _decode_clear(vf); /* clear out stream state */ + tremor_ogg_stream_destroy(work_os); + } if(vf->ready_state<STREAMSET){ - int link; - ogg_uint32_t serialno = ogg_page_serialno(&og); - - for(link=0;link<vf->links;link++) - if(vf->serialnos[link]==serialno)break; - - if(link==vf->links) continue; /* not the desired Vorbis - bitstream section; keep - trying */ - vf->current_link=link; - vf->current_serialno=serialno; - ogg_stream_reset_serialno(&vf->os,serialno); - ogg_stream_reset_serialno(&work_os,serialno); - vf->ready_state=STREAMSET; - firstflag=(pagepos<=vf->dataoffsets[link]); + int link; + + vf->current_serialno=tremor_ogg_page_serialno(&og); + for(link=0;link<vf->links;link++) + if(vf->serialnos[link]==vf->current_serialno)break; + if(link==vf->links) + goto seek_error; /* sign of a bogus stream. error out, + leave machine uninitialized */ + + /* need to initialize machine to this link */ + { + int ret=_set_link_number_preserve_pos(vf,link); + if(ret) goto seek_error; + } + tremor_ogg_stream_reset_serialno(vf->os,vf->current_serialno); + tremor_ogg_stream_reset_serialno(work_os,vf->current_serialno); + + + } + + { + tremor_ogg_page dup; + tremor_ogg_page_dup(&dup,&og); + eosflag=tremor_ogg_page_eos(&og); + tremor_ogg_stream_pagein(vf->os,&og); + tremor_ogg_stream_pagein(work_os,&dup); } - - ogg_stream_pagein(&vf->os,&og); - ogg_stream_pagein(&work_os,&og); - lastflag=ogg_page_eos(&og); - } } - ogg_stream_clear(&work_os); + tremor_ogg_packet_release(&op); + tremor_ogg_page_release(&og); + tremor_ogg_stream_destroy(work_os); vf->bittrack=0; vf->samptrack=0; - return(0); + return 0; seek_error: + tremor_ogg_packet_release(&op); + tremor_ogg_page_release(&og); + /* dump the machine so we're in a known state */ vf->pcm_offset=-1; - ogg_stream_clear(&work_os); + tremor_ogg_stream_destroy(work_os); _decode_clear(vf); return OV_EBADLINK; } -/* rescales the number x from the range of [0,from] to [0,to] - x is in the range [0,from] - from, to are in the range [1, 1<<62-1] */ -ogg_int64_t rescale64(ogg_int64_t x, ogg_int64_t from, ogg_int64_t to){ - ogg_int64_t frac=0; - ogg_int64_t ret=0; - int i; - if(x >= from) return to; - if(x <= 0) return 0; - - for(i=0;i<64;i++){ - if(x>=from){ - frac|=1; - x-=from; - } - x<<=1; - frac<<=1; - } - - for(i=0;i<64;i++){ - if(frac & 1){ - ret+=to; - } - frac>>=1; - ret>>=1; - } - - return ret; -} - /* Page granularity seek (faster than sample granularity because we don't do the last bit of decode to find a specific sample). - Seek to the last [granule marked] page preceding the specified pos + Seek to the last [granule marked] page preceeding the specified pos location, such that decoding past the returned point will quickly arrive at the requested position. */ -int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ +int ov_pcm_seek_page(TremorOggVorbis_File *vf,tremor_ogg_int64_t pos){ int link=-1; - ogg_int64_t result=0; - ogg_int64_t total=ov_pcm_total(vf,-1); - - if(vf->ready_state<OPENED)return(OV_EINVAL); - if(!vf->seekable)return(OV_ENOSEEK); - - if(pos<0 || pos>total)return(OV_EINVAL); - + tremor_ogg_int64_t result=0; + tremor_ogg_int64_t total=ov_pcm_total(vf,-1); + tremor_ogg_page og={0,0,0,0}; + tremor_ogg_packet op={0,0,0,0,0,0}; + + if(vf->ready_state<OPENED)return OV_EINVAL; + if(!vf->seekable)return OV_ENOSEEK; + if(pos<0 || pos>total)return OV_EINVAL; + /* which bitstream section does this pcm offset occur in? */ for(link=vf->links-1;link>=0;link--){ total-=vf->pcmlengths[link*2+1]; if(pos>=total)break; } - /* Search within the logical bitstream for the page with the highest - pcm_pos preceding pos. If we're looking for a position on the - first page, bisection will halt without finding our position as - it's before the first explicit granulepos fencepost. That case is - handled separately below. - - There is a danger here; missing pages or incorrect frame number - information in the bitstream could make our task impossible. - Account for that (it would be an error condition) */ - /* new search algorithm originally by HB (Nicholas Vinen) */ - - { - ogg_int64_t end=vf->offsets[link+1]; - ogg_int64_t begin=vf->dataoffsets[link]; - ogg_int64_t begintime = vf->pcmlengths[link*2]; - ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime; - ogg_int64_t target=pos-total+begintime; - ogg_int64_t best=-1; - int got_page=0; - - ogg_page og; - - /* if we have only one page, there will be no bisection. Grab the page here */ - if(begin==end){ - result=_seek_helper(vf,begin); - if(result) goto seek_error; + if(link!=vf->current_link){ + int ret=_set_link_number(vf,link); + if(ret) goto seek_error; + }else{ + vorbis_dsp_restart(vf->vd); + } - result=_get_next_page(vf,&og,1); - if(result<0) goto seek_error; + tremor_ogg_stream_reset_serialno(vf->os,vf->serialnos[link]); - got_page=1; - } + /* search within the logical bitstream for the page with the highest + pcm_pos preceeding (or equal to) pos. There is a danger here; + missing pages or incorrect frame number information in the + bitstream could make our task impossible. Account for that (it + would be an error condition) */ - /* bisection loop */ + /* new search algorithm by HB (Nicholas Vinen) */ + { + tremor_ogg_int64_t end=vf->offsets[link+1]; + tremor_ogg_int64_t begin=vf->offsets[link]; + tremor_ogg_int64_t begintime = vf->pcmlengths[link*2]; + tremor_ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime; + tremor_ogg_int64_t target=pos-total+begintime; + tremor_ogg_int64_t best=begin; + while(begin<end){ - ogg_int64_t bisect; - + tremor_ogg_int64_t bisect; + if(end-begin<CHUNKSIZE){ - bisect=begin; + bisect=begin; }else{ - /* take a (pretty decent) guess. */ - bisect=begin + rescale64(target-begintime, - endtime-begintime, - end-begin) - CHUNKSIZE; - if(bisect<begin+CHUNKSIZE) - bisect=begin; + /* take a (pretty decent) guess. */ + bisect=begin + + (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE; + if(bisect<=begin) + bisect=begin+1; } - - result=_seek_helper(vf,bisect); - if(result) goto seek_error; - - /* read loop within the bisection loop */ + + _seek_helper(vf,bisect); + while(begin<end){ - result=_get_next_page(vf,&og,end-vf->offset); - if(result==OV_EREAD) goto seek_error; - if(result<0){ - /* there is no next page! */ - if(bisect<=begin+1) - /* No bisection left to perform. We've either found the - best candidate already or failed. Exit loop. */ - end=begin; - else{ - /* We tried to load a fraction of the last page; back up a - bit and try to get the whole last page */ - if(bisect==0) goto seek_error; - bisect-=CHUNKSIZE; - - /* don't repeat/loop on a read we've already performed */ - if(bisect<=begin)bisect=begin+1; - - /* seek and continue bisection */ - result=_seek_helper(vf,bisect); - if(result) goto seek_error; - } - }else{ - ogg_int64_t granulepos; - got_page=1; - - /* got a page. analyze it */ - /* only consider pages from primary vorbis stream */ - if(ogg_page_serialno(&og)!=vf->serialnos[link]) - continue; - - /* only consider pages with the granulepos set */ - granulepos=ogg_page_granulepos(&og); - if(granulepos==-1)continue; - - if(granulepos<target){ - /* this page is a successful candidate! Set state */ - - best=result; /* raw offset of packet with granulepos */ - begin=vf->offset; /* raw offset of next page */ - begintime=granulepos; - - /* if we're before our target but within a short distance, - don't bisect; read forward */ - if(target-begintime>44100)break; - - bisect=begin; /* *not* begin + 1 as above */ - }else{ - - /* This is one of our pages, but the granpos is - post-target; it is not a bisection return - candidate. (The only way we'd use it is if it's the - first page in the stream; we handle that case later - outside the bisection) */ - if(bisect<=begin+1){ - /* No bisection left to perform. We've either found the - best candidate already or failed. Exit loop. */ - end=begin; - }else{ - if(end==vf->offset){ - /* bisection read to the end; use the known page - boundary (result) to update bisection, back up a - little bit, and try again */ - end=result; - bisect-=CHUNKSIZE; - if(bisect<=begin)bisect=begin+1; - result=_seek_helper(vf,bisect); - if(result) goto seek_error; - }else{ - /* Normal bisection */ - end=bisect; - endtime=granulepos; - break; - } - } - } - } + result=_get_next_page(vf,&og,end-vf->offset); + if(result==OV_EREAD) goto seek_error; + if(result<0){ + if(bisect<=begin+1) + end=begin; /* found it */ + else{ + if(bisect==0) goto seek_error; + bisect-=CHUNKSIZE; + if(bisect<=begin)bisect=begin+1; + _seek_helper(vf,bisect); + } + }else{ + tremor_ogg_int64_t granulepos=tremor_ogg_page_granulepos(&og); + if(granulepos==-1)continue; + if(granulepos<target){ + best=result; /* raw offset of packet with granulepos */ + begin=vf->offset; /* raw offset of next page */ + begintime=granulepos; + + if(target-begintime>44100)break; + bisect=begin; /* *not* begin + 1 */ + }else{ + if(bisect<=begin+1) + end=begin; /* found it */ + else{ + if(end==vf->offset){ /* we're pretty close - we'd be stuck in */ + end=result; + bisect-=CHUNKSIZE; /* an endless loop otherwise. */ + if(bisect<=begin)bisect=begin+1; + _seek_helper(vf,bisect); + }else{ + end=result; + endtime=granulepos; + break; + } + } + } + } } } - /* Out of bisection: did it 'fail?' */ - if(best == -1){ - - /* Check the 'looking for data in first page' special case; - bisection would 'fail' because our search target was before the - first PCM granule position fencepost. */ - - if(got_page && - begin == vf->dataoffsets[link] && - ogg_page_serialno(&og)==vf->serialnos[link]){ - - /* Yes, this is the beginning-of-stream case. We already have - our page, right at the beginning of PCM data. Set state - and return. */ - - vf->pcm_offset=total; - - if(link!=vf->current_link){ - /* Different link; dump entire decode machine */ - _decode_clear(vf); - - vf->current_link=link; - vf->current_serialno=vf->serialnos[link]; - vf->ready_state=STREAMSET; - - }else{ - vorbis_synthesis_restart(&vf->vd); - } - - ogg_stream_reset_serialno(&vf->os,vf->current_serialno); - ogg_stream_pagein(&vf->os,&og); - - }else - goto seek_error; - - }else{ - - /* Bisection found our page. seek to it, update pcm offset. Easier case than - raw_seek, don't keep packets preceding granulepos. */ - - ogg_page og; - ogg_packet op; - + /* found our page. seek to it, update pcm offset. Easier case than + raw_seek, don't keep packets preceeding granulepos. */ + { + /* seek */ - result=_seek_helper(vf,best); + _seek_helper(vf,best); vf->pcm_offset=-1; - if(result) goto seek_error; - result=_get_next_page(vf,&og,-1); - if(result<0) goto seek_error; - - if(link!=vf->current_link){ - /* Different link; dump entire decode machine */ - _decode_clear(vf); - - vf->current_link=link; - vf->current_serialno=vf->serialnos[link]; - vf->ready_state=STREAMSET; - - }else{ - vorbis_synthesis_restart(&vf->vd); + + if(_get_next_page(vf,&og,-1)<0){ + tremor_ogg_page_release(&og); + return OV_EOF; /* shouldn't happen */ } - ogg_stream_reset_serialno(&vf->os,vf->current_serialno); - ogg_stream_pagein(&vf->os,&og); + tremor_ogg_stream_pagein(vf->os,&og); /* pull out all but last packet; the one with granulepos */ while(1){ - result=ogg_stream_packetpeek(&vf->os,&op); - if(result==0){ - /* No packet returned; we exited the bisection with 'best' - pointing to a page with a granule position, so the packet - finishing this page ('best') originated on a preceding - page. Keep fetching previous pages until we get one with - a granulepos or without the 'continued' flag set. Then - just use raw_seek for simplicity. */ - /* Do not rewind past the beginning of link data; if we do, - it's either a bug or a broken stream */ - result=best; - while(result>vf->dataoffsets[link]){ - result=_get_prev_page(vf,result,&og); - if(result<0) goto seek_error; - if(ogg_page_serialno(&og)==vf->current_serialno && - (ogg_page_granulepos(&og)>-1 || - !ogg_page_continued(&og))){ - return ov_raw_seek(vf,result); - } - } - } - if(result<0){ - result = OV_EBADPACKET; - goto seek_error; - } - if(op.granulepos!=-1){ - vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; - if(vf->pcm_offset<0)vf->pcm_offset=0; - vf->pcm_offset+=total; - break; - }else - result=ogg_stream_packetout(&vf->os,NULL); + result=tremor_ogg_stream_packetpeek(vf->os,&op); + if(result==0){ + /* !!! the packet finishing this page originated on a + preceeding page. Keep fetching previous pages until we + get one with a granulepos or without the 'continued' flag + set. Then just use raw_seek for simplicity. */ + + _seek_helper(vf,best); + + while(1){ + result=_get_prev_page(vf,&og); + if(result<0) goto seek_error; + if(tremor_ogg_page_granulepos(&og)>-1 || + !tremor_ogg_page_continued(&og)){ + return ov_raw_seek(vf,result); + } + vf->offset=result; + } + } + if(result<0){ + result = OV_EBADPACKET; + goto seek_error; + } + if(op.granulepos!=-1){ + vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; + if(vf->pcm_offset<0)vf->pcm_offset=0; + vf->pcm_offset+=total; + break; + }else + result=tremor_ogg_stream_packetout(vf->os,NULL); } } } - + /* verify result */ if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){ result=OV_EFAULT; @@ -1645,89 +1284,98 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ } vf->bittrack=0; vf->samptrack=0; - return(0); + tremor_ogg_page_release(&og); + tremor_ogg_packet_release(&op); + return 0; + seek_error: + + tremor_ogg_page_release(&og); + tremor_ogg_packet_release(&op); + /* dump machine so we're in a known state */ vf->pcm_offset=-1; _decode_clear(vf); return (int)result; } -/* seek to a sample offset relative to the decompressed pcm stream +/* seek to a sample offset relative to the decompressed pcm stream returns zero on success, nonzero on failure */ -int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ +int ov_pcm_seek(TremorOggVorbis_File *vf,tremor_ogg_int64_t pos){ + tremor_ogg_packet op={0,0,0,0,0,0}; + tremor_ogg_page og={0,0,0,0}; int thisblock,lastblock=0; int ret=ov_pcm_seek_page(vf,pos); - if(ret<0)return(ret); - if((ret=_make_decode_ready(vf)))return ret; + if(ret<0)return ret; + if(_make_decode_ready(vf))return OV_EBADLINK; /* discard leading packets we don't need for the lapping of the position we want; don't decode them */ while(1){ - ogg_packet op; - ogg_page og; - int ret=ogg_stream_packetpeek(&vf->os,&op); + int ret=tremor_ogg_stream_packetpeek(vf->os,&op); if(ret>0){ - thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); + thisblock=vorbis_packet_blocksize(&vf->vi,&op); if(thisblock<0){ - ogg_stream_packetout(&vf->os,NULL); - continue; /* non audio packet */ + tremor_ogg_stream_packetout(vf->os,NULL); + continue; /* non audio packet */ } if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; - + if(vf->pcm_offset+((thisblock+ - vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break; - + vorbis_info_blocksize(&vf->vi,1))>>2)>=pos)break; + /* remove the packet from packet queue and track its granulepos */ - ogg_stream_packetout(&vf->os,NULL); - vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with - only tracking, no - pcm_decode */ - vorbis_synthesis_blockin(&vf->vd,&vf->vb); - + tremor_ogg_stream_packetout(vf->os,NULL); + vorbis_dsp_synthesis(vf->vd,&op,0); /* set up a vb with + only tracking, no + pcm_decode */ + /* end of logical stream case is hard, especially with exact - length positioning. */ - + length positioning. */ + if(op.granulepos>-1){ - int i; - /* always believe the stream markers */ - vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; - if(vf->pcm_offset<0)vf->pcm_offset=0; - for(i=0;i<vf->current_link;i++) - vf->pcm_offset+=vf->pcmlengths[i*2+1]; + int i; + /* always believe the stream markers */ + vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; + if(vf->pcm_offset<0)vf->pcm_offset=0; + for(i=0;i<vf->current_link;i++) + vf->pcm_offset+=vf->pcmlengths[i*2+1]; } - + lastblock=thisblock; - + }else{ if(ret<0 && ret!=OV_HOLE)break; - + /* suck in a new page */ if(_get_next_page(vf,&og,-1)<0)break; - if(ogg_page_bos(&og))_decode_clear(vf); - + if(vf->current_serialno!=tremor_ogg_page_serialno(&og))_decode_clear(vf); + if(vf->ready_state<STREAMSET){ - ogg_uint32_t serialno=ogg_page_serialno(&og); - int link; - - for(link=0;link<vf->links;link++) - if(vf->serialnos[link]==serialno)break; - if(link==vf->links) continue; - vf->current_link=link; - - vf->ready_state=STREAMSET; - vf->current_serialno=ogg_page_serialno(&og); - ogg_stream_reset_serialno(&vf->os,serialno); - ret=_make_decode_ready(vf); - if(ret)return ret; - lastblock=0; + int link,ret; + + vf->current_serialno=tremor_ogg_page_serialno(&og); + for(link=0;link<vf->links;link++) + if(vf->serialnos[link]==vf->current_serialno)break; + if(link==vf->links){ + tremor_ogg_page_release(&og); + tremor_ogg_packet_release(&op); + return OV_EBADLINK; + } + + + vf->current_link=link; + ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); + if(ret) return ret; + if(_make_decode_ready(vf))return OV_EBADLINK; + lastblock=0; } - ogg_stream_pagein(&vf->os,&og); + tremor_ogg_stream_pagein(vf->os,&og); } } @@ -1736,104 +1384,107 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ /* discard samples until we reach the desired position. Crossing a logical bitstream boundary with abandon is OK. */ while(vf->pcm_offset<pos){ - ogg_int64_t target=pos-vf->pcm_offset; - long samples=vorbis_synthesis_pcmout(&vf->vd,NULL); + tremor_ogg_int64_t target=pos-vf->pcm_offset; + long samples=vorbis_dsp_pcmout(vf->vd,NULL,0); if(samples>target)samples=target; - vorbis_synthesis_read(&vf->vd,samples); + vorbis_dsp_read(vf->vd,samples); vf->pcm_offset+=samples; - + if(samples<target) - if(_fetch_and_process_packet(vf,NULL,1,1)<=0) - vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */ + if(_fetch_and_process_packet(vf,1,1)<=0) + vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */ } + + tremor_ogg_page_release(&og); + tremor_ogg_packet_release(&op); return 0; } -/* seek to a playback time relative to the decompressed pcm stream +/* seek to a playback time relative to the decompressed pcm stream returns zero on success, nonzero on failure */ -int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){ +int ov_time_seek(TremorOggVorbis_File *vf,tremor_ogg_int64_t milliseconds){ /* translate time to PCM position and call ov_pcm_seek */ int link=-1; - ogg_int64_t pcm_total=0; - ogg_int64_t time_total=0; - - if(vf->ready_state<OPENED)return(OV_EINVAL); - if(!vf->seekable)return(OV_ENOSEEK); - if(milliseconds<0)return(OV_EINVAL); + tremor_ogg_int64_t pcm_total=ov_pcm_total(vf,-1); + tremor_ogg_int64_t time_total=ov_time_total(vf,-1); + if(vf->ready_state<OPENED)return OV_EINVAL; + if(!vf->seekable)return OV_ENOSEEK; + if(milliseconds<0 || milliseconds>time_total)return OV_EINVAL; + /* which bitstream section does this time offset occur in? */ - for(link=0;link<vf->links;link++){ - ogg_int64_t addsec = ov_time_total(vf,link); - if(milliseconds<time_total+addsec)break; - time_total+=addsec; - pcm_total+=vf->pcmlengths[link*2+1]; + for(link=vf->links-1;link>=0;link--){ + pcm_total-=vf->pcmlengths[link*2+1]; + time_total-=ov_time_total(vf,link); + if(milliseconds>=time_total)break; } - if(link==vf->links)return(OV_EINVAL); - /* enough information to convert time offset to pcm offset */ { - ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000; - return(ov_pcm_seek(vf,target)); + int ret=_set_link_number(vf,link); + if(ret)return ret; + return + ov_pcm_seek(vf,pcm_total+(milliseconds-time_total)* + vf->vi.rate/1000); } } /* page-granularity version of ov_time_seek returns zero on success, nonzero on failure */ -int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t milliseconds){ +int ov_time_seek_page(TremorOggVorbis_File *vf,tremor_ogg_int64_t milliseconds){ /* translate time to PCM position and call ov_pcm_seek */ int link=-1; - ogg_int64_t pcm_total=0; - ogg_int64_t time_total=0; - - if(vf->ready_state<OPENED)return(OV_EINVAL); - if(!vf->seekable)return(OV_ENOSEEK); - if(milliseconds<0)return(OV_EINVAL); + tremor_ogg_int64_t pcm_total=ov_pcm_total(vf,-1); + tremor_ogg_int64_t time_total=ov_time_total(vf,-1); + if(vf->ready_state<OPENED)return OV_EINVAL; + if(!vf->seekable)return OV_ENOSEEK; + if(milliseconds<0 || milliseconds>time_total)return OV_EINVAL; + /* which bitstream section does this time offset occur in? */ - for(link=0;link<vf->links;link++){ - ogg_int64_t addsec = ov_time_total(vf,link); - if(milliseconds<time_total+addsec)break; - time_total+=addsec; - pcm_total+=vf->pcmlengths[link*2+1]; + for(link=vf->links-1;link>=0;link--){ + pcm_total-=vf->pcmlengths[link*2+1]; + time_total-=ov_time_total(vf,link); + if(milliseconds>=time_total)break; } - if(link==vf->links)return(OV_EINVAL); - /* enough information to convert time offset to pcm offset */ { - ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000; - return(ov_pcm_seek_page(vf,target)); + int ret=_set_link_number(vf,link); + if(ret)return ret; + return + ov_pcm_seek_page(vf,pcm_total+(milliseconds-time_total)* + vf->vi.rate/1000); } } /* tell the current stream offset cursor. Note that seek followed by tell will likely not give the set offset due to caching */ -ogg_int64_t ov_raw_tell(OggVorbis_File *vf){ - if(vf->ready_state<OPENED)return(OV_EINVAL); - return(vf->offset); +tremor_ogg_int64_t ov_raw_tell(TremorOggVorbis_File *vf){ + if(vf->ready_state<OPENED)return OV_EINVAL; + return vf->offset; } /* return PCM offset (sample) of next PCM sample to be read */ -ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){ - if(vf->ready_state<OPENED)return(OV_EINVAL); - return(vf->pcm_offset); +tremor_ogg_int64_t ov_pcm_tell(TremorOggVorbis_File *vf){ + if(vf->ready_state<OPENED)return OV_EINVAL; + return vf->pcm_offset; } /* return time offset (milliseconds) of next PCM sample to be read */ -ogg_int64_t ov_time_tell(OggVorbis_File *vf){ +tremor_ogg_int64_t ov_time_tell(TremorOggVorbis_File *vf){ int link=0; - ogg_int64_t pcm_total=0; - ogg_int64_t time_total=0; - - if(vf->ready_state<OPENED)return(OV_EINVAL); + tremor_ogg_int64_t pcm_total=0; + tremor_ogg_int64_t time_total=0; + + if(vf->ready_state<OPENED)return OV_EINVAL; if(vf->seekable){ pcm_total=ov_pcm_total(vf,-1); time_total=ov_time_total(vf,-1); - + /* which bitstream section does this time offset occur in? */ for(link=vf->links-1;link>=0;link--){ pcm_total-=vf->pcmlengths[link*2+1]; @@ -1842,50 +1493,38 @@ ogg_int64_t ov_time_tell(OggVorbis_File *vf){ } } - return(time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi[link].rate); + return time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi.rate; } /* link: -1) return the vorbis_info struct for the bitstream section currently being decoded 0-n) to request information for a specific bitstream section - + In the case of a non-seekable bitstream, any call returns the current bitstream. NULL in the case that the machine is not initialized */ -vorbis_info *ov_info(OggVorbis_File *vf,int link){ +vorbis_info *ov_info(TremorOggVorbis_File *vf,int link){ if(vf->seekable){ - if(link<0) - if(vf->ready_state>=STREAMSET) - return vf->vi+vf->current_link; - else - return vf->vi; - else - if(link>=vf->links) - return NULL; - else - return vf->vi+link; - }else{ - return vf->vi; + if(link>=vf->links)return NULL; + if(link>=0){ + int ret=_set_link_number_preserve_pos(vf,link); + if(ret)return NULL; + } } + return &vf->vi; } /* grr, strong typing, grr, no templates/inheritence, grr */ -vorbis_comment *ov_comment(OggVorbis_File *vf,int link){ +vorbis_comment *ov_comment(TremorOggVorbis_File *vf,int link){ if(vf->seekable){ - if(link<0) - if(vf->ready_state>=STREAMSET) - return vf->vc+vf->current_link; - else - return vf->vc; - else - if(link>=vf->links) - return NULL; - else - return vf->vc+link; - }else{ - return vf->vc; + if(link>=vf->links)return NULL; + if(link>=0){ + int ret=_set_link_number_preserve_pos(vf,link); + if(ret)return NULL; + } } + return &vf->vc; } /* up to this point, everything could more or less hide the multiple @@ -1904,65 +1543,47 @@ vorbis_comment *ov_comment(OggVorbis_File *vf,int link){ functions above are aware of this dichotomy). input values: buffer) a buffer to hold packed PCM data for return - bytes_req) the byte length requested to be placed into buffer + length) the byte length requested to be placed into buffer return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL) 0) EOF - n) number of bytes of PCM actually returned. The - below works on a packet-by-packet basis, so the - return length is not related to the 'length' passed - in, just guaranteed to fit. + n) number of bytes of PCM actually returned. The + below works on a packet-by-packet basis, so the + return length is not related to the 'length' passed + in, just guaranteed to fit. - *section) set to the logical bitstream number */ + *section) set to the logical bitstream number */ -long ov_read(OggVorbis_File *vf,char *buffer,int bytes_req,int *bitstream){ - int i,j; +long ov_read(TremorOggVorbis_File *vf,void *buffer,int bytes_req,int *bitstream){ - ogg_int32_t **pcm; long samples; + long channels; - if(vf->ready_state<OPENED)return(OV_EINVAL); + if(vf->ready_state<OPENED)return OV_EINVAL; while(1){ if(vf->ready_state==INITSET){ - samples=vorbis_synthesis_pcmout(&vf->vd,&pcm); - if(samples)break; + channels=vf->vi.channels; + samples=vorbis_dsp_pcmout(vf->vd,buffer,(bytes_req>>1)/channels); + if(samples){ + if(samples>0){ + vorbis_dsp_read(vf->vd,samples); + vf->pcm_offset+=samples; + if(bitstream)*bitstream=vf->current_link; + return samples*2*channels; + } + return samples; + } } /* suck in another packet */ { - int ret=_fetch_and_process_packet(vf,NULL,1,1); + int ret=_fetch_and_process_packet(vf,1,1); if(ret==OV_EOF) - return(0); + return 0; if(ret<=0) - return(ret); + return ret; } } - - if(samples>0){ - - /* yay! proceed to pack data into the byte buffer */ - - long channels=ov_info(vf,-1)->channels; - - if(samples>(bytes_req/(2*channels))) - samples=bytes_req/(2*channels); - - for(i=0;i<channels;i++) { /* It's faster in this order */ - ogg_int32_t *src=pcm[i]; - short *dest=((short *)buffer)+i; - for(j=0;j<samples;j++) { - *dest=CLIP_TO_15(src[j]>>9); - dest+=channels; - } - } - - vorbis_synthesis_read(&vf->vd,samples); - vf->pcm_offset+=samples; - if(bitstream)*bitstream=vf->current_link; - return(samples*2*channels); - }else{ - return(samples); - } } diff --git a/lib/tremor/vorbisidec.pc.in b/lib/tremor/vorbisidec.pc.in index 56fa6567..9c095242 100644 --- a/lib/tremor/vorbisidec.pc.in +++ b/lib/tremor/vorbisidec.pc.in @@ -8,7 +8,7 @@ includedir=@includedir@ Name: vorbisidec Description: vorbisidec is the integer Ogg Vorbis library Version: @VERSION@ -Requires.private: ogg +Requires: ogg Conflicts: -Libs: -L${libdir} -lvorbisidec +Libs: -L${libdir} -lvorbisidec -lm Cflags: -I${includedir} diff --git a/lib/tremor/win32/VS2005/libogg.vsprops b/lib/tremor/win32/VS2005/libogg.vsprops deleted file mode 100644 index dca12081..00000000 --- a/lib/tremor/win32/VS2005/libogg.vsprops +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="windows-1250"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="libogg" - > - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""..\..\..\..\libogg-$(LIBOGG_VERSION)\include";..\..\..\..\ogg\include;..\..\..\..\..\..\..\core\ogg\libogg\include" - /> - <Tool - Name="VCLinkerTool" - AdditionalLibraryDirectories=""..\..\..\..\libogg-$(LIBOGG_VERSION)\win32\VS2005\$(PlatformName)\$(ConfigurationName)";"..\..\..\..\ogg\win32\VS2005\$(PlatformName)\$(ConfigurationName)";"..\..\..\..\..\..\..\core\ogg\libogg\win32\VS2005\$(PlatformName)\$(ConfigurationName)"" - /> - <UserMacro - Name="LIBOGG_VERSION" - Value="1.1.4" - /> -</VisualStudioPropertySheet> diff --git a/lib/tremor/win32/VS2005/libtremor/libtremor.vcproj b/lib/tremor/win32/VS2005/libtremor/libtremor.vcproj deleted file mode 100644 index c18654f6..00000000 --- a/lib/tremor/win32/VS2005/libtremor/libtremor.vcproj +++ /dev/null @@ -1,865 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="8,00" - Name="libtremor" - ProjectGUID="{7A8E774E-DD94-43B8-8758-6F9F656CC8D2}" - RootNamespace="libtremor" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="Win32" - /> - <Platform - Name="x64" - /> - <Platform - Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" - /> - <Platform - Name="Windows Mobile 5.0 Smartphone SDK (ARMV4I)" - /> - <Platform - Name="Windows Mobile 6 Professional SDK (ARMV4I)" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - CallingConvention="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug|x64" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="3" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - CallingConvention="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="_DEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - MinimalRebuild="true" - RuntimeLibrary="1" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="_DEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - MinimalRebuild="true" - RuntimeLibrary="1" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="_DEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - MinimalRebuild="true" - RuntimeLibrary="1" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - CallingConvention="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|x64" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="3" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - CallingConvention="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="NDEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - RuntimeLibrary="0" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="NDEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - RuntimeLibrary="0" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="NDEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - RuntimeLibrary="0" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File - RelativePath="..\..\..\block.c" - > - </File> - <File - RelativePath="..\..\..\codebook.c" - > - </File> - <File - RelativePath="..\..\..\floor0.c" - > - </File> - <File - RelativePath="..\..\..\floor1.c" - > - </File> - <File - RelativePath="..\..\..\info.c" - > - </File> - <File - RelativePath="..\..\..\mapping0.c" - > - </File> - <File - RelativePath="..\..\..\mdct.c" - > - </File> - <File - RelativePath="..\..\..\registry.c" - > - </File> - <File - RelativePath="..\..\..\res012.c" - > - </File> - <File - RelativePath="..\..\..\sharedbook.c" - > - </File> - <File - RelativePath="..\..\..\synthesis.c" - > - </File> - <File - RelativePath="..\..\..\window.c" - > - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File - RelativePath="..\..\..\backends.h" - > - </File> - <File - RelativePath="..\..\..\block.h" - > - </File> - <File - RelativePath="..\..\..\codebook.h" - > - </File> - <File - RelativePath="..\..\..\codec_internal.h" - > - </File> - <File - RelativePath="..\..\..\config_types.h" - > - </File> - <File - RelativePath="..\..\..\ivorbiscodec.h" - > - </File> - <File - RelativePath="..\..\..\ivorbisfile.h" - > - </File> - <File - RelativePath="..\..\..\lsp_lookup.h" - > - </File> - <File - RelativePath="..\..\..\mdct.h" - > - </File> - <File - RelativePath="..\..\..\mdct_lookup.h" - > - </File> - <File - RelativePath="..\..\..\misc.h" - > - </File> - <File - RelativePath="..\..\..\ogg.h" - > - </File> - <File - RelativePath="..\..\..\os.h" - > - </File> - <File - RelativePath="..\..\..\os_types.h" - > - </File> - <File - RelativePath="..\..\..\registry.h" - > - </File> - <File - RelativePath="..\..\..\window.h" - > - </File> - <File - RelativePath="..\..\..\window_lookup.h" - > - </File> - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - <File - RelativePath=".\ReadMe.txt" - > - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/lib/tremor/win32/VS2008/libogg.vsprops b/lib/tremor/win32/VS2008/libogg.vsprops deleted file mode 100644 index 807b74a6..00000000 --- a/lib/tremor/win32/VS2008/libogg.vsprops +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="windows-1250"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="libogg" - > - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""..\..\..\..\libogg-$(LIBOGG_VERSION)\include";..\..\..\..\ogg\include;..\..\..\..\..\..\..\core\ogg\libogg\include" - /> - <Tool - Name="VCLinkerTool" - AdditionalLibraryDirectories=""..\..\..\..\libogg-$(LIBOGG_VERSION)\win32\VS2008\$(PlatformName)\$(ConfigurationName)";"..\..\..\..\ogg\win32\VS2008\$(PlatformName)\$(ConfigurationName)";"..\..\..\..\..\..\..\core\ogg\libogg\win32\VS2008\$(PlatformName)\$(ConfigurationName)"" - /> - <UserMacro - Name="LIBOGG_VERSION" - Value="1.1.4" - /> -</VisualStudioPropertySheet> diff --git a/lib/tremor/win32/VS2008/libtremor/libtremor.vcproj b/lib/tremor/win32/VS2008/libtremor/libtremor.vcproj deleted file mode 100644 index 7edb39b9..00000000 --- a/lib/tremor/win32/VS2008/libtremor/libtremor.vcproj +++ /dev/null @@ -1,865 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9,00" - Name="libtremor" - ProjectGUID="{7A8E774E-DD94-43B8-8758-6F9F656CC8D2}" - RootNamespace="libtremor" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="Win32" - /> - <Platform - Name="x64" - /> - <Platform - Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" - /> - <Platform - Name="Windows Mobile 5.0 Smartphone SDK (ARMV4I)" - /> - <Platform - Name="Windows Mobile 6 Professional SDK (ARMV4I)" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="4" - CallingConvention="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug|x64" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="3" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="3" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - CallingConvention="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="_DEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - MinimalRebuild="true" - RuntimeLibrary="1" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="_DEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - MinimalRebuild="true" - RuntimeLibrary="1" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Debug|Windows Mobile 6 Professional SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="_DEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - MinimalRebuild="true" - RuntimeLibrary="1" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - CallingConvention="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|x64" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="3" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB" - RuntimeLibrary="2" - UsePrecompiledHeader="0" - WarningLevel="3" - Detect64BitPortabilityProblems="true" - DebugInformationFormat="3" - CallingConvention="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="NDEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - RuntimeLibrary="0" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="NDEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - RuntimeLibrary="0" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - <Configuration - Name="Release|Windows Mobile 6 Professional SDK (ARMV4I)" - OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - InheritedPropertySheets="..\libogg.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="1" - /> - <Tool - Name="VCCLCompilerTool" - ExecutionBucket="7" - AdditionalIncludeDirectories="..\..\..\include;..\..\..\..\libogg\include" - PreprocessorDefinitions="NDEBUG;_LIB;_WIN32_WCE=$(CEVER);UNDER_CE;WIN32;WINCE;$(ARCHFAM);$(_ARCHFAM_);$(PLATFORMDEFINES)" - RuntimeLibrary="0" - TreatWChar_tAsBuiltInType="false" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCCodeSignTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - <DeploymentTool - ForceDirty="-1" - RemoteDirectory="" - RegisterOutput="0" - AdditionalFiles="" - /> - <DebuggerTool - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File - RelativePath="..\..\..\block.c" - > - </File> - <File - RelativePath="..\..\..\codebook.c" - > - </File> - <File - RelativePath="..\..\..\floor0.c" - > - </File> - <File - RelativePath="..\..\..\floor1.c" - > - </File> - <File - RelativePath="..\..\..\info.c" - > - </File> - <File - RelativePath="..\..\..\mapping0.c" - > - </File> - <File - RelativePath="..\..\..\mdct.c" - > - </File> - <File - RelativePath="..\..\..\registry.c" - > - </File> - <File - RelativePath="..\..\..\res012.c" - > - </File> - <File - RelativePath="..\..\..\sharedbook.c" - > - </File> - <File - RelativePath="..\..\..\synthesis.c" - > - </File> - <File - RelativePath="..\..\..\window.c" - > - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File - RelativePath="..\..\..\backends.h" - > - </File> - <File - RelativePath="..\..\..\block.h" - > - </File> - <File - RelativePath="..\..\..\codebook.h" - > - </File> - <File - RelativePath="..\..\..\codec_internal.h" - > - </File> - <File - RelativePath="..\..\..\config_types.h" - > - </File> - <File - RelativePath="..\..\..\ivorbiscodec.h" - > - </File> - <File - RelativePath="..\..\..\ivorbisfile.h" - > - </File> - <File - RelativePath="..\..\..\lsp_lookup.h" - > - </File> - <File - RelativePath="..\..\..\mdct.h" - > - </File> - <File - RelativePath="..\..\..\mdct_lookup.h" - > - </File> - <File - RelativePath="..\..\..\misc.h" - > - </File> - <File - RelativePath="..\..\..\ogg.h" - > - </File> - <File - RelativePath="..\..\..\os.h" - > - </File> - <File - RelativePath="..\..\..\os_types.h" - > - </File> - <File - RelativePath="..\..\..\registry.h" - > - </File> - <File - RelativePath="..\..\..\window.h" - > - </File> - <File - RelativePath="..\..\..\window_lookup.h" - > - </File> - </Filter> - <Filter - Name="Resource Files" - Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" - UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" - > - </Filter> - <File - RelativePath=".\ReadMe.txt" - > - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/lib/tremor/window.c b/lib/tremor/window.c deleted file mode 100644 index 006a1ee6..00000000 --- a/lib/tremor/window.c +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: window functions - - ********************************************************************/ - -#include <stdlib.h> -#include <math.h> -#include "misc.h" -#include "window.h" -#include "window_lookup.h" - -const void *_vorbis_window(int type, int left){ - - switch(type){ - case 0: - - switch(left){ - case 32: - return vwin64; - case 64: - return vwin128; - case 128: - return vwin256; - case 256: - return vwin512; - case 512: - return vwin1024; - case 1024: - return vwin2048; - case 2048: - return vwin4096; - case 4096: - return vwin8192; - default: - return(0); - } - break; - default: - return(0); - } -} - -void _vorbis_apply_window(ogg_int32_t *d,const void *window_p[2], - long *blocksizes, - int lW,int W,int nW){ - - LOOKUP_T *window[2]={window_p[0],window_p[1]}; - long n=blocksizes[W]; - long ln=blocksizes[lW]; - long rn=blocksizes[nW]; - - long leftbegin=n/4-ln/4; - long leftend=leftbegin+ln/2; - - long rightbegin=n/2+n/4-rn/4; - long rightend=rightbegin+rn/2; - - int i,p; - - for(i=0;i<leftbegin;i++) - d[i]=0; - - for(p=0;i<leftend;i++,p++) - d[i]=MULT31(d[i],window[lW][p]); - - for(i=rightbegin,p=rn/2-1;i<rightend;i++,p--) - d[i]=MULT31(d[i],window[nW][p]); - - for(;i<n;i++) - d[i]=0; -} diff --git a/lib/tremor/window.h b/lib/tremor/window.h deleted file mode 100644 index 27647fe6..00000000 --- a/lib/tremor/window.h +++ /dev/null @@ -1,27 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * - * * - ******************************************************************** - - function: window functions - - ********************************************************************/ - -#ifndef _V_WINDOW_ -#define _V_WINDOW_ - -extern const void *_vorbis_window(int type,int left); -extern void _vorbis_apply_window(ogg_int32_t *d,const void *window[2], - long *blocksizes, - int lW,int W,int nW); - - -#endif diff --git a/lib/tremor/window_lookup.h b/lib/tremor/window_lookup.h index fc0494e6..d2e69371 100644 --- a/lib/tremor/window_lookup.h +++ b/lib/tremor/window_lookup.h @@ -1,12 +1,12 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** @@ -16,9 +16,9 @@ ********************************************************************/ -#include <ogg/os_types.h> +#include "os_types.h" -static const LOOKUP_T vwin64[32] = { +static LOOKUP_T vwin64[32] = { X(0x001f0003), X(0x01168c98), X(0x030333c8), X(0x05dfe3a4), X(0x09a49562), X(0x0e45df18), X(0x13b47ef2), X(0x19dcf676), X(0x20a74d83), X(0x27f7137c), X(0x2fabb05a), X(0x37a1105a), @@ -29,7 +29,7 @@ static const LOOKUP_T vwin64[32] = { X(0x7fdd78a5), X(0x7ff6ec6d), X(0x7ffed0e9), X(0x7ffffc3f), }; -static const LOOKUP_T vwin128[64] = { +static LOOKUP_T vwin128[64] = { X(0x0007c04d), X(0x0045bb89), X(0x00c18b87), X(0x017ae294), X(0x02714a4e), X(0x03a4217a), X(0x05129952), X(0x06bbb24f), X(0x089e38a1), X(0x0ab8c073), X(0x0d09a228), X(0x0f8ef6bd), @@ -48,7 +48,7 @@ static const LOOKUP_T vwin128[64] = { X(0x7ffdcf39), X(0x7fff6dac), X(0x7fffed01), X(0x7fffffc4), }; -static const LOOKUP_T vwin256[128] = { +static LOOKUP_T vwin256[128] = { X(0x0001f018), X(0x00117066), X(0x00306e9e), X(0x005ee5f1), X(0x009ccf26), X(0x00ea208b), X(0x0146cdea), X(0x01b2c87f), X(0x022dfedf), X(0x02b85ced), X(0x0351cbbd), X(0x03fa317f), @@ -83,7 +83,7 @@ static const LOOKUP_T vwin256[128] = { X(0x7fffdcd2), X(0x7ffff6d6), X(0x7ffffed0), X(0x7ffffffc), }; -static const LOOKUP_T vwin512[256] = { +static LOOKUP_T vwin512[256] = { X(0x00007c06), X(0x00045c32), X(0x000c1c62), X(0x0017bc4c), X(0x00273b7a), X(0x003a9955), X(0x0051d51c), X(0x006cede7), X(0x008be2a9), X(0x00aeb22a), X(0x00d55b0d), X(0x00ffdbcc), @@ -150,7 +150,7 @@ static const LOOKUP_T vwin512[256] = { X(0x7ffffdcd), X(0x7fffff6d), X(0x7fffffed), X(0x7fffffff), }; -static const LOOKUP_T vwin1024[512] = { +static LOOKUP_T vwin1024[512] = { X(0x00001f02), X(0x0001170e), X(0x00030724), X(0x0005ef40), X(0x0009cf59), X(0x000ea767), X(0x0014775e), X(0x001b3f2e), X(0x0022fec8), X(0x002bb618), X(0x00356508), X(0x00400b81), @@ -281,7 +281,7 @@ static const LOOKUP_T vwin1024[512] = { X(0x7fffffdd), X(0x7ffffff7), X(0x7fffffff), X(0x7fffffff), }; -static const LOOKUP_T vwin2048[1024] = { +static LOOKUP_T vwin2048[1024] = { X(0x000007c0), X(0x000045c4), X(0x0000c1ca), X(0x00017bd3), X(0x000273de), X(0x0003a9eb), X(0x00051df9), X(0x0006d007), X(0x0008c014), X(0x000aee1e), X(0x000d5a25), X(0x00100428), @@ -540,7 +540,7 @@ static const LOOKUP_T vwin2048[1024] = { X(0x7ffffffe), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), }; -static const LOOKUP_T vwin4096[2048] = { +static LOOKUP_T vwin4096[2048] = { X(0x000001f0), X(0x00001171), X(0x00003072), X(0x00005ef5), X(0x00009cf8), X(0x0000ea7c), X(0x00014780), X(0x0001b405), X(0x0002300b), X(0x0002bb91), X(0x00035698), X(0x0004011e), @@ -1055,7 +1055,9 @@ static const LOOKUP_T vwin4096[2048] = { X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), }; -static const LOOKUP_T vwin8192[4096] = { +#ifndef LIMIT_TO_64kHz + +static LOOKUP_T vwin8192[4096] = { X(0x0000007c), X(0x0000045c), X(0x00000c1d), X(0x000017bd), X(0x0000273e), X(0x00003a9f), X(0x000051e0), X(0x00006d02), X(0x00008c03), X(0x0000aee5), X(0x0000d5a7), X(0x00010049), @@ -2082,3 +2084,4 @@ static const LOOKUP_T vwin8192[4096] = { X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), }; +#endif |
