diff options
author | Monty <xiphmont@xiph.org> | 2000-12-27 23:46:38 +0000 |
---|---|---|
committer | Monty <xiphmont@xiph.org> | 2000-12-27 23:46:38 +0000 |
commit | 6f5ce779237ca696ea44f7b24671baeb042235b9 (patch) | |
tree | 3a10a10377ee9c656e1136939ada24fecfb0eec7 | |
download | libvorbis-git-6f5ce779237ca696ea44f7b24671baeb042235b9.tar.gz |
Major work on psy.c
some global optimization (less memory and lin->dB->lin conversions)
median based noise curve
FFT based tone masking
*much* faster encode.
We still have a bug where current tuning overflows codebooks on the
100dB masking curves. Hacked around for now.
Monty
svn path=/branches/monty_branch_20001226/vorbis/; revision=1131
-rw-r--r-- | configure.in | 169 | ||||
-rwxr-xr-x | debian/rules | 77 | ||||
-rw-r--r-- | examples/encoder_example.c | 199 | ||||
-rw-r--r-- | include/vorbis/codec.h | 225 | ||||
-rw-r--r-- | lib/analysis.c | 107 | ||||
-rw-r--r-- | lib/backends.h | 148 | ||||
-rw-r--r-- | lib/block.c | 780 | ||||
-rw-r--r-- | lib/codec_internal.h | 117 | ||||
-rw-r--r-- | lib/envelope.c | 233 | ||||
-rw-r--r-- | lib/floor0.c | 430 | ||||
-rw-r--r-- | lib/info.c | 571 | ||||
-rw-r--r-- | lib/mapping0.c | 441 | ||||
-rw-r--r-- | lib/modes/mode_A.h | 300 | ||||
-rw-r--r-- | lib/modes/mode_AA.h | 292 | ||||
-rw-r--r-- | lib/modes/mode_B.h | 210 | ||||
-rw-r--r-- | lib/modes/mode_C.h | 283 | ||||
-rw-r--r-- | lib/modes/mode_D.h | 236 | ||||
-rw-r--r-- | lib/modes/mode_E.h | 169 | ||||
-rw-r--r-- | lib/psy.c | 654 | ||||
-rw-r--r-- | lib/psy.h | 103 | ||||
-rw-r--r-- | lib/psytune.c | 392 | ||||
-rw-r--r-- | lib/scales.h | 51 | ||||
-rw-r--r-- | libvorbis.spec | 84 |
23 files changed, 6271 insertions, 0 deletions
diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..e1fac805 --- /dev/null +++ b/configure.in @@ -0,0 +1,169 @@ +dnl Process this file with autoconf to produce a configure script + +dnl ------------------------------------------------ +dnl Initialization and Versioning +dnl ------------------------------------------------ + +AC_INIT(lib/mdct.c) +AM_INIT_AUTOMAKE(libvorbis,1.0prebeta4) + +dnl Library versioning + +V_LIB_CURRENT=0 +V_LIB_REVISION=0 +V_LIB_AGE=0 +VF_LIB_CURRENT=0 +VF_LIB_REVISION=0 +VF_LIB_AGE=0 +VE_LIB_CURRENT=0 +VE_LIB_REVISION=0 +VE_LIB_AGE=0 +AC_SUBST(V_LIB_CURRENT) +AC_SUBST(V_LIB_REVISION) +AC_SUBST(V_LIB_AGE) +AC_SUBST(VF_LIB_CURRENT) +AC_SUBST(VF_LIB_REVISION) +AC_SUBST(VF_LIB_AGE) +AC_SUBST(VE_LIB_CURRENT) +AC_SUBST(VE_LIB_REVISION) +AC_SUBST(VE_LIB_AGE) + +dnl -------------------------------------------------- +dnl Check for programs +dnl -------------------------------------------------- + +dnl save $CFLAGS since AC_PROG_CC likes to insert "-g -O2" +dnl if $CFLAGS is blank +cflags_save="$CFLAGS" +AC_PROG_CC +CFLAGS="$cflags_save" + +AM_PROG_LIBTOOL + +dnl -------------------------------------------------- +dnl Set build flags based on environment +dnl -------------------------------------------------- + +AC_CANONICAL_HOST + +dnl Set some target options +if test -z "$GCC"; then + case $host in + *-*-irix*) + dnl If we're on IRIX, we wanna use cc even if gcc + dnl is there (unless the user has overriden us)... + if test -z "$CC"; then + CC=cc + fi + DEBUG="-g -signed" + CFLAGS="-O2 -w -signed" + PROFILE="-p -g3 -O2 -signed" ;; + sparc-sun-solaris*) + DEBUG="-v -g" + CFLAGS="-xO4 -fast -w -fsimple -native -xcg92" + PROFILE="-v -xpg -g -xO4 -fast -native -fsimple -xcg92 -Dsuncc" ;; + *) + DEBUG="-g" + CFLAGS="-O" + PROFILE="-g -p" ;; + esac +else + + case $host in + *86-*-linux*) + DEBUG="-g -Wall -D_REENTRANT -D__NO_MATH_INLINES -fsigned-char" + CFLAGS="-O20 -ffast-math -mno-ieee-fp -D_REENTRANT -fsigned-char" +# PROFILE="-Wall -W -pg -g -O20 -ffast-math -D_REENTRANT -fsigned-char -fno-inline -static" + PROFILE="-Wall -W -pg -g -O20 -ffast-math -mno-ieee-fp -D_REENTRANT -fsigned-char -fno-inline -static" + + # glibc < 2.1.3 has a serious FP bug in the math inline header + # that will cripple Vorbis. Look to see if the magic FP stack + # clobber is missing in the mathinline header, thus indicating + # the buggy version + + AC_EGREP_CPP(log10.*fldlg2.*fxch,[ + #define __LIBC_INTERNAL_MATH_INLINES 1 + #define __OPTIMIZE__ + #include <math.h> + ],bad=maybe,bad=no) + if test ${bad} = "maybe" ;then + AC_EGREP_CPP(log10.*fldlg2.*fxch.*st\([[0123456789]]*\), + [ + #define __LIBC_INTERNAL_MATH_INLINES 1 + #define __OPTIMIZE__ + #include <math.h> + ],bad=no,bad=yes) + fi + if test ${bad} = "yes" ;then + AC_MSG_WARN([ ]) + AC_MSG_WARN([********************************************************]) + AC_MSG_WARN([* The glibc headers on this machine have a serious bug *]) + AC_MSG_WARN([* in /usr/include/bits/mathinline.h This bug affects *]) + AC_MSG_WARN([* all floating point code, not just Ogg, built on this *]) + AC_MSG_WARN([* machine. Upgrading to glibc 2.1.3 is strongly urged *]) + AC_MSG_WARN([* to correct the problem. Note that upgrading glibc *]) + AC_MSG_WARN([* will not fix any previously built programs; this is *]) + AC_MSG_WARN([* a compile-time time bug. *]) + AC_MSG_WARN([* To work around the problem for this build of Ogg, *]) + AC_MSG_WARN([* autoconf is disabling all math inlining. This will *]) + AC_MSG_WARN([* hurt Ogg performace but is necessary for an Ogg that *]) + AC_MSG_WARN([* will actually work. Once glibc is upgraded, rerun *]) + AC_MSG_WARN([* configure and make to build with inlining. *]) + AC_MSG_WARN([********************************************************]) + AC_MSG_WARN([ ]) + + CFLAGS=${OPT}" -D__NO_MATH_INLINES" + PROFILE=${PROFILE}" -D__NO_MATH_INLINES" + fi;; + *-*-linux*) + DEBUG="-g -Wall -D_REENTRANT -D__NO_MATH_INLINES -fsigned-char" + CFLAGS="-O20 -ffast-math -D_REENTRANT -fsigned-char" + PROFILE="-pg -g -O20 -ffast-math -D_REENTRANT -fsigned-char";; + sparc-sun-*) + DEBUG="-g -Wall -D__NO_MATH_INLINES -fsigned-char -mv8" + CFLAGS="-O20 -ffast-math -D__NO_MATH_INLINES -fsigned-char -mv8" + PROFILE="-pg -g -O20 -D__NO_MATH_INLINES -fsigned-char -mv8" ;; + *) + DEBUG="-g -Wall -D__NO_MATH_INLINES -fsigned-char" + CFLAGS="-O20 -D__NO_MATH_INLINES -fsigned-char" + PROFILE="-O20 -g -pg -D__NO_MATH_INLINES -fsigned-char" ;; + esac +fi + +dnl -------------------------------------------------- +dnl Check for headers +dnl -------------------------------------------------- + +AC_CHECK_HEADER(memory.h,CFLAGS="$CFLAGS -DUSE_MEMORY_H",:) + +dnl -------------------------------------------------- +dnl Check for typedefs, structures, etc +dnl -------------------------------------------------- + +dnl none + +dnl -------------------------------------------------- +dnl Check for libraries +dnl -------------------------------------------------- + +AC_CHECK_LIB(m, cos, LIBS="-lm", LIBS="") +AC_CHECK_LIB(pthread, pthread_create, pthread_lib="-lpthread", :) + +AM_PATH_OGG(LIBS="$LIBS $OGG_LIBS", AC_MSG_ERROR(must have Ogg installed!)) + +dnl -------------------------------------------------- +dnl Check for library functions +dnl -------------------------------------------------- + +AC_FUNC_ALLOCA +AC_FUNC_MEMCMP + +dnl -------------------------------------------------- +dnl Do substitutions +dnl -------------------------------------------------- + +AC_SUBST(DEBUG) +AC_SUBST(PROFILE) +AC_SUBST(pthread_lib) + +AC_OUTPUT(Makefile lib/Makefile lib/modes/Makefile lib/books/Makefile doc/Makefile doc/vorbisfile/Makefile doc/vorbisenc/Makefile include/Makefile include/vorbis/Makefile examples/Makefile win32/Makefile debian/Makefile vq/Makefile) diff --git a/debian/rules b/debian/rules new file mode 100755 index 00000000..9937d63f --- /dev/null +++ b/debian/rules @@ -0,0 +1,77 @@ +#!/usr/bin/make -f +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +# This is the debhelper compatability version to use. +export DH_COMPAT=2 + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + # If compiling cvs version change to ./autogen.sh --prefix=/usr + ./configure --prefix=/usr + + touch configure-stamp + +build: configure-stamp build-stamp +build-stamp: + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/tmp. + $(MAKE) install DESTDIR=`pwd`/debian/tmp + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + + dh_movefiles + + dh_installdocs debian/tmp/usr/share/doc/libvorbis-1.0prebeta4/* + dh_installexamples + dh_installmanpages + dh_installchangelogs + dh_link + dh_strip + dh_compress + dh_fixperms + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/examples/encoder_example.c b/examples/encoder_example.c new file mode 100644 index 00000000..cb5da7df --- /dev/null +++ b/examples/encoder_example.c @@ -0,0 +1,199 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: simple example encoder + last mod: $Id: encoder_example.c,v 1.17.2.1 2000/12/27 23:46:33 xiphmont Exp $ + + ********************************************************************/ + +/* takes a stereo 16bit 44.1kHz WAV file from stdin and encodes it into + a Vorbis bitstream */ + +/* Note that this is POSIX, not ANSI, code */ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <math.h> +#include <vorbis/vorbisenc.h> + +#ifdef _WIN32 /* We need the following two to set stdin/stdout to binary */ +#include <io.h> +#include <fcntl.h> +#endif + +#if defined(macintosh) && defined(__MWERKS__) +#include <console.h> /* CodeWarrior's Mac "command-line" support */ +#endif + +#define READ 1024 +signed char readbuffer[READ*4+44]; /* out of the data segment, not the stack */ + +int main(){ + ogg_stream_state os; /* take physical pages, weld into a logical + stream of packets */ + ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ + ogg_packet op; /* one raw packet of data for decode */ + + vorbis_info vi; /* struct that stores all the static vorbis bitstream + settings */ + vorbis_comment vc; /* struct that stores all the user comments */ + + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + vorbis_block vb; /* local working space for packet->PCM decode */ + + int eos=0; + +#if defined(macintosh) && defined(__MWERKS__) + int argc = 0; + char **argv = NULL; + argc = ccommand(&argv); /* get a "command line" from the Mac user */ + /* this also lets the user set stdin and stdout */ +#endif + + /* we cheat on the WAV header; we just bypass 44 bytes and never + verify that it matches 16bit/stereo/44.1kHz. This is just an + example, after all. */ + +#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ + /* Beware the evil ifdef. We avoid these where we can, but this one we + cannot. Don't add any more, you'll probably go to hell if you do. */ + _setmode( _fileno( stdin ), _O_BINARY ); + _setmode( _fileno( stdout ), _O_BINARY ); +#endif + + + fread(readbuffer,1,44,stdin); + + /********** Encode setup ************/ + + /* choose an encoding mode */ + /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */ + vorbis_info_init(&vi); + vorbis_encode_init(&vi,2,44100, -1, 128000, -1); + + /* add a comment */ + vorbis_comment_init(&vc); + vorbis_comment_add(&vc,"Track encoded by encoder_example.c"); + + /* set up the analysis state and auxiliary encoding storage */ + vorbis_analysis_init(&vd,&vi); + vorbis_block_init(&vd,&vb); + + /* set up our packet->stream encoder */ + /* pick a random serial number; that way we can more likely build + chained streams just by concatenation */ + srand(time(NULL)); + ogg_stream_init(&os,rand()); + + /* Vorbis streams begin with three headers; the initial header (with + most of the codec setup parameters) which is mandated by the Ogg + bitstream spec. The second header holds any comment fields. The + third header holds the bitstream codebook. We merely need to + make the headers, then pass them to libvorbis one at a time; + libvorbis handles the additional Ogg bitstream constraints */ + + { + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); + ogg_stream_packetin(&os,&header); /* automatically placed in its own + page */ + ogg_stream_packetin(&os,&header_comm); + ogg_stream_packetin(&os,&header_code); + + /* We don't have to write out here, but doing so makes streaming + * much easier, so we do, flushing ALL pages. This ensures the actual + * audio data will start on a new page + */ + while(!eos){ + int result=ogg_stream_flush(&os,&og); + if(result==0)break; + fwrite(og.header,1,og.header_len,stdout); + fwrite(og.body,1,og.body_len,stdout); + } + + } + + while(!eos){ + long i; + long bytes=fread(readbuffer,1,READ*4,stdin); /* stereo hardwired here */ + + if(bytes==0){ + /* end of file. this can be done implicitly in the mainline, + but it's easier to see here in non-clever fashion. + Tell the library we're at end of stream so that it can handle + the last frame and mark end of stream in the output properly */ + vorbis_analysis_wrote(&vd,0); + + }else{ + /* data to encode */ + + /* expose the buffer to submit data */ + float **buffer=vorbis_analysis_buffer(&vd,READ); + + /* uninterleave samples */ + for(i=0;i<bytes/4;i++){ + buffer[0][i]=((readbuffer[i*4+1]<<8)| + (0x00ff&(int)readbuffer[i*4]))/32768.f; + buffer[1][i]=((readbuffer[i*4+3]<<8)| + (0x00ff&(int)readbuffer[i*4+2]))/32768.f; + } + + /* tell the library how much we actually submitted */ + vorbis_analysis_wrote(&vd,i); + } + + /* vorbis does some data preanalysis, then divvies up blocks for + more involved (potentially parallel) processing. Get a single + block for encoding now */ + while(vorbis_analysis_blockout(&vd,&vb)==1){ + + /* analysis */ + vorbis_analysis(&vb,&op); + + /* weld the packet into the bitstream */ + ogg_stream_packetin(&os,&op); + + /* write out pages (if any) */ + while(!eos){ + int result=ogg_stream_pageout(&os,&og); + if(result==0)break; + fwrite(og.header,1,og.header_len,stdout); + fwrite(og.body,1,og.body_len,stdout); + + /* this could be set above, but for illustrative purposes, I do + it here (to show that vorbis does know where the stream ends) */ + + if(ogg_page_eos(&og))eos=1; + + } + } + } + + /* clean up and exit. vorbis_info_clear() must be called last */ + + ogg_stream_clear(&os); + vorbis_block_clear(&vb); + vorbis_dsp_clear(&vd); + vorbis_info_clear(&vi); + + /* ogg_page and ogg_packet structs always point to storage in + libvorbis. They're never freed or manipulated directly */ + + fprintf(stderr,"Done.\n"); + return(0); +} + diff --git a/include/vorbis/codec.h b/include/vorbis/codec.h new file mode 100644 index 00000000..c3f12658 --- /dev/null +++ b/include/vorbis/codec.h @@ -0,0 +1,225 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: libvorbis codec headers + last mod: $Id: codec.h,v 1.33.2.1 2000/12/27 23:46:34 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _vorbis_codec_h_ +#define _vorbis_codec_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include <ogg/ogg.h> + +typedef struct vorbis_info{ + int version; + int channels; + long rate; + + /* The below bitrate declarations are *hints*. + Combinations of the three values carry the following implications: + + all three set to the same value: + implies a fixed rate bitstream + only nominal set: + implies a VBR stream that averages the nominal bitrate. No hard + upper/lower limit + upper and or lower set: + implies a VBR bitstream that obeys the bitrate limits. nominal + may also be set to give a nominal rate. + none set: + the coder does not care to speculate. + */ + + long bitrate_upper; + long bitrate_nominal; + long bitrate_lower; + long bitrate_window; + + 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; + + float **pcm; + float **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; + + ogg_int64_t glue_bits; + ogg_int64_t time_bits; + ogg_int64_t floor_bits; + ogg_int64_t res_bits; + + void *backend_state; +} vorbis_dsp_state; + +typedef struct vorbis_block{ + /* necessary stream state for linking to the framing abstraction */ + float **pcm; /* this is a pointer into local storage */ + float **pcmdelay; /* 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; + + /* bitmetrics for the frame */ + long glue_bits; + long time_bits; + long floor_bits; + long res_bits; + +} 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; + char *vendor; + +} 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); +extern void vorbis_info_clear(vorbis_info *vi); +extern void vorbis_comment_init(vorbis_comment *vc); +extern void vorbis_comment_add(vorbis_comment *vc, char *comment); +extern void vorbis_comment_add_tag(vorbis_comment *vc, + char *tag, char *contents); +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: analysis/DSP layer ****************************/ + +extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code); +extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); + +/* Vorbis PRIMITIVES: synthesis layer *******************************/ +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(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,float ***pcm); +extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); + +/* Vorbis ERRORS and return codes ***********************************/ + +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 + +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 +#define OV_ENOTVORBIS -132 +#define OV_EBADHEADER -133 +#define OV_EVERSION -134 +#define OV_ENOTAUDIO -135 +#define OV_EBADPACKET -136 +#define OV_EBADLINK -137 +#define OV_ENOSEEK -138 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/lib/analysis.c b/lib/analysis.c new file mode 100644 index 00000000..bd6029fe --- /dev/null +++ b/lib/analysis.c @@ -0,0 +1,107 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: single-block PCM analysis mode dispatch + last mod: $Id: analysis.c,v 1.40.2.1 2000/12/27 23:46:34 xiphmont Exp $ + + ********************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <ogg/ogg.h> +#include "vorbis/codec.h" +#include "registry.h" +#include "scales.h" +#include "os.h" + +/* decides between modes, dispatches to the appropriate mapping. */ +int vorbis_analysis(vorbis_block *vb,ogg_packet *op){ + vorbis_dsp_state *vd=vb->vd; + backend_lookup_state *b=vd->backend_state; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + int type,ret; + int mode=0; + + vb->glue_bits=0; + vb->time_bits=0; + vb->floor_bits=0; + vb->res_bits=0; + + /* first things first. Make sure encode is ready */ + oggpack_reset(&vb->opb); + /* Encode the packet type */ + oggpack_write(&vb->opb,0,1); + + /* currently lazy. Short block dispatches to 0, long to 1. */ + + if(vb->W &&ci->modes>1)mode=1; + type=ci->map_type[ci->mode_param[mode]->mapping]; + vb->mode=mode; + + /* Encode frame mode, pre,post windowsize, then dispatch */ + oggpack_write(&vb->opb,mode,b->modebits); + if(vb->W){ + oggpack_write(&vb->opb,vb->lW,1); + oggpack_write(&vb->opb,vb->nW,1); + fprintf(stderr,"*"); + }else{ + fprintf(stderr,"."); + } + + if((ret=_mapping_P[type]->forward(vb,b->mode[mode]))) + return(ret); + + /* set up the packet wrapper */ + + op->packet=oggpack_get_buffer(&vb->opb); + op->bytes=oggpack_bytes(&vb->opb); + op->b_o_s=0; + op->e_o_s=vb->eofflag; + op->granulepos=vb->granulepos; + op->packetno=vb->sequence; /* for sake of completeness */ + + return(0); +} + +/* there was no great place to put this.... */ +void _analysis_output(char *base,int i,float *v,int n,int bark,int dB){ +#ifdef ANALYSIS + int j; + FILE *of; + char buffer[80]; + sprintf(buffer,"%s_%d.m",base,i); + of=fopen(buffer,"w"); + + if(!of)perror("failed to open data dump file"); + + for(j=0;j<n;j++){ + if(dB && v[j]==0) + fprintf(of,"\n\n"); + else{ + if(bark) + fprintf(of,"%g ",toBARK(22050.f*j/n)); + else + fprintf(of,"%g ",(double)j); + + if(dB){ + fprintf(of,"%g\n",todB(fabs(v[j]))); + }else{ + fprintf(of,"%g\n",v[j]); + } + } + } + fclose(of); +#endif +} diff --git a/lib/backends.h b/lib/backends.h new file mode 100644 index 00000000..3c1b7367 --- /dev/null +++ b/lib/backends.h @@ -0,0 +1,148 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: libvorbis backend and mapping structures; needed for + static mode headers + last mod: $Id: backends.h,v 1.3.2.1 2000/12/27 23:46:34 xiphmont Exp $ + + ********************************************************************/ + +/* 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 */ + +/* Time backend generic ******************************************/ +typedef struct{ + void (*pack) (vorbis_info_time *,oggpack_buffer *); + vorbis_info_time *(*unpack)(vorbis_info *,oggpack_buffer *); + vorbis_look_time *(*look) (vorbis_dsp_state *,vorbis_info_mode *, + vorbis_info_time *); + vorbis_info_time *(*copy_info)(vorbis_info_time *); + + void (*free_info) (vorbis_info_time *); + void (*free_look) (vorbis_look_time *); + int (*forward) (struct vorbis_block *,vorbis_look_time *, + float *,float *); + int (*inverse) (struct vorbis_block *,vorbis_look_time *, + float *,float *); +} vorbis_func_time; + +typedef struct{ + int dummy; +} vorbis_info_time0; + +/* Floor backend generic *****************************************/ +typedef struct{ + void (*pack) (vorbis_info_floor *,oggpack_buffer *); + vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *); + vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_mode *, + vorbis_info_floor *); + vorbis_info_floor *(*copy_info)(vorbis_info_floor *); + void (*free_info) (vorbis_info_floor *); + void (*free_look) (vorbis_look_floor *); + int (*forward) (struct vorbis_block *,vorbis_look_floor *, + float *,vorbis_bitbuffer *); + float(*forward2) (struct vorbis_block *,vorbis_look_floor *, + long,float, vorbis_bitbuffer *); + int (*inverse) (struct vorbis_block *,vorbis_look_floor *, + float *); +} vorbis_func_floor; + +typedef struct{ + int order; + long rate; + long barkmap; + + int ampbits; + int ampdB; + + int numbooks; /* <= 16 */ + int books[16]; +} vorbis_info_floor0; + +/* Residue backend generic *****************************************/ +typedef struct{ + void (*pack) (vorbis_info_residue *,oggpack_buffer *); + vorbis_info_residue *(*unpack)(vorbis_info *,oggpack_buffer *); + vorbis_look_residue *(*look) (vorbis_dsp_state *,vorbis_info_mode *, + vorbis_info_residue *); + vorbis_info_residue *(*copy_info)(vorbis_info_residue *); + void (*free_info) (vorbis_info_residue *); + void (*free_look) (vorbis_look_residue *); + int (*forward) (struct vorbis_block *,vorbis_look_residue *, + float **,int,vorbis_bitbuffer *); + int (*inverse) (struct vorbis_block *,vorbis_look_residue *, + float **,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 groupbook; /* huffbook for partitioning */ + int secondstages[64]; /* expanded out to pointers in lookup */ + int booklist[256]; /* list of second stage books */ + + /* encode-only heuristic settings */ + float entmax[64]; /* book entropy threshholds*/ + float ampmax[64]; /* book amp threshholds*/ + int subgrp[64]; /* book heuristic subgroup size */ + int blimit[64]; /* subgroup position limits */ + +} vorbis_info_residue0; + +/* Mapping backend generic *****************************************/ +typedef struct{ + void (*pack) (vorbis_info *,vorbis_info_mapping *, + oggpack_buffer *); + vorbis_info_mapping *(*unpack)(vorbis_info *,oggpack_buffer *); + vorbis_look_mapping *(*look) (vorbis_dsp_state *,vorbis_info_mode *, + vorbis_info_mapping *); + vorbis_info_mapping *(*copy_info)(vorbis_info_mapping *); + void (*free_info) (vorbis_info_mapping *); + void (*free_look) (vorbis_look_mapping *); + int (*forward) (struct vorbis_block *vb,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 timesubmap[16]; /* [mux] */ + int floorsubmap[16]; /* [mux] submap to floors */ + int residuesubmap[16]; /* [mux] submap to residue */ + int psysubmap[16]; /* [mux]; encode only */ +} vorbis_info_mapping0; + +#endif + + + + + diff --git a/lib/block.c b/lib/block.c new file mode 100644 index 00000000..da01551b --- /dev/null +++ b/lib/block.c @@ -0,0 +1,780 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: PCM data vector blocking, windowing and dis/reassembly + last mod: $Id: block.c,v 1.42.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + Handle windowing, overlap-add, etc of the PCM vectors. This is made + more amusing by Vorbis' current two allowed block sizes. + + ********************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ogg/ogg.h> +#include "vorbis/codec.h" + +#include "window.h" +#include "envelope.h" +#include "mdct.h" +#include "lpc.h" +#include "registry.h" +#include "codebook.h" +#include "misc.h" +#include "os.h" + +static int ilog2(unsigned int v){ + int ret=0; + while(v>1){ + 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(vorbis_block)); + vb->vd=v; + vb->localalloc=0; + vb->localstore=NULL; + if(v->analysisp) + oggpack_writeinit(&vb->opb); + + 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=_ogg_malloc(sizeof(struct alloc_chain)); + 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(struct alloc_chain)); + _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){ + if(vb->vd) + if(vb->vd->analysisp) + oggpack_writeclear(&vb->opb); + _vorbis_block_ripcord(vb); + if(vb->localstore)_ogg_free(vb->localstore); + + memset(vb,0,sizeof(vorbis_block)); + return(0); +} + +/* Analysis side code, but directly related to blocking. Thus it's + here and not in analysis.c (which is for analysis transforms only). + The init is here because some of it is shared */ + +static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ + int i; + codec_setup_info *ci=vi->codec_setup; + backend_lookup_state *b=NULL; + + memset(v,0,sizeof(vorbis_dsp_state)); + b=v->backend_state=_ogg_calloc(1,sizeof(backend_lookup_state)); + + v->vi=vi; + b->modebits=ilog2(ci->modes); + + b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(vorbis_look_transform *)); + b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(vorbis_look_transform *)); + + /* MDCT is tranform 0 */ + + b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup)); + b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup)); + mdct_init(b->transform[0][0],ci->blocksizes[0]); + mdct_init(b->transform[1][0],ci->blocksizes[1]); + + b->window[0][0][0]=_ogg_calloc(VI_WINDOWB,sizeof(float *)); + b->window[0][0][1]=b->window[0][0][0]; + b->window[0][1][0]=b->window[0][0][0]; + b->window[0][1][1]=b->window[0][0][0]; + b->window[1][0][0]=_ogg_calloc(VI_WINDOWB,sizeof(float *)); + b->window[1][0][1]=_ogg_calloc(VI_WINDOWB,sizeof(float *)); + b->window[1][1][0]=_ogg_calloc(VI_WINDOWB,sizeof(float *)); + b->window[1][1][1]=_ogg_calloc(VI_WINDOWB,sizeof(float *)); + + for(i=0;i<VI_WINDOWB;i++){ + b->window[0][0][0][i]= + _vorbis_window(i,ci->blocksizes[0],ci->blocksizes[0]/2,ci->blocksizes[0]/2); + b->window[1][0][0][i]= + _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[0]/2,ci->blocksizes[0]/2); + b->window[1][0][1][i]= + _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[0]/2,ci->blocksizes[1]/2); + b->window[1][1][0][i]= + _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[1]/2,ci->blocksizes[0]/2); + b->window[1][1][1][i]= + _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[1]/2,ci->blocksizes[1]/2); + } + + if(encp){ /* encode/decode differ here */ + /* finish the codebooks */ + b->fullbooks=_ogg_calloc(ci->books,sizeof(codebook)); + for(i=0;i<ci->books;i++) + vorbis_book_init_encode(b->fullbooks+i,ci->book_param[i]); + v->analysisp=1; + }else{ + /* finish the codebooks */ + b->fullbooks=_ogg_calloc(ci->books,sizeof(codebook)); + for(i=0;i<ci->books;i++) + vorbis_book_init_decode(b->fullbooks+i,ci->book_param[i]); + } + + /* initialize the storage vectors to a decent size greater than the + minimum */ + + v->pcm_storage=8192; /* we'll assume later that we have + a minimum of twice the blocksize of + accumulated samples in analysis */ + v->pcm=_ogg_malloc(vi->channels*sizeof(float *)); + v->pcmret=_ogg_malloc(vi->channels*sizeof(float *)); + { + int i; + for(i=0;i<vi->channels;i++) + v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(float)); + } + + /* 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 */ + + /* all vector indexes */ + v->centerW=ci->blocksizes[1]/2; + + v->pcm_current=v->centerW; + + /* initialize all the mapping/backend lookups */ + b->mode=_ogg_calloc(ci->modes,sizeof(vorbis_look_mapping *)); + 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); +} + +/* arbitrary settings and spec-mandated numbers get filled in here */ +int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ + backend_lookup_state *b=NULL; + + _vds_shared_init(v,vi,1); + b=v->backend_state; + + /* Initialize the envelope state storage */ + b->ve=_ogg_calloc(1,sizeof(envelope_lookup)); + _ve_envelope_init(b->ve,vi); + + return(0); +} + +void vorbis_dsp_clear(vorbis_dsp_state *v){ + int i,j,k; + if(v){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=(vi?vi->codec_setup:NULL); + backend_lookup_state *b=v->backend_state; + + if(b){ + if(b->window[0][0][0]){ + for(i=0;i<VI_WINDOWB;i++) + if(b->window[0][0][0][i])_ogg_free(b->window[0][0][0][i]); + _ogg_free(b->window[0][0][0]); + + for(j=0;j<2;j++) + for(k=0;k<2;k++){ + for(i=0;i<VI_WINDOWB;i++) + if(b->window[1][j][k][i])_ogg_free(b->window[1][j][k][i]); + _ogg_free(b->window[1][j][k]); + } + } + + if(b->ve){ + _ve_envelope_clear(b->ve); + _ogg_free(b->ve); + } + + if(b->transform[0]){ + mdct_clear(b->transform[0][0]); + _ogg_free(b->transform[0][0]); + _ogg_free(b->transform[0]); + } + if(b->transform[1]){ + mdct_clear(b->transform[1][0]); + _ogg_free(b->transform[1][0]); + _ogg_free(b->transform[1]); + } + + } + + 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]); + } + /* free codebooks */ + for(i=0;i<ci->books;i++) + if(b && b->fullbooks)vorbis_book_clear(b->fullbooks+i); + } + + if(b){ + if(b->mode)_ogg_free(b->mode); + if(b->fullbooks)_ogg_free(b->fullbooks); + + /* free header, header1, header2 */ + if(b->header)_ogg_free(b->header); + if(b->header1)_ogg_free(b->header1); + if(b->header2)_ogg_free(b->header2); + _ogg_free(b); + } + + memset(v,0,sizeof(vorbis_dsp_state)); + } +} + +float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){ + int i; + vorbis_info *vi=v->vi; + backend_lookup_state *b=v->backend_state; + + /* free header, header1, header2 */ + if(b->header)_ogg_free(b->header);b->header=NULL; + if(b->header1)_ogg_free(b->header1);b->header1=NULL; + if(b->header2)_ogg_free(b->header2);b->header2=NULL; + + /* Do we have enough storage space for the requested buffer? If not, + expand the PCM (and envelope) storage */ + + if(v->pcm_current+vals>=v->pcm_storage){ + v->pcm_storage=v->pcm_current+vals*2; + + for(i=0;i<vi->channels;i++){ + v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(float)); + } + } + + for(i=0;i<vi->channels;i++) + v->pcmret[i]=v->pcm[i]+v->pcm_current; + + return(v->pcmret); +} + +static void _preextrapolate_helper(vorbis_dsp_state *v){ + int i; + int order=32; + float *lpc=alloca(order*sizeof(float)); + float *work=alloca(v->pcm_current*sizeof(float)); + long j; + v->preextrapolate=1; + + if(v->pcm_current-v->centerW>order*2){ /* safety */ + for(i=0;i<v->vi->channels;i++){ + + /* need to run the extrapolation in reverse! */ + for(j=0;j<v->pcm_current;j++) + work[j]=v->pcm[i][v->pcm_current-j-1]; + + /* prime as above */ + vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order); + + /* run the predictor filter */ + vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order, + order, + work+v->pcm_current-v->centerW, + v->centerW); + for(j=0;j<v->pcm_current;j++) + v->pcm[i][v->pcm_current-j-1]=work[j]; + } + } +} + + +/* call with val<=0 to set eof */ + +int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + + if(vals<=0){ + int order=32; + int i; + float *lpc=alloca(order*sizeof(float)); + + /* if it wasn't done earlier (very short sample) */ + if(!v->preextrapolate) + _preextrapolate_helper(v); + + /* We're encoding the end of the stream. Just make sure we have + [at least] a full block of zeroes at the end. */ + /* actually, we don't want zeroes; that could drop a large + amplitude off a cliff, creating spread spectrum noise that will + suck to encode. Extrapolate for the sake of cleanliness. */ + + vorbis_analysis_buffer(v,ci->blocksizes[1]*2); + v->eofflag=v->pcm_current; + v->pcm_current+=ci->blocksizes[1]*2; + + for(i=0;i<vi->channels;i++){ + if(v->eofflag>order*2){ + /* extrapolate with LPC to fill in */ + long n; + + /* make a predictor filter */ + n=v->eofflag; + if(n>ci->blocksizes[1])n=ci->blocksizes[1]; + vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order); + + /* run the predictor filter */ + vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order, + v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag); + }else{ + /* not enough data to extrapolate (unlikely to happen due to + guarding the overlap, but bulletproof in case that + assumtion goes away). zeroes will do. */ + memset(v->pcm[i]+v->eofflag,0, + (v->pcm_current-v->eofflag)*sizeof(float)); + + } + } + }else{ + + if(v->pcm_current+vals>v->pcm_storage) + return(OV_EINVAL); + + v->pcm_current+=vals; + + /* we may want to reverse extrapolate the beginning of a stream + too... in case we're beginning on a cliff! */ + /* clumsy, but simple. It only runs once, so simple is good. */ + if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) + _preextrapolate_helper(v); + + } + return(0); +} + +/* do the deltas, envelope shaping, pre-echo and determine the size of + the next block on which to continue analysis */ +int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ + int i; + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + backend_lookup_state *b=v->backend_state; + long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext; + + /* check to see if we're started... */ + if(!v->preextrapolate)return(0); + + /* check to see if we're done... */ + if(v->eofflag==-1)return(0); + + /* By our invariant, we have lW, W and centerW set. Search for + the next boundary so we can determine nW (the next window size) + which lets us compute the shape of the current block's window */ + + if(ci->blocksizes[0]<ci->blocksizes[1]){ + long largebound; + long bp; + + if(v->W) + /* min boundary; nW large, next small */ + largebound=v->centerW+ci->blocksizes[1]*3/4+ci->blocksizes[0]/4; + else + /* min boundary; nW large, next small */ + largebound=v->centerW+ci->blocksizes[1]*3/4+ci->blocksizes[0]*3/4; + + bp=_ve_envelope_search(v,largebound); + if(bp==-1)return(0); /* not enough data currently to search for a + full long block */ + v->nW=bp; + + }else + v->nW=0; + + centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4; + + { + /* center of next block + next block maximum right side. */ + + long blockbound=centerNext+ci->blocksizes[v->nW]/2; + if(v->pcm_current<blockbound)return(0); /* not enough data yet; + although this check is + less strict that the + _ve_envelope_search, + the search is not run + if we only use one + block size */ + } + + /* fill in the block. Note that for a short window, lW and nW are *short* + regardless of actual settings in the stream */ + + _vorbis_block_ripcord(vb); + if(v->W){ + vb->lW=v->lW; + vb->W=v->W; + vb->nW=v->nW; + }else{ + vb->lW=0; + vb->W=v->W; + vb->nW=0; + } + vb->vd=v; + vb->sequence=v->sequence; + vb->granulepos=v->granulepos; + vb->pcmend=ci->blocksizes[v->W]; + + /* copy the vectors; this uses the local storage in vb */ + { + vb->pcm=_vorbis_block_alloc(vb,sizeof(float *)*vi->channels); + vb->pcmdelay=_vorbis_block_alloc(vb,sizeof(float *)*vi->channels); + for(i=0;i<vi->channels;i++){ + vb->pcmdelay[i]= + _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(float)); + memcpy(vb->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(float)); + vb->pcm[i]=vb->pcmdelay[i]+beginW; + + /* before we added the delay + vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(float)); + memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(float)); + */ + + } + } + + /* handle eof detection: eof==0 means that we've not yet received EOF + eof>0 marks the last 'real' sample in pcm[] + eof<0 'no more to do'; doesn't get here */ + + if(v->eofflag){ + if(v->centerW>=v->eofflag){ + v->eofflag=-1; + vb->eofflag=1; + return(1); + } + } + + /* advance storage vectors and clean up */ + { + int new_centerNext=ci->blocksizes[1]/2+ci->delaycache; + int movementW=centerNext-new_centerNext; + + if(movementW>0){ + + _ve_envelope_shift(b->ve,movementW); + v->pcm_current-=movementW; + + for(i=0;i<vi->channels;i++) + memmove(v->pcm[i],v->pcm[i]+movementW, + v->pcm_current*sizeof(float)); + + + v->lW=v->W; + v->W=v->nW; + v->centerW=new_centerNext; + + v->sequence++; + + if(v->eofflag){ + v->eofflag-=movementW; + /* do not add padding to end of stream! */ + if(v->centerW>=v->eofflag){ + v->granulepos+=movementW-(v->centerW-v->eofflag); + }else{ + v->granulepos+=movementW; + } + }else{ + v->granulepos+=movementW; + } + } + } + + /* done */ + return(1); +} + +int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + _vds_shared_init(v,vi,0); + + /* Adjust centerW to allow an easier mechanism for determining output */ + v->pcm_returned=v->centerW; + v->centerW-= ci->blocksizes[v->W]/4+ci->blocksizes[v->lW]/4; + v->granulepos=-1; + v->sequence=-1; + + return(0); +} + +/* 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=vi->codec_setup; + + /* Shift out any PCM that we returned previously */ + /* centerW is currently the center of the last block added */ + + if(v->centerW>ci->blocksizes[1]/2 && + /* Quick additional hack; to avoid *alot* of shifts, use an + oversized buffer. This increases memory usage, but doesn't make + much difference wrt L1/L2 cache pressure. */ + v->pcm_returned>8192){ + + /* don't shift too much; we need to have a minimum PCM buffer of + 1/2 long block */ + + int shiftPCM=v->centerW-ci->blocksizes[1]/2; + shiftPCM=(v->pcm_returned<shiftPCM?v->pcm_returned:shiftPCM); + + v->pcm_current-=shiftPCM; + v->centerW-=shiftPCM; + v->pcm_returned-=shiftPCM; + + if(shiftPCM){ + int i; + for(i=0;i<vi->channels;i++) + memmove(v->pcm[i],v->pcm[i]+shiftPCM, + v->pcm_current*sizeof(float)); + } + } + + v->lW=v->W; + v->W=vb->W; + v->nW=-1; + + v->glue_bits+=vb->glue_bits; + v->time_bits+=vb->time_bits; + v->floor_bits+=vb->floor_bits; + v->res_bits+=vb->res_bits; + + if(v->sequence+1 != vb->sequence)v->granulepos=-1; /* out of sequence; + lose count */ + + v->sequence=vb->sequence; + + { + int sizeW=ci->blocksizes[v->W]; + int centerW=v->centerW+ci->blocksizes[v->lW]/4+sizeW/4; + int beginW=centerW-sizeW/2; + int endW=beginW+sizeW; + int beginSl; + int endSl; + int i,j; + + /* Do we have enough PCM/mult storage for the block? */ + if(endW>v->pcm_storage){ + /* expand the storage */ + v->pcm_storage=endW+ci->blocksizes[1]; + + for(i=0;i<vi->channels;i++) + v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(float)); + } + + /* overlap/add PCM */ + + switch(v->W){ + case 0: + beginSl=0; + endSl=ci->blocksizes[0]/2; + break; + case 1: + beginSl=ci->blocksizes[1]/4-ci->blocksizes[v->lW]/4; + endSl=beginSl+ci->blocksizes[v->lW]/2; + break; + default: + return(-1); + } + + for(j=0;j<vi->channels;j++){ + float *pcm=v->pcm[j]+beginW; + float *p=vb->pcm[j]; + + /* the overlap/add section */ + for(i=beginSl;i<endSl;i++) + pcm[i]+=p[i]; + /* the remaining section */ + for(;i<sizeW;i++) + pcm[i]=p[i]; + } + + /* 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(v->granulepos==-1) + if(vb->granulepos==-1){ + v->granulepos=0; + }else{ + v->granulepos=vb->granulepos; + } + else{ + v->granulepos+=(centerW-v->centerW); + if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ + + if(v->granulepos>vb->granulepos){ + long extra=v->granulepos-vb->granulepos; + + if(vb->eofflag){ + /* partial last frame. Strip the extra samples off */ + centerW-=extra; + }else if(vb->sequence == 1){ + /* partial first frame. Discard extra leading samples */ + v->pcm_returned+=extra; + if(v->pcm_returned>centerW)v->pcm_returned=centerW; + + } + + }/* else{ Shouldn't happen *unless* the bitstream is out of + spec. Either way, believe the bitstream } */ + v->granulepos=vb->granulepos; + } + } + + /* Update, cleanup */ + + v->centerW=centerW; + v->pcm_current=endW; + + 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,float ***pcm){ + vorbis_info *vi=v->vi; + if(v->pcm_returned<v->centerW){ + 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->centerW-v->pcm_returned); + } + return(0); +} + +int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){ + if(bytes && v->pcm_returned+bytes>v->centerW)return(OV_EINVAL); + v->pcm_returned+=bytes; + return(0); +} + diff --git a/lib/codec_internal.h b/lib/codec_internal.h new file mode 100644 index 00000000..d80b08ee --- /dev/null +++ b/lib/codec_internal.h @@ -0,0 +1,117 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: libvorbis codec headers + last mod: $Id: codec_internal.h,v 1.3.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_CODECI_H_ +#define _V_CODECI_H_ + +#include "envelope.h" +#include "codebook.h" +#include "psy.h" +#include "bitbuffer.h" + +typedef void vorbis_look_time; +typedef void vorbis_look_mapping; +typedef void vorbis_look_floor; +typedef void vorbis_look_residue; +typedef void vorbis_look_transform; + +typedef struct backend_lookup_state { + /* local lookup storage */ + envelope_lookup *ve; /* envelope lookup */ + float **window[2][2][2]; /* block, leadin, leadout, type */ + vorbis_look_transform **transform[2]; /* block, type */ + codebook *fullbooks; + + /* backend lookups are tied to the mode, not the backend or naked mapping */ + int modebits; + vorbis_look_mapping **mode; + + /* local storage, only used on the encoding side. This way the + application does not need to worry about freeing some packets' + memory and not others'; packet storage is always tracked. + Cleared next call to a _dsp_ function */ + unsigned char *header; + unsigned char *header1; + unsigned char *header2; + +} backend_lookup_state; + +/* mode ************************************************************/ +typedef struct { + int blockflag; + int windowtype; + int transformtype; + int mapping; +} vorbis_info_mode; + +typedef void vorbis_info_time; +typedef void vorbis_info_floor; +typedef void vorbis_info_residue; +typedef void vorbis_info_mapping; + +/* vorbis_info contains all the setup information specific to the + specific compression/decompression mode in progress (eg, + psychoacoustic settings, channel setup, options, codebook + etc). +*********************************************************************/ + +typedef struct codec_setup_info { + + /* Vorbis supports only short and long blocks, but allows the + encoder to choose the sizes */ + + long blocksizes[2]; + + /* modes are the primary means of supporting on-the-fly different + blocksizes, different channel mappings (LR or mid-side), + different residue backends, etc. Each mode consists of a + blocksize flag and a mapping (along with the mapping setup */ + + int modes; + int maps; + int times; + int floors; + int residues; + int books; + int psys; /* encode only */ + + vorbis_info_mode *mode_param[64]; + int map_type[64]; + vorbis_info_mapping *map_param[64]; + int time_type[64]; + vorbis_info_time *time_param[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]; + vorbis_info_psy *psy_param[64]; /* encode only */ + + /* for block long/sort tuning; encode only */ + int envelopesa; + float preecho_thresh; + float postecho_thresh; + float preecho_minenergy; + + /* delay caching... how many samples to keep around prior to our + current block to aid in analysis? */ + int delaycache; + +} codec_setup_info; + +#endif diff --git a/lib/envelope.c b/lib/envelope.c new file mode 100644 index 00000000..5cc18cdc --- /dev/null +++ b/lib/envelope.c @@ -0,0 +1,233 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: PCM data envelope analysis and manipulation + last mod: $Id: envelope.c,v 1.28.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + Preecho calculation. + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <ogg/ogg.h> +#include "vorbis/codec.h" +#include "codec_internal.h" + +#include "os.h" +#include "scales.h" +#include "envelope.h" +#include "misc.h" + +/* We use a Chebyshev bandbass for the preecho trigger bandpass; it's + close enough for sample rates 32000-48000 Hz (corner frequencies at + 6k/14k assuming sample rate of 44.1kHz) */ + +/* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher + Command line: /www/usr/fisher/helpers/mkfilter -Ch \ + -6.0000000000e+00 -Bp -o 5 -a 1.3605442177e-01 3.1746031746e-01 -l */ + +#if 0 +static int cheb_bandpass_stages=10; +static float cheb_bandpass_gain=5.589612458e+01f; +static float cheb_bandpass_B[]={-1.f,0.f,5.f,0.f,-10.f,0.f, + 10.f,0.f,-5.f,0.f,1f}; +static float cheb_bandpass_A[]={ + -0.1917409386f, + 0.0078657069f, + -0.7126903444f, + 0.0266343467f, + -1.4047174730f, + 0.0466964232f, + -1.9032773429f, + 0.0451493360f, + -1.4471447397f, + 0.0303413711f}; +#endif + +static int cheb_highpass_stages=10; +static float cheb_highpass_gain= 5.291963434e+01f; +/* z^-stage, z^-stage+1... */ +static float cheb_highpass_B[]={1.f,-10.f,45.f,-120.f,210.f, + -252.f,210.f,-120.f,45.f,-10.f,1.f}; +static float cheb_highpass_A[]={ + -0.1247628029f, + 0.1334086523f, + -0.3997715614f, + 0.3213011089f, + -1.1131924119f, + 1.7692446626f, + -3.6241199038f, + 4.1950871291f, + -4.2771757867f, + 2.3920318913f}; + +void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + int ch=vi->channels; + int window=ci->envelopesa; + int i; + e->winlength=window; + e->minenergy=fromdB(ci->preecho_minenergy); + e->iir=_ogg_calloc(ch,sizeof(IIR_state)); + e->filtered=_ogg_calloc(ch,sizeof(float *)); + e->ch=ch; + e->storage=128; + for(i=0;i<ch;i++){ + IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass_gain, + cheb_highpass_A,cheb_highpass_B); + e->filtered[i]=_ogg_calloc(e->storage,sizeof(float)); + } + + drft_init(&e->drft,window); + e->window=_ogg_malloc(e->winlength*sizeof(float)); + /* We just use a straight sin(x) window for this */ + for(i=0;i<e->winlength;i++) + e->window[i]=sin((i+.5)/e->winlength*M_PI); +} + +void _ve_envelope_clear(envelope_lookup *e){ + int i; + for(i=0;i<e->ch;i++){ + IIR_clear((e->iir+i)); + _ogg_free(e->filtered[i]); + } + drft_clear(&e->drft); + _ogg_free(e->window); + _ogg_free(e->filtered); + _ogg_free(e->iir); + memset(e,0,sizeof(envelope_lookup)); +} + +/* straight threshhold based until we find something that works better + and isn't patented */ +static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){ + long n=ve->winlength; + + long i; + + /* we want to have a 'minimum bar' for energy, else we're just + basing blocks on quantization noise that outweighs the signal + itself (for low power signals) */ + + float min=ve->minenergy; + float A=min*min*n; + float B=A; + + /*_analysis_output("A",granulepos,pre,n,0,0); + _analysis_output("B",granulepos,post,n,0,0);*/ + + for(i=0;i<n;i++){ + A+=pre[i]*pre[i]; + B+=post[i]*post[i]; + } + + A=todB(A); + B=todB(B); + + return(B-A); +} + +static float _ve_ampi(envelope_lookup *ve,float *pre){ + long n=ve->winlength; + + long i; + + /* we want to have a 'minimum bar' for energy, else we're just + basing blocks on quantization noise that outweighs the signal + itself (for low power signals) */ + + float min=ve->minenergy; + float A=min*min*n; + + for(i=0;i<n;i++){ + A+=pre[i]*pre[i]; + } + + A=todB(A); + return(A); +} + +long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve; + long i,j; + + /* make sure we have enough storage to match the PCM */ + if(v->pcm_storage>ve->storage){ + ve->storage=v->pcm_storage; + for(i=0;i<ve->ch;i++) + ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(float)); + } + + /* catch up the highpass to match the pcm */ + for(i=0;i<ve->ch;i++){ + float *filtered=ve->filtered[i]; + float *pcm=v->pcm[i]; + IIR_state *iir=ve->iir+i; + int flag=1; + + for(j=ve->current;j<v->pcm_current;j++){ + filtered[j]=IIR_filter(iir,pcm[j]); + if(pcm[j])flag=0; + } + if(flag && ve->current+64<v->pcm_current)IIR_reset(iir); + } + + ve->current=v->pcm_current; + + /* Now search through our cached highpass data for breaking points */ + /* starting point */ + if(v->W) + j=v->centerW+ci->blocksizes[1]/4-ci->blocksizes[0]/4; + else + j=v->centerW; + + while(j+ve->winlength<=v->pcm_current){ + for(i=0;i<ve->ch;i++){ + float *filtered=ve->filtered[i]+j; + float m=_ve_deltai(ve,filtered-ve->winlength,filtered); + + if(m>ci->preecho_thresh){ + /*granulepos++;*/ + return(0); + } + if(m<ci->postecho_thresh){ + /*granulepos++;*/ + return(0); + } + /*granulepos++;*/ + } + + j+=min(ci->blocksizes[0],ve->winlength)/2; + + if(j>=searchpoint){ + return(1); + } + } + + return(-1); +} + +void _ve_envelope_shift(envelope_lookup *e,long shift){ + int i; + for(i=0;i<e->ch;i++) + memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)* + sizeof(float)); + e->current-=shift; +} + + diff --git a/lib/floor0.c b/lib/floor0.c new file mode 100644 index 00000000..76b807da --- /dev/null +++ b/lib/floor0.c @@ -0,0 +1,430 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: floor backend 0 implementation + last mod: $Id: floor0.c,v 1.34.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ogg/ogg.h> +#include "vorbis/codec.h" +#include "codec_internal.h" +#include "registry.h" +#include "lpc.h" +#include "lsp.h" +#include "codebook.h" +#include "scales.h" +#include "misc.h" +#include "os.h" + +#include "misc.h" +#include <stdio.h> + +typedef struct { + long n; + int ln; + int m; + int *linearmap; + + vorbis_info_floor0 *vi; + lpc_lookup lpclook; + float *lsp_look; + +} vorbis_look_floor0; + +/* infrastructure for finding fit */ +static long _f0_fit(codebook *book, + float *orig, + float *workfit, + int cursor){ + int dim=book->dim; + float norm,base=0.f; + int i,best=0; + float *lsp=workfit+cursor; + + if(cursor)base=workfit[cursor-1]; + norm=orig[cursor+dim-1]-base; + + for(i=0;i<dim;i++) + lsp[i]=(orig[i+cursor]-base); + best=_best(book,lsp,1); + + memcpy(lsp,book->valuelist+best*dim,dim*sizeof(float)); + for(i=0;i<dim;i++) + lsp[i]+=base; + return(best); +} + +/***********************************************/ + +static vorbis_info_floor *floor0_copy_info (vorbis_info_floor *i){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + vorbis_info_floor0 *ret=_ogg_malloc(sizeof(vorbis_info_floor0)); + memcpy(ret,info,sizeof(vorbis_info_floor0)); + return(ret); +} + +static void floor0_free_info(vorbis_info_floor *i){ + if(i){ + memset(i,0,sizeof(vorbis_info_floor0)); + _ogg_free(i); + } +} + +static void floor0_free_look(vorbis_look_floor *i){ + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + if(i){ + if(look->linearmap)_ogg_free(look->linearmap); + if(look->lsp_look)_ogg_free(look->lsp_look); + lpc_clear(&look->lpclook); + memset(look,0,sizeof(vorbis_look_floor0)); + _ogg_free(look); + } +} + +static void floor0_pack (vorbis_info_floor *i,oggpack_buffer *opb){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + int j; + oggpack_write(opb,info->order,8); + oggpack_write(opb,info->rate,16); + oggpack_write(opb,info->barkmap,16); + oggpack_write(opb,info->ampbits,6); + oggpack_write(opb,info->ampdB,8); + oggpack_write(opb,info->numbooks-1,4); + for(j=0;j<info->numbooks;j++) + oggpack_write(opb,info->books[j],8); +} + +static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + int j; + + vorbis_info_floor0 *info=_ogg_malloc(sizeof(vorbis_info_floor0)); + 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; + + 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; + } + return(info); + + err_out: + floor0_free_info(info); + 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; + float scale; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(vorbis_look_floor0)); + look->m=info->order; + look->n=ci->blocksizes[mi->blockflag]/2; + look->ln=info->barkmap; + look->vi=info; + + if(vd->analysisp) + lpc_init(&look->lpclook,look->ln,look->m); + + /* we choose a scaling constant so that: + floor(bark(rate/2-1)*C)=mapped-1 + floor(bark(rate/2)*C)=mapped */ + scale=look->ln/toBARK(info->rate/2.f); + + /* 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=_ogg_malloc((look->n+1)*sizeof(int)); + for(j=0;j<look->n;j++){ + int val=floor( toBARK((info->rate/2.f)/look->n*j) + *scale); /* bark numbers represent band edges */ + if(val>=look->ln)val=look->ln; /* guard against the approximation */ + look->linearmap[j]=val; + } + look->linearmap[j]=-1; + + look->lsp_look=_ogg_malloc(look->ln*sizeof(float)); + for(j=0;j<look->ln;j++) + look->lsp_look[j]=2*cos(M_PI/look->ln*j); + + return look; +} + +/* less efficient than the decode side (written for clarity). We're + not bottlenecked here anyway */ + +float _curve_to_lpc(float *curve,float *lpc, + vorbis_look_floor0 *l){ + /* map the input curve to a bark-scale curve for encoding */ + + int mapped=l->ln; + float *work=alloca(sizeof(float)*mapped); + int i,j,last=0; + int bark=0; + + memset(work,0,sizeof(float)*mapped); + + /* Only the decode side is behavior-specced; for now in the encoder, + we select the maximum value of each band as representative (this + helps make sure peaks don't go out of range. In error terms, + selecting min would make more sense, but the codebook is trained + numerically, so we don't actually lose. We'd still want to + use the original curve for error and noise estimation */ + + for(i=0;i<l->n;i++){ + bark=l->linearmap[i]; + if(work[bark]<curve[i])work[bark]=curve[i]; + if(bark>last+1){ + /* If the bark scale is climbing rapidly, some bins may end up + going unused. This isn't a waste actually; it keeps the + scale resolution even so that the LPC generator has an easy + time. However, if we leave the bins empty we lose energy. + So, fill 'em in. The decoder does not do anything with he + unused bins, so we can fill them anyway we like to end up + with a better spectral curve */ + + /* we'll always have a bin zero, so we don't need to guard init */ + long span=bark-last; + for(j=1;j<span;j++){ + float del=(float)j/span; + work[j+last]=work[bark]*del+work[last]*(1.f-del); + } + } + last=bark; + } + + /* If we're over-ranged to avoid edge effects, fill in the end of spectrum gap */ + for(i=bark+1;i<mapped;i++) + work[i]=work[i-1]; + + return vorbis_lpc_from_curve(work,lpc,&(l->lpclook)); +} + +/* generate the whole freq response curve of an LSP IIR filter */ +/* didn't need in->out seperation, modifies the flr[] vector; takes in + a dB scale floor, puts out linear */ +static int floor0_forward(vorbis_block *vb,vorbis_look_floor *i, + float *flr,vorbis_bitbuffer *vbb){ + long j; + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + vorbis_info_floor0 *info=look->vi; + float amp; + long bits=0; + long val=0; + static int seq=0; + +#ifdef TRAIN_LSP + FILE *of; + FILE *ef; + char buffer[80]; + +#if 1 + sprintf(buffer,"lsp0coeff_%d.vqd",vb->mode); + of=fopen(buffer,"a"); +#endif + + sprintf(buffer,"lsp0ent_%d.vqd",vb->mode); + ef=fopen(buffer,"a"); +#endif + + /* our floor comes in on a [-Inf...0] dB scale. The curve has to be + positive, so we offset it. */ + + for(j=0;j<look->n;j++) + flr[j]+=info->ampdB; + + /* use 'out' as temp storage */ + /* Convert our floor to a set of lpc coefficients */ + amp=sqrt(_curve_to_lpc(flr,flr,look)); + + /* amp is in the range (0. to ampdB]. Encode that range using + ampbits bits */ + + { + long maxval=(1L<<info->ampbits)-1; + + val=rint(amp/info->ampdB*maxval); + + if(val<0)val=0; /* likely */ + if(val>maxval)val=maxval; /* not bloody likely */ + + /*oggpack_write(&vb->opb,val,info->ampbits);*/ + if(val>0) + amp=(float)val/maxval*info->ampdB; + else + amp=0; + } + + if(val){ + float *lspwork=alloca(look->m*sizeof(float)); + + /* the spec supports using one of a number of codebooks. Right + now, encode using this lib supports only one */ + backend_lookup_state *be=vb->vd->backend_state; + codebook *b=be->fullbooks+info->books[0]; + bitbuf_write(vbb,0,_ilog(info->numbooks)); + + /* LSP <-> LPC is orthogonal and LSP quantizes more stably */ + vorbis_lpc_to_lsp(flr,flr,look->m); + +#ifdef ANALYSIS +#ifndef TRAIN_LSP + + memcpy(lspwork,flr,look->m*sizeof(float)); + vorbis_lsp_to_curve(flr,look->linearmap,look->n,look->ln, + lspwork,look->m,amp,info->ampdB); + _analysis_output("prefit",seq,flr,look->n,0,1); + +#endif +#endif + + +#if 1 +#ifdef TRAIN_LSP + { + float last=0.f; + for(j=0;j<look->m;j++){ + fprintf(of,"%.12g, ",flr[j]-last); + last=flr[j]; + } + } + fprintf(of,"\n"); + fclose(of); +#endif +#endif + + /* code the spectral envelope, and keep track of the actual + quantized values; we don't want creeping error as each block is + nailed to the last quantized value of the previous block. */ + + for(j=0;j<look->m;j+=b->dim){ + int entry=_f0_fit(b,flr,lspwork,j); + bits+=vorbis_book_bufencode(b,entry,vbb); + +#ifdef TRAIN_LSP + fprintf(ef,"%d,\n",entry); +#endif + + } + +#ifdef TRAIN_LSP + fclose(ef); +#endif + + /* take the coefficients back to a spectral envelope curve */ + vorbis_lsp_to_curve(flr,look->linearmap,look->n,look->ln, + lspwork,look->m,amp,info->ampdB); + return(val); + } + + memset(flr,0,sizeof(float)*look->n); + seq++; + return(val); +} + +static float floor0_forward2(vorbis_block *vb,vorbis_look_floor *i, + long amp,float error, + vorbis_bitbuffer *vbb){ + + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + vorbis_info_floor0 *info=look->vi; + if(amp){ + long maxval=(1L<<info->ampbits)-1; + long adj=rint(todB(error)/info->ampdB*maxval/2); + + amp+=adj; + if(amp<1)amp=1; + + oggpack_write(&vb->opb,amp,info->ampbits); + bitbuf_pack(&vb->opb,vbb); + return(fromdB((float)adj/maxval*info->ampdB)); + }else{ + oggpack_write(&vb->opb,0,info->ampbits); + bitbuf_pack(&vb->opb,vbb); + } + return(0.f); +} + + +static int floor0_inverse(vorbis_block *vb,vorbis_look_floor *i,float *out){ + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + vorbis_info_floor0 *info=look->vi; + int j,k; + + int ampraw=oggpack_read(&vb->opb,info->ampbits); + if(ampraw>0){ /* also handles the -1 out of data case */ + long maxval=(1<<info->ampbits)-1; + float amp=(float)ampraw/maxval*info->ampdB; + int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); + float *lsp=alloca(sizeof(float)*look->m); + + if(booknum!=-1){ + backend_lookup_state *be=vb->vd->backend_state; + codebook *b=be->fullbooks+info->books[booknum]; + float last=0.f; + + memset(out,0,sizeof(float)*look->m); + + for(j=0;j<look->m;j+=b->dim) + if(vorbis_book_decodevs(b,lsp+j,&vb->opb,1,-1)==-1)goto eop; + for(j=0;j<look->m;){ + for(k=0;k<b->dim;k++,j++)lsp[j]+=last; + last=lsp[j-1]; + } + + /* 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); + return(1); + } + } + + eop: + memset(out,0,sizeof(float)*look->n); + return(0); +} + +/* export hooks */ +vorbis_func_floor floor0_exportbundle={ + &floor0_pack,&floor0_unpack,&floor0_look,&floor0_copy_info,&floor0_free_info, + &floor0_free_look,&floor0_forward,&floor0_forward2,&floor0_inverse +}; + + diff --git a/lib/info.c b/lib/info.c new file mode 100644 index 00000000..54558689 --- /dev/null +++ b/lib/info.c @@ -0,0 +1,571 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: maintain the info structure, info <-> header packets + last mod: $Id: info.c,v 1.33.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + ********************************************************************/ + +/* general handling of the header and the vorbis_info structure (and + substructures) */ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <ogg/ogg.h> +#include "vorbis/codec.h" +#include "backends.h" +#include "codec_internal.h" +#include "codebook.h" +#include "registry.h" +#include "window.h" +#include "psy.h" +#include "misc.h" +#include "os.h" + +/* helpers */ +static int ilog2(unsigned int v){ + int ret=0; + while(v>1){ + ret++; + v>>=1; + } + return(ret); +} + +static void _v_writestring(oggpack_buffer *o,char *s){ + while(*s){ + oggpack_write(o,*s++,8); + } +} + +static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ + while(bytes--){ + *buf++=oggpack_read(o,8); + } +} + +void vorbis_comment_init(vorbis_comment *vc){ + memset(vc,0,sizeof(vorbis_comment)); +} + +void vorbis_comment_add(vorbis_comment *vc,char *comment){ + vc->user_comments=_ogg_realloc(vc->user_comments, + (vc->comments+2)*sizeof(char *)); + vc->comment_lengths=_ogg_realloc(vc->comment_lengths, + (vc->comments+2)*sizeof(int)); + vc->user_comments[vc->comments]=strdup(comment); + vc->comment_lengths[vc->comments]=strlen(comment); + vc->comments++; + vc->user_comments[vc->comments]=NULL; +} + +void vorbis_comment_add_tag(vorbis_comment *vc, char *tag, char *contents){ + char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */ + strcpy(comment, tag); + strcat(comment, "="); + strcat(comment, contents); + vorbis_comment_add(vc, comment); +} + +/* This is more or less the same as strncasecmp - but that doesn't exist + * everywhere, and this is a fairly trivial function, so we include it */ +static int tagcompare(const char *s1, const char *s2, int n){ + int c=0; + while(c < n){ + if(toupper(s1[c]) != toupper(s2[c])) + return !0; + c++; + } + return 0; +} + +char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ + long i; + int found = 0; + int taglen = strlen(tag)+1; /* +1 for the = we append */ + char *fulltag = alloca(taglen+ 1); + + strcpy(fulltag, tag); + strcat(fulltag, "="); + + for(i=0;i<vc->comments;i++){ + if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ + if(count == found) + /* We return a pointer to the data, not a copy */ + return vc->user_comments[i] + taglen; + else + found++; + } + } + return NULL; /* didn't find anything */ +} + +int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ + int i,count=0; + int taglen = strlen(tag)+1; /* +1 for the = we append */ + char *fulltag = alloca(taglen+1); + strcpy(fulltag,tag); + strcat(fulltag, "="); + + for(i=0;i<vc->comments;i++){ + if(!tagcompare(vc->user_comments[i], fulltag, taglen)) + count++; + } + + return count; +} + +void vorbis_comment_clear(vorbis_comment *vc){ + if(vc){ + long i; + for(i=0;i<vc->comments;i++) + if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); + if(vc->user_comments)_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(vorbis_comment)); +} + +/* used by synthesis, which has a full, alloced vi */ +void vorbis_info_init(vorbis_info *vi){ + memset(vi,0,sizeof(vorbis_info)); + vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info)); +} + +void vorbis_info_clear(vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + int i; + + if(ci){ + + for(i=0;i<ci->modes;i++) + if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); + + for(i=0;i<ci->maps;i++) /* unpack does the range checking */ + _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); + + for(i=0;i<ci->times;i++) /* unpack does the range checking */ + _time_P[ci->time_type[i]]->free_info(ci->time_param[i]); + + for(i=0;i<ci->floors;i++) /* unpack does the range checking */ + _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); + + for(i=0;i<ci->residues;i++) /* unpack does the range checking */ + _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]); + } + } + + for(i=0;i<ci->psys;i++) + _vi_psy_free(ci->psy_param[i]); + + _ogg_free(ci); + } + + memset(vi,0,sizeof(vorbis_info)); +} + +/* Header packing/unpacking ********************************************/ + +static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + if(!ci)return(OV_EFAULT); + + vi->version=oggpack_read(opb,32); + if(vi->version!=0)return(OV_EVERSION); + + vi->channels=oggpack_read(opb,8); + vi->rate=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); + + ci->blocksizes[0]=1<<oggpack_read(opb,4); + ci->blocksizes[1]=1<<oggpack_read(opb,4); + + if(vi->rate<1)goto err_out; + if(vi->channels<1)goto err_out; + if(ci->blocksizes[0]<8)goto err_out; + if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; + + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ + + return(0); + err_out: + vorbis_info_clear(vi); + return(OV_EBADHEADER); +} + +static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ + int i; + int vendorlen=oggpack_read(opb,32); + if(vendorlen<0)goto err_out; + vc->vendor=_ogg_calloc(vendorlen+1,1); + _v_readstring(opb,vc->vendor,vendorlen); + vc->comments=oggpack_read(opb,32); + if(vc->comments<0)goto err_out; + vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(char **)); + vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(int)); + + for(i=0;i<vc->comments;i++){ + int len=oggpack_read(opb,32); + if(len<0)goto err_out; + vc->comment_lengths[i]=len; + vc->user_comments[i]=_ogg_calloc(len+1,1); + _v_readstring(opb,vc->user_comments[i],len); + } + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ + + return(0); + err_out: + vorbis_comment_clear(vc); + return(OV_EBADHEADER); +} + +/* all of the real encoding details are here. The modes, books, + everything */ +static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + int i; + if(!ci)return(OV_EFAULT); + + /* codebooks */ + ci->books=oggpack_read(opb,8)+1; + /*ci->book_param=_ogg_calloc(ci->books,sizeof(static_codebook *));*/ + for(i=0;i<ci->books;i++){ + ci->book_param[i]=_ogg_calloc(1,sizeof(static_codebook)); + if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; + } + + /* time backend settings */ + ci->times=oggpack_read(opb,6)+1; + /*ci->time_type=_ogg_malloc(ci->times*sizeof(int));*/ + /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/ + 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); + if(!ci->time_param[i])goto err_out; + } + + /* floor backend settings */ + ci->floors=oggpack_read(opb,6)+1; + /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(int));*/ + /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/ + for(i=0;i<ci->floors;i++){ + ci->floor_type[i]=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_param[i])goto err_out; + } + + /* residue backend settings */ + ci->residues=oggpack_read(opb,6)+1; + /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(int));*/ + /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/ + 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; + } + + /* map backend settings */ + ci->maps=oggpack_read(opb,6)+1; + /*ci->map_type=_ogg_malloc(ci->maps*sizeof(int));*/ + /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/ + 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; + } + + /* mode settings */ + ci->modes=oggpack_read(opb,6)+1; + /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/ + for(i=0;i<ci->modes;i++){ + ci->mode_param[i]=_ogg_calloc(1,sizeof(vorbis_info_mode)); + 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(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ + + return(0); + err_out: + vorbis_info_clear(vi); + return(OV_EBADHEADER); +} + +/* 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; + + if(op){ + oggpack_readinit(&opb,op->packet,op->bytes); + + /* Which of the three types of header is this? */ + /* Also verify header-ness, vorbis */ + { + char buffer[6]; + int packtype=oggpack_read(&opb,8); + memset(buffer,0,6); + _v_readstring(&opb,buffer,6); + if(memcmp(buffer,"vorbis",6)){ + /* not a vorbis header */ + return(OV_ENOTVORBIS); + } + switch(packtype){ + case 0x01: /* least significant *bit* is read first */ + if(!op->b_o_s){ + /* Not the initial packet */ + return(OV_EBADHEADER); + } + if(vi->rate!=0){ + /* previously initialized info header */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_info(vi,&opb)); + + case 0x03: /* least significant *bit* is read first */ + if(vi->rate==0){ + /* um... we didn't get the initial header */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_comment(vc,&opb)); + + case 0x05: /* least significant *bit* is read first */ + if(vi->rate==0 || vc->vendor==NULL){ + /* um... we didn;t get the initial header or comments yet */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_books(vi,&opb)); + + default: + /* Not a valid vorbis header type */ + return(OV_EBADHEADER); + break; + } + } + } + return(OV_EBADHEADER); +} + +/* pack side **********************************************************/ + +static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + if(!ci)return(OV_EFAULT); + + /* preamble */ + oggpack_write(opb,0x01,8); + _v_writestring(opb,"vorbis"); + + /* basic information about the stream */ + oggpack_write(opb,0x00,32); + oggpack_write(opb,vi->channels,8); + oggpack_write(opb,vi->rate,32); + + oggpack_write(opb,vi->bitrate_upper,32); + oggpack_write(opb,vi->bitrate_nominal,32); + oggpack_write(opb,vi->bitrate_lower,32); + + oggpack_write(opb,ilog2(ci->blocksizes[0]),4); + oggpack_write(opb,ilog2(ci->blocksizes[1]),4); + oggpack_write(opb,1,1); + + return(0); +} + +static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){ + char temp[]="Xiphophorus libVorbis I 20001223"; + + /* preamble */ + oggpack_write(opb,0x03,8); + _v_writestring(opb,"vorbis"); + + /* vendor */ + oggpack_write(opb,strlen(temp),32); + _v_writestring(opb,temp); + + /* comments */ + + oggpack_write(opb,vc->comments,32); + if(vc->comments){ + int i; + for(i=0;i<vc->comments;i++){ + if(vc->user_comments[i]){ + oggpack_write(opb,vc->comment_lengths[i],32); + _v_writestring(opb,vc->user_comments[i]); + }else{ + oggpack_write(opb,0,32); + } + } + } + oggpack_write(opb,1,1); + + return(0); +} + +static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + int i; + if(!ci)return(OV_EFAULT); + + oggpack_write(opb,0x05,8); + _v_writestring(opb,"vorbis"); + + /* books */ + oggpack_write(opb,ci->books-1,8); + for(i=0;i<ci->books;i++) + if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out; + + /* times */ + oggpack_write(opb,ci->times-1,6); + for(i=0;i<ci->times;i++){ + oggpack_write(opb,ci->time_type[i],16); + _time_P[ci->time_type[i]]->pack(ci->time_param[i],opb); + } + + /* floors */ + oggpack_write(opb,ci->floors-1,6); + for(i=0;i<ci->floors;i++){ + oggpack_write(opb,ci->floor_type[i],16); + _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb); + } + + /* residues */ + oggpack_write(opb,ci->residues-1,6); + for(i=0;i<ci->residues;i++){ + oggpack_write(opb,ci->residue_type[i],16); + _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb); + } + + /* maps */ + oggpack_write(opb,ci->maps-1,6); + for(i=0;i<ci->maps;i++){ + oggpack_write(opb,ci->map_type[i],16); + _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb); + } + + /* modes */ + oggpack_write(opb,ci->modes-1,6); + for(i=0;i<ci->modes;i++){ + oggpack_write(opb,ci->mode_param[i]->blockflag,1); + oggpack_write(opb,ci->mode_param[i]->windowtype,16); + oggpack_write(opb,ci->mode_param[i]->transformtype,16); + oggpack_write(opb,ci->mode_param[i]->mapping,8); + } + oggpack_write(opb,1,1); + + return(0); +err_out: + return(-1); +} + +int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code){ + int ret=OV_EIMPL; + vorbis_info *vi=v->vi; + oggpack_buffer opb; + backend_lookup_state *b=v->backend_state; + + if(!b){ + ret=OV_EFAULT; + goto err_out; + } + + /* first header packet **********************************************/ + + oggpack_writeinit(&opb); + if(_vorbis_pack_info(&opb,vi))goto err_out; + + /* build the packet */ + if(b->header)_ogg_free(b->header); + b->header=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header,opb.buffer,oggpack_bytes(&opb)); + op->packet=b->header; + op->bytes=oggpack_bytes(&opb); + op->b_o_s=1; + op->e_o_s=0; + op->granulepos=0; + + /* second header packet (comments) **********************************/ + + oggpack_reset(&opb); + if(_vorbis_pack_comment(&opb,vc))goto err_out; + + if(b->header1)_ogg_free(b->header1); + b->header1=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header1,opb.buffer,oggpack_bytes(&opb)); + op_comm->packet=b->header1; + op_comm->bytes=oggpack_bytes(&opb); + op_comm->b_o_s=0; + op_comm->e_o_s=0; + op_comm->granulepos=0; + + /* third header packet (modes/codebooks) ****************************/ + + oggpack_reset(&opb); + if(_vorbis_pack_books(&opb,vi))goto err_out; + + if(b->header2)_ogg_free(b->header2); + b->header2=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header2,opb.buffer,oggpack_bytes(&opb)); + op_code->packet=b->header2; + op_code->bytes=oggpack_bytes(&opb); + op_code->b_o_s=0; + op_code->e_o_s=0; + op_code->granulepos=0; + + oggpack_writeclear(&opb); + return(0); + err_out: + oggpack_writeclear(&opb); + memset(op,0,sizeof(ogg_packet)); + memset(op_comm,0,sizeof(ogg_packet)); + memset(op_code,0,sizeof(ogg_packet)); + + if(b->header)_ogg_free(b->header); + if(b->header1)_ogg_free(b->header1); + if(b->header2)_ogg_free(b->header2); + b->header=NULL; + b->header1=NULL; + b->header2=NULL; + return(ret); +} + diff --git a/lib/mapping0.c b/lib/mapping0.c new file mode 100644 index 00000000..76c97eb1 --- /dev/null +++ b/lib/mapping0.c @@ -0,0 +1,441 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: channel mapping 0 implementation + last mod: $Id: mapping0.c,v 1.22.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + ********************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <ogg/ogg.h> +#include "vorbis/codec.h" +#include "codec_internal.h" +#include "codebook.h" +#include "bitbuffer.h" +#include "registry.h" +#include "psy.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 { + drft_lookup fft_look; + vorbis_info_mode *mode; + vorbis_info_mapping0 *map; + + vorbis_look_time **time_look; + vorbis_look_floor **floor_look; + + vorbis_look_residue **residue_look; + vorbis_look_psy *psy_look; + + vorbis_func_time **time_func; + 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 vorbis_info_mapping *mapping0_copy_info(vorbis_info_mapping *vm){ + vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm; + vorbis_info_mapping0 *ret=_ogg_malloc(sizeof(vorbis_info_mapping0)); + memcpy(ret,info,sizeof(vorbis_info_mapping0)); + return(ret); +} + +static void mapping0_free_info(vorbis_info_mapping *i){ + if(i){ + memset(i,0,sizeof(vorbis_info_mapping0)); + _ogg_free(i); + } +} + +static void mapping0_free_look(vorbis_look_mapping *look){ + int i; + vorbis_look_mapping0 *l=(vorbis_look_mapping0 *)look; + if(l){ + drft_clear(&l->fft_look); + + for(i=0;i<l->map->submaps;i++){ + l->time_func[i]->free_look(l->time_look[i]); + l->floor_func[i]->free_look(l->floor_look[i]); + l->residue_func[i]->free_look(l->residue_look[i]); + if(l->psy_look)_vp_psy_clear(l->psy_look+i); + } + + _ogg_free(l->time_func); + _ogg_free(l->floor_func); + _ogg_free(l->residue_func); + _ogg_free(l->time_look); + _ogg_free(l->floor_look); + _ogg_free(l->residue_look); + if(l->psy_look)_ogg_free(l->psy_look); + memset(l,0,sizeof(vorbis_look_mapping0)); + _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=vi->codec_setup; + vorbis_look_mapping0 *look=_ogg_calloc(1,sizeof(vorbis_look_mapping0)); + vorbis_info_mapping0 *info=look->map=(vorbis_info_mapping0 *)m; + look->mode=vm; + + look->time_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_time *)); + look->floor_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_floor *)); + + look->residue_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_residue *)); + if(ci->psys)look->psy_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_psy)); + + look->time_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_time *)); + look->floor_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_floor *)); + look->residue_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_residue *)); + + for(i=0;i<info->submaps;i++){ + int timenum=info->timesubmap[i]; + int floornum=info->floorsubmap[i]; + int resnum=info->residuesubmap[i]; + + look->time_func[i]=_time_P[ci->time_type[timenum]]; + look->time_look[i]=look->time_func[i]-> + look(vd,vm,ci->time_param[timenum]); + 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]); + + if(ci->psys && vd->analysisp){ + int psynum=info->psysubmap[i]; + _vp_psy_init(look->psy_look+i,ci->psy_param[psynum], + ci->blocksizes[vm->blockflag]/2,vi->rate); + } + } + + look->ch=vi->channels; + + if(vd->analysisp)drft_init(&look->fft_look,ci->blocksizes[vm->blockflag]); + return(look); +} + +static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm,oggpack_buffer *opb){ + int i; + vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm; + + oggpack_write(opb,info->submaps-1,4); + /* we don't write the channel submappings if we only have one... */ + if(info->submaps>1){ + for(i=0;i<vi->channels;i++) + oggpack_write(opb,info->chmuxlist[i],4); + } + for(i=0;i<info->submaps;i++){ + oggpack_write(opb,info->timesubmap[i],8); + oggpack_write(opb,info->floorsubmap[i],8); + oggpack_write(opb,info->residuesubmap[i],8); + } +} + +/* also responsible for range checking */ +static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){ + int i; + vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(vorbis_info_mapping0)); + codec_setup_info *ci=vi->codec_setup; + memset(info,0,sizeof(vorbis_info_mapping0)); + + info->submaps=oggpack_read(opb,4)+1; + + if(info->submaps>1){ + for(i=0;i<vi->channels;i++){ + info->chmuxlist[i]=oggpack_read(opb,4); + if(info->chmuxlist[i]>=info->submaps)goto err_out; + } + } + for(i=0;i<info->submaps;i++){ + info->timesubmap[i]=oggpack_read(opb,8); + if(info->timesubmap[i]>=ci->times)goto err_out; + info->floorsubmap[i]=oggpack_read(opb,8); + if(info->floorsubmap[i]>=ci->floors)goto err_out; + info->residuesubmap[i]=oggpack_read(opb,8); + if(info->residuesubmap[i]>=ci->residues)goto err_out; + } + + return info; + + err_out: + mapping0_free_info(info); + return(NULL); +} + +#include "os.h" +#include "lpc.h" +#include "lsp.h" +#include "envelope.h" +#include "mdct.h" +#include "psy.h" +#include "scales.h" + +/* no time mapping implementation for now */ +static long seq=0; +static int mapping0_forward(vorbis_block *vb,vorbis_look_mapping *l){ + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + backend_lookup_state *b=vb->vd->backend_state; + vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l; + vorbis_info_mapping0 *info=look->map; + vorbis_info_mode *mode=look->mode; + int n=vb->pcmend; + int i,j; + float *window=b->window[vb->W][vb->lW][vb->nW][mode->windowtype]; + + float **pcmbundle=alloca(sizeof(float *)*vi->channels); + + int *nonzero=alloca(sizeof(int)*vi->channels); + + float **floor=_vorbis_block_alloc(vb,vi->channels*sizeof(float *)); + float *additional=_vorbis_block_alloc(vb,n*sizeof(float)); + + vorbis_bitbuffer vbb_res; + vorbis_bitbuffer *vbb_flr=_vorbis_block_alloc(vb, + sizeof(vorbis_bitbuffer)* + vi->channels); + + for(i=0;i<vi->channels;i++) + bitbuf_init(vbb_flr+i,vb); + bitbuf_init(&vbb_res,vb); + + for(i=0;i<vi->channels;i++){ + float *pcm=vb->pcm[i]; + float scale=4.f/n; + int submap=info->chmuxlist[i]; + + /* window the PCM data */ + for(j=0;j<n;j++) + additional[j]=pcm[j]*=window[j]; + + /* transform the PCM data */ + /* only MDCT right now.... */ + mdct_forward(b->transform[vb->W][0],pcm,pcm); + + /* FFT yields more accurate tonal estimation (not phase sensitive) */ + drft_forward(&look->fft_look,additional); + + additional[0]*=scale; + for(j=1;j<n-1;j+=2) + additional[(j+1)>>1]=scale*FAST_HYPOT(additional[j],additional[j+1]); + + /* set up our masking data working vector, and stash unquantized + data for later */ + memcpy(pcm+n/2,pcm,n*sizeof(float)/2); + memcpy(additional+n/2,pcm,n*sizeof(float)/2); + + /* begin masking work */ + floor[i]=_vorbis_block_alloc(vb,n*sizeof(float)/2); + + _analysis_output("fft",seq,additional,n/2,0,1); + _analysis_output("mdct",seq,additional+n/2,n/2,0,1); + _analysis_output("lfft",seq,additional,n/2,0,0); + _analysis_output("lmdct",seq,additional+n/2,n/2,0,0); + + /* perform psychoacoustics; do masking */ + _vp_compute_mask(look->psy_look+submap,additional,additional+n/2, + floor[i],NULL); + + _analysis_output("prefloor",seq,floor[i],n/2,0,0); + + /* perform floor encoding */ + nonzero[i]=look->floor_func[submap]-> + forward(vb,look->floor_look[submap],floor[i],vbb_flr+i); + + _analysis_output("floor",seq,floor[i],n/2,0,1); + + /* apply the floor, do optional noise levelling */ + _vp_apply_floor(look->psy_look+submap,pcm,floor[i]); + + _analysis_output("res",seq++,pcm,n/2,0,0); + +#ifdef TRAIN_RES + if(nonzero[i]){ + FILE *of; + char buffer[80]; + int i; + + sprintf(buffer,"residue_%d.vqd",vb->mode); + of=fopen(buffer,"a"); + for(i=0;i<n/2;i++) + fprintf(of,"%.2f, ",pcm[i]); + fprintf(of,"\n"); + fclose(of); + } +#endif + + } + + /* perform residue encoding with residue mapping; this is + multiplexed. All the channels belonging to one submap are + encoded (values interleaved), then the next submap, etc */ + + for(i=0;i<info->submaps;i++){ + int ch_in_bundle=0; + for(j=0;j<vi->channels;j++){ + if(info->chmuxlist[j]==i && nonzero[j]>0){ + pcmbundle[ch_in_bundle++]=vb->pcm[j]; + } + } + + look->residue_func[i]->forward(vb,look->residue_look[i], + pcmbundle,ch_in_bundle,&vbb_res); + } + + /* go back and compute the original MDCT inverse and our quantized + inverse; we'll want to give the floor mapping a shot at + massaging things before we write out the final version. */ + + { + for(i=0;i<vi->channels;i++){ + float *pcm=vb->pcm[i]; + float *pcmori=vb->pcm[i]+n/2; + float *quant=floor[i]; + float num=0.f,den=0.f; + int submap=info->chmuxlist[i]; + + if(nonzero[i]){ + + mdct_backward(b->transform[vb->W][0],pcm+n/2,additional); + for(j=0;j<n;j++) + additional[j]*=window[j]; + + for(j=0;j<n/2;j++) + pcm[j]=pcmori[j]-pcm[j]*quant[j]; + mdct_backward(b->transform[vb->W][0],pcm,pcm); + for(j=0;j<n;j++) + pcm[j]*=window[j]; + + /* weighted compare twixt original and quantized mdct output */ + for(j=0;j<n;j++){ + den+=(pcm[j]*pcm[j]); + num+=(additional[j]*additional[j]); + } + + num=sqrt(num); + den=sqrt(den); + + } + + look->floor_func[submap]-> + forward2(vb,look->floor_look[submap], + nonzero[i],den==0.f?0.:num/den,vbb_flr+i); + + } + } + + bitbuf_pack(&vb->opb,&vbb_res); + + look->lastframe=vb->sequence; + return(0); +} + +static int mapping0_inverse(vorbis_block *vb,vorbis_look_mapping *l){ + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + backend_lookup_state *b=vd->backend_state; + vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l; + vorbis_info_mapping0 *info=look->map; + vorbis_info_mode *mode=look->mode; + int i,j; + long n=vb->pcmend=ci->blocksizes[vb->W]; + + float *window=b->window[vb->W][vb->lW][vb->nW][mode->windowtype]; + float **pcmbundle=alloca(sizeof(float *)*vi->channels); + int *nonzero=alloca(sizeof(int)*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++){ + float *pcm=vb->pcm[i]; + int submap=info->chmuxlist[i]; + nonzero[i]=look->floor_func[submap]-> + inverse(vb,look->floor_look[submap],pcm); + _analysis_output("ifloor",seq+i,pcm,n/2,0,1); + } + + /* recover the residue, apply directly to the spectral envelope */ + + for(i=0;i<info->submaps;i++){ + int ch_in_bundle=0; + for(j=0;j<vi->channels;j++){ + if(info->chmuxlist[j]==i && nonzero[j]) + pcmbundle[ch_in_bundle++]=vb->pcm[j]; + } + + look->residue_func[i]->inverse(vb,look->residue_look[i],pcmbundle,ch_in_bundle); + } + + /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ + /* only MDCT right now.... */ + for(i=0;i<vi->channels;i++){ + float *pcm=vb->pcm[i]; + _analysis_output("out",seq+i,pcm,n/2,0,1); + mdct_backward(b->transform[vb->W][0],pcm,pcm); + } + + /* now apply the decoded pre-window time information */ + /* NOT IMPLEMENTED */ + + /* window the data */ + for(i=0;i<vi->channels;i++){ + float *pcm=vb->pcm[i]; + if(nonzero[i]) + for(j=0;j<n;j++) + pcm[j]*=window[j]; + else + for(j=0;j<n;j++) + pcm[j]=0.f; + _analysis_output("final",seq++,pcm,n,0,0); + } + + /* now apply the decoded post-window time information */ + /* NOT IMPLEMENTED */ + + /* all done! */ + return(0); +} + +/* export hooks */ +vorbis_func_mapping mapping0_exportbundle={ + &mapping0_pack,&mapping0_unpack,&mapping0_look,&mapping0_copy_info, + &mapping0_free_info,&mapping0_free_look,&mapping0_forward,&mapping0_inverse +}; + + + diff --git a/lib/modes/mode_A.h b/lib/modes/mode_A.h new file mode 100644 index 00000000..206fd76e --- /dev/null +++ b/lib/modes/mode_A.h @@ -0,0 +1,300 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: predefined encoding modes + last mod: $Id: mode_A.h,v 1.7.2.1 2000/12/27 23:46:38 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_MODES_A_H_ +#define _V_MODES_A_H_ + +#include <stdio.h> +#include "vorbis/codec.h" +#include "backends.h" + +#include "books/lsp12_0.vqh" +#include "books/lsp30_0.vqh" + +#include "books/res0_128_128aux.vqh" +#include "books/res0_128_1024aux.vqh" + +#include "books/res0_128_128_1.vqh" +#include "books/res0_128_128_2.vqh" +#include "books/res0_128_128_3.vqh" +#include "books/res0_128_128_4.vqh" +#include "books/res0_128_128_5.vqh" + +#include "books/res0_128_1024_1.vqh" +#include "books/res0_128_1024_2.vqh" +#include "books/res0_128_1024_3.vqh" +#include "books/res0_128_1024_4.vqh" +#include "books/res0_128_1024_5.vqh" +#include "books/res0_128_1024_6.vqh" +#include "books/res0_128_1024_7.vqh" +#include "books/res0_128_1024_8.vqh" +#include "books/res0_128_1024_9.vqh" + + +static vorbis_info_psy _psy_set_A0={ + 1,/*athp*/ + 1,/*decayp*/ + + -100., + -140., + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 2, /* nearDCp */ + -40.f, /* nearDCdB */ + + 1,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*63*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*88*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*125*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*175*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*250*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*350*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*500*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*700*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*1000*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*1400*/ + {-40.,-40.,-40.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*2000*/ + {-40.,-40.,-40.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*2800*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*4000*/ + {-30.,-30.,-35.,-37.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*5600*/ + {-20.,-25.,-30.,-35.,-35.,-50.,-60.,-70.,-80.,-90.,-100.}, /*8000*/ + {-20.,-25.,-30.,-33.,-35.,-45.,-55.,-65.,-75.,-90.,-100.}, /*11500*/ + {-20.,-24.,-26.,-32.,-35.,-45.,-55.,-65.,-75.,-90.,-100.}, /*16000*/ + }, + + 1,/* peakattp */ + {{-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-28.,-28.,-28.}, /*63*/ + {-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-28.,-28.,-28.}, /*88*/ + {-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-28.,-28.,-28.}, /*125*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-18.,-28.,-28.,-28.}, /*175*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-18.,-28.,-28.,-28.}, /*250*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-18.,-28.,-28.,-28.}, /*350*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-28.,-28.,-28.,-28.}, /*500*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*700*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*1000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*1400*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*2000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*2400*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*4000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*5600*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-16.,-17.}, /*8000*/ + { -6., -7., -9., -9., -9., -9.,-10.,-11.,-12.,-13.,-14.}, /*11500*/ + { -6., -6., -9., -9., -9., -9., -9., -9.,-10.,-11.,-12.}, /*16000*/ + }, + + 1,/*noisemaskp */ + -40.f, /* noisemaxsupp */ + .5, /* low window */ + .5, /* high window */ + 5, + 5, + {.000, /*63*/ + .000, /*88*/ + .000, /*125*/ + .000, /*175*/ + .000, /*250*/ + .000, /*350*/ + .000, /*500*/ + .500, /*700*/ + .600, /*1000*/ + .600, /*1400*/ + .500, /*2000*/ + .500, /*2800*/ + .750, /*4000*/ + .850, /*5600*/ + .900, /*8000*/ + .900, /*11500*/ + .950, /*16000*/ + }, + + 100., + + -0., -.004 /* attack/decay control */ +}; + +static vorbis_info_psy _psy_set_A={ + 1,/*athp*/ + 1,/*decayp*/ + + -100.f, + -140.f, + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 1, /* nearDCp */ + -40.f, /* nearDCdB */ + + 1,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*63*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*88*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*125*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*175*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*250*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*350*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*500*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*700*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1000*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1400*/ + {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2000*/ + {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2800*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*4000*/ + {-30.f,-30.f,-35.f,-37.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*5600*/ + {-20.f,-25.f,-30.f,-35.f,-35.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*8000*/ + {-20.f,-25.f,-30.f,-33.f,-35.f,-45.f,-55.f,-65.f,-75.f,-90.f,-100.f}, /*11500*/ + {-20.f,-24.f,-26.f,-32.f,-35.f,-45.f,-55.f,-65.f,-75.f,-90.f,-100.f}, /*16000*/ + }, + + 1,/* peakattp */ + {{-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}, + {-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f,-30.f}}, + + 1, /* noisemaskp */ + -40.f, /* noisemaxsupp */ + .5, /* low window */ + .5, /* high window */ + 25, + 25, + {.000, /*63*/ + .000, /*88*/ + .000, /*125*/ + .000, /*175*/ + .000, /*250*/ + .000, /*350*/ + .000, /*500*/ + .500, /*700*/ + .600, /*1000*/ + .600, /*1400*/ + .500, /*2000*/ + .500, /*2800*/ + .750, /*4000*/ + .850, /*5600*/ + .900, /*8000*/ + .900, /*11500*/ + .950, /*16000*/ + }, + + 100.f, + + -0.f, -.004f /* attack/decay control */ +}; + +/* with GNUisms, this could be short and readable. Oh well */ +static vorbis_info_time0 _time_set0A={0}; +static vorbis_info_floor0 _floor_set0A={12, 44100, 64, 12,150, 1, {0} }; +static vorbis_info_floor0 _floor_set1A={30, 44100, 256, 12,150, 1, {1} }; +static vorbis_info_residue0 _residue_set0A={0,128, 32,6,2, + {0,1,1,1,1,1}, + {4,5,6,7,8}, + + {0,99999,9999,9999,9999}, + {99.f,1.5f,2.5f,6.5f,12.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + +static vorbis_info_residue0 _residue_set1A={0,1024, 32,10,3, + {0,1,1,1,1,1,1,1,1,1}, + {9,10,11,12,13,14,15,16,17}, + + {0,8,9999,17,9999, + 28,9999,9999,9999}, + {99.f,1.5f,1.5f,2.5f,2.5f, + 4.f,4.f,6.5f,12.5f}, + {5,5,5,5,5,5,5,5,5}, + {99,99,99,99,99,99,99,99,99}}; + +static vorbis_info_mapping0 _mapping_set0A={1, {0,0}, {0}, {0}, {0}, {0}}; +static vorbis_info_mapping0 _mapping_set1A={1, {0,0}, {0}, {1}, {1}, {1}}; +static vorbis_info_mode _mode_set0A={0,0,0,0}; +static vorbis_info_mode _mode_set1A={1,0,0,1}; + +/* CD quality stereo, no channel coupling */ +codec_setup_info info_A={ + + /* smallblock, largeblock */ + {256, 2048}, + /* modes,maps,times,floors,residues,books,psys */ + 2, 2, 1, 2, 2, 18, 2, + /* modes */ + {&_mode_set0A,&_mode_set1A}, + /* maps */ + {0,0},{&_mapping_set0A,&_mapping_set1A}, + /* times */ + {0,0},{&_time_set0A}, + /* floors */ + {0,0},{&_floor_set0A,&_floor_set1A}, + /* residue */ + {0,0},{&_residue_set0A,&_residue_set1A}, + /* books */ + {&_vq_book_lsp12_0, /* 0 */ + &_vq_book_lsp30_0, /* 1 */ + + &_huff_book_res0_128_128aux, + &_huff_book_res0_128_1024aux, + + &_vq_book_res0_128_128_1, + &_vq_book_res0_128_128_2, + &_vq_book_res0_128_128_3, + &_vq_book_res0_128_128_4, + &_vq_book_res0_128_128_5, + + &_vq_book_res0_128_1024_1, + &_vq_book_res0_128_1024_2, + &_vq_book_res0_128_1024_3, + &_vq_book_res0_128_1024_4, + &_vq_book_res0_128_1024_5, + &_vq_book_res0_128_1024_6, + &_vq_book_res0_128_1024_7, + &_vq_book_res0_128_1024_8, + &_vq_book_res0_128_1024_9, + + }, + /* psy */ + {&_psy_set_A0,&_psy_set_A}, + /* thresh sample period, preecho clamp trigger threshhold, range, minenergy */ + 256, 32.f, -32.f, -96.f +}; + +#define PREDEF_INFO_MAX 0 + +#endif diff --git a/lib/modes/mode_AA.h b/lib/modes/mode_AA.h new file mode 100644 index 00000000..6fa684b5 --- /dev/null +++ b/lib/modes/mode_AA.h @@ -0,0 +1,292 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: predefined encoding modes + last mod: $Id: mode_AA.h,v 1.3.2.1 2000/12/27 23:46:38 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_MODES_AA_H_ +#define _V_MODES_AA_H_ + +#include <stdio.h> +#include "vorbis/codec.h" +#include "backends.h" + +#include "books/lsp12_0.vqh" +#include "books/lsp30_0.vqh" + +#include "books/res0_96_128aux.vqh" + +#include "books/res0_96_128_1.vqh" +#include "books/res0_96_128_2.vqh" +#include "books/res0_96_128_3.vqh" +#include "books/res0_96_128_4.vqh" +#include "books/res0_96_128_5.vqh" + +#include "books/res0_96_1024aux.vqh" + +#include "books/res0_96_1024_1.vqh" +#include "books/res0_96_1024_2.vqh" +#include "books/res0_96_1024_3.vqh" +#include "books/res0_96_1024_4.vqh" +#include "books/res0_96_1024_5.vqh" +#include "books/res0_96_1024_6.vqh" +#include "books/res0_96_1024_7.vqh" + +static vorbis_info_psy _psy_set_AA0={ + 1,/*athp*/ + 1,/*decayp*/ + 1,/*smoothp*/ + + -100., + -140., + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 1,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*63*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*88*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*125*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*175*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*250*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*350*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*500*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*700*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*1000*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*1400*/ + {-40.,-40.,-40.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*2000*/ + {-40.,-40.,-40.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*2800*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*4000*/ + {-30.,-30.,-35.,-37.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*5600*/ + {-20.,-25.,-30.,-35.,-35.,-50.,-60.,-70.,-80.,-90.,-100.}, /*8000*/ + {-20.,-25.,-30.,-33.,-35.,-45.,-55.,-65.,-75.,-90.,-100.}, /*11500*/ + {-20.,-24.,-26.,-32.,-35.,-45.,-55.,-65.,-75.,-90.,-100.}, /*16000*/ + }, + + 1,/* peakattp */ + {{-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-22.,-22.,-22.}, /*63*/ + {-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-22.,-22.,-22.}, /*88*/ + {-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-22.,-22.,-22.}, /*125*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*175*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*250*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*350*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*500*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*700*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*1000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*1400*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*2000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*2800*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*4000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*5600*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-16.,-17.}, /*8000*/ + { -6., -7., -9., -9., -9., -9.,-10.,-11.,-12.,-13.,-14.}, /*11500*/ + { -6., -6., -9., -9., -9., -9., -9., -9.,-10.,-11.,-12.}, /*16000*/ + }, + + 1,/*noisemaskp */ + .5, /* low window */ + .5, /* high window */ + 15, + 15, + {.000, /*63*/ + .000, /*88*/ + .000, /*125*/ + .000, /*175*/ + .000, /*250*/ + .000, /*350*/ + .000, /*500*/ + .500, /*700*/ + .500, /*1000*/ + .500, /*1400*/ + .500, /*2000*/ + .500, /*2800*/ + .500, /*4000*/ + .500, /*5600*/ + .650, /*8000*/ + .650, /*11500*/ + .600, /*16000*/ + }, + + 95., + + -0., -.004 /* attack/decay control */ +}; + +static vorbis_info_psy _psy_set_AA={ + 1,/*athp*/ + 1,/*decayp*/ + 1,/*smoothp*/ + + -100.f, + -140.f, + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 1,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*63*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*88*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*125*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*175*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*250*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*350*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*500*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*700*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1000*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1400*/ + {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2000*/ + {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2800*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*4000*/ + {-30.f,-30.f,-35.f,-37.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*5600*/ + {-20.f,-25.f,-30.f,-35.f,-35.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*8000*/ + {-20.f,-25.f,-30.f,-33.f,-35.f,-45.f,-55.f,-65.f,-75.f,-90.f,-100.f}, /*11500*/ + {-20.f,-24.f,-26.f,-32.f,-35.f,-45.f,-55.f,-65.f,-75.f,-90.f,-100.f}, /*16000*/ + }, + + 1,/* peakattp */ + {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*63*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*88*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*125*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*175*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*250*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*350*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*500*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*700*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*1000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*1400*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*2000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*2800*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*4000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*5600*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-16.f,-17.f}, /*8000*/ + { -6.f, -7.f, -9.f, -9.f, -9.f, -9.f,-10.f,-11.f,-12.f,-13.f,-14.f}, /*11500*/ + { -6.f, -6.f, -9.f, -9.f, -9.f, -9.f, -9.f, -9.f,-10.f,-11.f,-12.f}, /*16000*/ + }, + + 1,/*noisemaskp */ + .5, /* low window */ + .5, /* high window */ + 25, + 25, + {.000, /*63*/ + .000, /*88*/ + .000, /*125*/ + .000, /*175*/ + .000, /*250*/ + .000, /*350*/ + .000, /*500*/ + .500, /*700*/ + .500, /*1000*/ + .500, /*1400*/ + .500, /*2000*/ + .500, /*2800*/ + .700, /*4000*/ + .800, /*5600*/ + .850, /*8000*/ + .850, /*11500*/ + .900, /*16000*/ + }, + + 95.f, + + -0.f, -.004f /* attack/decay control */ +}; + + +/* with GNUisms, this could be short and readable. Oh well */ +static vorbis_info_time0 _time_set0AA={0}; +static vorbis_info_floor0 _floor_set0AA={12, 44100, 64, 12,150, 1, {0} }; +static vorbis_info_floor0 _floor_set1AA={30, 44100, 256, 12,150, 1, {1} }; +static vorbis_info_residue0 _residue_set0AA={0,128, 32,6,2, + {0,1,1,1,1,1}, + {4,5,6,7,8}, + + {0,99999,9999,9999,9999}, + {99.f,1.5f,2.5f,6.5f,12.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + + +static vorbis_info_residue0 _residue_set1AA={0,1024, 32,8,3, + {0,1,1,1,1,1,1,1}, + {9,10,11,12,13,14,15}, + + {0,9,9999,21,9999, + 9999,9999,9999}, + {99.f,2.f,2.f,4.f,4.f,9.5f,15.5f}, + {5,5,5,5,5,5,5}, + {99,99,99,99,99,99,99}}; + +static vorbis_info_mapping0 _mapping_set0AA={1, {0,0}, {0}, {0}, {0}, {0}}; +static vorbis_info_mapping0 _mapping_set1AA={1, {0,0}, {0}, {1}, {1}, {1}}; +static vorbis_info_mode _mode_set0AA={0,0,0,0}; +static vorbis_info_mode _mode_set1AA={1,0,0,1}; + +/* CD quality stereo, no channel coupling */ +codec_setup_info info_AA={ + + /* smallblock, largeblock */ + {256, 2048}, + /* modes,maps,times,floors,residues,books,psys */ + 2, 2, 1, 2, 2, 16, 2, + /* modes */ + {&_mode_set0AA,&_mode_set1AA}, + /* maps */ + {0,0},{&_mapping_set0AA,&_mapping_set1AA}, + /* times */ + {0,0},{&_time_set0AA}, + /* floors */ + {0,0},{&_floor_set0AA,&_floor_set1AA}, + /* residue */ + {0,0},{&_residue_set0AA,&_residue_set1AA}, + /* books */ + {&_vq_book_lsp12_0, /* 0 */ + &_vq_book_lsp30_0, /* 1 */ + + &_huff_book_res0_96_128aux, + &_huff_book_res0_96_1024aux, + + &_vq_book_res0_96_128_1, + &_vq_book_res0_96_128_2, + &_vq_book_res0_96_128_3, + &_vq_book_res0_96_128_4, + &_vq_book_res0_96_128_5, + + &_vq_book_res0_96_1024_1, + &_vq_book_res0_96_1024_2, + &_vq_book_res0_96_1024_3, + &_vq_book_res0_96_1024_4, + &_vq_book_res0_96_1024_5, + &_vq_book_res0_96_1024_6, + &_vq_book_res0_96_1024_7, + + }, + /* psy */ + {&_psy_set_AA0,&_psy_set_AA}, + /* thresh sample period, preecho clamp trigger threshhold, range, minenergy */ + 256, 32.f, 6.f, -96.f +}; + +#define PREDEF_INFO_MAX 0 + +#endif diff --git a/lib/modes/mode_B.h b/lib/modes/mode_B.h new file mode 100644 index 00000000..ad3025b3 --- /dev/null +++ b/lib/modes/mode_B.h @@ -0,0 +1,210 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: predefined encoding modes + last mod: $Id: mode_B.h,v 1.6.2.1 2000/12/27 23:46:38 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_MODES_B_H_ +#define _V_MODES_B_H_ + +#include <stdio.h> +#include "vorbis/codec.h" +#include "backends.h" + +#include "books/lsp12_0.vqh" +#include "books/lsp30_0.vqh" + +#include "books/res0_160_128aux.vqh" +#include "books/res0_160_1024aux.vqh" + +#include "books/res0_160_128_1.vqh" +#include "books/res0_160_128_2.vqh" +#include "books/res0_160_128_3.vqh" +#include "books/res0_160_128_4.vqh" +#include "books/res0_160_128_5.vqh" + +#include "books/res0_160_1024_1.vqh" +#include "books/res0_160_1024_2.vqh" +#include "books/res0_160_1024_3.vqh" +#include "books/res0_160_1024_4.vqh" +#include "books/res0_160_1024_5.vqh" +#include "books/res0_160_1024_6.vqh" +#include "books/res0_160_1024_7.vqh" +#include "books/res0_160_1024_8.vqh" +#include "books/res0_160_1024_9.vqh" + +static vorbis_info_psy _psy_set_B={ + 1,/*athp*/ + 1,/*decayp*/ + 1,/*smoothp*/ + + -100.f, + -140.f, + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 1,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*63*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*88*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*125*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*175*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*250*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*350*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*500*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*700*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1000*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1400*/ + {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2000*/ + {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2800*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*4000*/ + {-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*5600*/ + {-30.f,-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*8000*/ + {-30.f,-30.f,-35.f,-33.f,-35.f,-45.f,-55.f,-65.f,-75.f,-90.f,-100.f}, /*11500*/ + {-30.f,-28.f,-30.f,-32.f,-35.f,-45.f,-55.f,-65.f,-75.f,-90.f,-100.f}, /*16000*/ + }, + + 1,/* peakattp */ + {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*63*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*88*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*125*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-28.f,-28.f,-28.f}, /*175*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-28.f,-28.f,-28.f}, /*250*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-28.f,-28.f,-28.f}, /*350*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-28.f,-28.f,-28.f}, /*500*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*700*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*1000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*1400*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*2000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*2800*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*4000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*5600*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-16.f,-17.f}, /*8000*/ + { -6.f, -7.f, -9.f, -9.f, -9.f, -9.f,-10.f,-11.f,-12.f,-13.f,-14.f}, /*11500*/ + { -6.f, -6.f, -9.f, -9.f, -9.f, -9.f, -9.f, -9.f,-10.f,-11.f,-12.f}, /*16000*/ + }, + + 1,/*noisemaskp */ + .5, /* low window */ + .5, /* high window */ + 25, + 25, + {.000, /*63*/ + .000, /*88*/ + .000, /*125*/ + .000, /*175*/ + .000, /*250*/ + .000, /*350*/ + .000, /*500*/ + .500, /*700*/ + .500, /*1000*/ + .500, /*1400*/ + .500, /*2000*/ + .500, /*2800*/ + .700, /*4000*/ + .800, /*5600*/ + .850, /*8000*/ + .850, /*11500*/ + .900, /*16000*/ + }, + + 110.f, + + -3.f, -.004f /* attack/decay control */ +}; + +/* with GNUisms, this could be short and readable. Oh well */ +static vorbis_info_time0 _time_set0B={0}; +static vorbis_info_floor0 _floor_set0B={12, 44100, 64, 12,150, 1, {0} }; +static vorbis_info_floor0 _floor_set1B={30, 44100, 256, 12,150, 1, {1} }; +static vorbis_info_residue0 _residue_set0B={0,128, 32,6,2, + {0,1,1,1,1,1}, + {4,5,6,7,8}, + + {0,99999,9999,9999,9999}, + {99.f,1.5f,2.5f,6.5f,12.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + +static vorbis_info_residue0 _residue_set1B={0,1024, 32,10,3, + {0,1,1,1,1,1,1,1,1,1}, + {9,10,11,12,13,14,15,16,17}, + + {0,8,9999,17,9999, + 22,9999,9999,9999}, + {99.f,1.5f,1.5f,2.5f,2.5f, + 4.f,4.f,6.5f,12.5f}, + {5,5,5,5,5,5,5,5,5}, + {99,99,99,99,99,99,99,99,99}}; + +static vorbis_info_mapping0 _mapping_set0B={1, {0,0}, {0}, {0}, {0}, {0}}; +static vorbis_info_mapping0 _mapping_set1B={1, {0,0}, {0}, {1}, {1}, {0}}; +static vorbis_info_mode _mode_set0B={0,0,0,0}; +static vorbis_info_mode _mode_set1B={1,0,0,1}; + +/* CD quality stereo, no channel coupling */ +codec_setup_info info_B={ + + /* smallblock, largeblock */ + {256, 2048}, + /* modes,maps,times,floors,residues,books,psys */ + 2, 2, 1, 2, 2, 18, 1, + /* modes */ + {&_mode_set0B,&_mode_set1B}, + /* maps */ + {0,0},{&_mapping_set0B,&_mapping_set1B}, + /* times */ + {0,0},{&_time_set0B}, + /* floors */ + {0,0},{&_floor_set0B,&_floor_set1B}, + /* residue */ + {0,0},{&_residue_set0B,&_residue_set1B}, + /* books */ + {&_vq_book_lsp12_0, /* 0 */ + &_vq_book_lsp30_0, /* 1 */ + + &_huff_book_res0_160_128aux, + &_huff_book_res0_160_1024aux, + + &_vq_book_res0_160_128_1, + &_vq_book_res0_160_128_2, + &_vq_book_res0_160_128_3, + &_vq_book_res0_160_128_4, + &_vq_book_res0_160_128_5, + + &_vq_book_res0_160_1024_1, + &_vq_book_res0_160_1024_2, + &_vq_book_res0_160_1024_3, + &_vq_book_res0_160_1024_4, + &_vq_book_res0_160_1024_5, + &_vq_book_res0_160_1024_6, + &_vq_book_res0_160_1024_7, + &_vq_book_res0_160_1024_8, + &_vq_book_res0_160_1024_9, + + }, + /* psy */ + {&_psy_set_B}, + /* thresh sample period, preecho clamp trigger threshhold, range, minenergy */ + 256, 32.f, 6.f, -96.f +}; + +#define PREDEF_INFO_MAX 0 + +#endif diff --git a/lib/modes/mode_C.h b/lib/modes/mode_C.h new file mode 100644 index 00000000..97307d20 --- /dev/null +++ b/lib/modes/mode_C.h @@ -0,0 +1,283 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: predefined encoding modes + last mod: $Id: mode_C.h,v 1.6.2.1 2000/12/27 23:46:38 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_MODES_C_H_ +#define _V_MODES_C_H_ + +#include <stdio.h> +#include "vorbis/codec.h" +#include "backends.h" + +#include "books/lsp12_0.vqh" +#include "books/lsp30_0.vqh" + +#include "books/res0_192_128aux.vqh" +#include "books/res0_192_1024aux.vqh" + +#include "books/res0_192_128_1.vqh" +#include "books/res0_192_128_2.vqh" +#include "books/res0_192_128_3.vqh" +#include "books/res0_192_128_4.vqh" +#include "books/res0_192_128_5.vqh" + +#include "books/res0_192_1024_1.vqh" +#include "books/res0_192_1024_2.vqh" +#include "books/res0_192_1024_3.vqh" +#include "books/res0_192_1024_4.vqh" +#include "books/res0_192_1024_5.vqh" + +static vorbis_info_psy _psy_set_C0={ + 1,/*athp*/ + 0,/*decayp*/ + 1,/*smoothp*/ + + -100.f, + -140.f, + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 0,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*63*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*88*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*125*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*175*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*250*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*350*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*500*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*700*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*1000*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*1400*/ + {-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*2000*/ + {-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*2800*/ + {-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*4000*/ + {-30.f,-30.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*5600*/ + {-30.f,-30.f,-35.f,-35.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f,-110.f}, /*8000*/ + {-30.f,-30.f,-35.f,-33.f,-45.f,-55.f,-65.f,-75.f,-85.f,-100.f,-110.f}, /*11500*/ + {-30.f,-28.f,-30.f,-32.f,-45.f,-55.f,-65.f,-75.f,-85.f,-100.f,-110.f}, /*16000*/ + }, + + 1,/* peakattp */ + {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*63*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*88*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*125*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-28.f,-28.f,-28.f}, /*175*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-28.f,-28.f,-28.f}, /*250*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-28.f,-28.f,-28.f}, /*350*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-28.f,-28.f,-28.f}, /*500*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*700*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*1000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*1400*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*2000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*2800*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*4000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*5600*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-16.f,-17.f}, /*8000*/ + { -6.f, -7.f, -9.f, -9.f, -9.f, -9.f,-10.f,-11.f,-12.f,-13.f,-14.f}, /*11500*/ + { -6.f, -6.f, -9.f, -9.f, -9.f, -9.f, -9.f, -9.f,-10.f,-11.f,-12.f}, /*16000*/ + }, + + 1,/*noisemaskp */ + .5, /* low window */ + .5, /* high window */ + 25, + 25, + {.000, /*63*/ + .000, /*88*/ + .000, /*125*/ + .000, /*175*/ + .000, /*250*/ + .000, /*350*/ + .000, /*500*/ + .500, /*700*/ + .500, /*1000*/ + .500, /*1400*/ + .500, /*2000*/ + .500, /*2800*/ + .700, /*4000*/ + .800, /*5600*/ + .850, /*8000*/ + .850, /*11500*/ + .900, /*16000*/ + }, + + 100.f, + + -6.f, -.006f /* attack/decay control */ +}; + +static vorbis_info_psy _psy_set_C1={ + 1,/*athp*/ + 0,/*decayp*/ + 1,/*smoothp*/ + + -100.f, + -140.f, + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 1,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*63*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*88*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*125*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*175*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*250*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*350*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*500*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*700*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1000*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1400*/ + {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2000*/ + {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2800*/ + {-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*4000*/ + {-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*5600*/ + {-30.f,-30.f,-35.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*8000*/ + {-30.f,-30.f,-35.f,-33.f,-35.f,-45.f,-55.f,-65.f,-75.f,-90.f,-100.f}, /*11500*/ + {-30.f,-28.f,-30.f,-32.f,-35.f,-45.f,-55.f,-65.f,-75.f,-90.f,-100.f}, /*16000*/ + }, + + 1,/* peakattp */ + {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-28.f,-28.f}, /*63*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-28.f,-28.f}, /*88*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-28.f,-28.f}, /*125*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-18.f,-18.f,-20.f}, /*175*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-18.f,-18.f,-20.f}, /*250*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-18.f,-18.f,-20.f}, /*350*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-18.f,-18.f,-20.f}, /*500*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*700*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*1000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*1400*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*2000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*2800*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*4000*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-18.f,-20.f}, /*5600*/ + { -7.f, -8.f, -9.f,-10.f,-10.f,-11.f,-12.f,-13.f,-15.f,-16.f,-17.f}, /*8000*/ + { -6.f, -7.f, -9.f, -9.f, -9.f, -9.f,-10.f,-11.f,-12.f,-13.f,-14.f}, /*11500*/ + { -6.f, -6.f, -9.f, -9.f, -9.f, -9.f, -9.f, -9.f,-10.f,-11.f,-12.f}, /*16000*/ + }, + + 1,/*noisemaskp */ + .5, /* low window */ + .5, /* high window */ + 25, + 25, + {.000, /*63*/ + .000, /*88*/ + .000, /*125*/ + .000, /*175*/ + .000, /*250*/ + .000, /*350*/ + .000, /*500*/ + .500, /*700*/ + .500, /*1000*/ + .500, /*1400*/ + .500, /*2000*/ + .500, /*2800*/ + .700, /*4000*/ + .800, /*5600*/ + .850, /*8000*/ + .850, /*11500*/ + .900, /*16000*/ + }, + 110.f, + + -6.f, -.006f /* attack/decay control */ +}; + +/* with GNUisms, this could be short and readable. Oh well */ +static vorbis_info_time0 _time_set0C={0}; +static vorbis_info_floor0 _floor_set0C={12, 44100, 64, 12,150, 1, {0} }; +static vorbis_info_floor0 _floor_set1C={30, 44100, 256, 12,150, 1, {1} }; +static vorbis_info_residue0 _residue_set0C={0,128, 32,6,2, + {0,1,1,1,1,1}, + {4,5,6,7,8}, + + {0,99999,9999,9999,9999}, + {99.f,1.5f,2.5f,6.5f,12.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + +static vorbis_info_residue0 _residue_set1C={0,1024, 32,6,3, + {0,1,1,1,1,1}, + {9,10,11,12,13}, + + {0,99999,9999,9999,9999}, + {99.f,1.5f,2.5f,6.5f,12.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + +static vorbis_info_mapping0 _mapping_set0C={1, {0,0}, {0}, {0}, {0}, {0}}; +static vorbis_info_mapping0 _mapping_set1C={1, {0,0}, {0}, {1}, {1}, {1}}; +static vorbis_info_mode _mode_set0C={0,0,0,0}; +static vorbis_info_mode _mode_set1C={1,0,0,1}; + +/* CD quality stereo, no channel coupling */ +codec_setup_info info_C={ + + /* smallblock, largeblock */ + {256, 2048}, + /* modes,maps,times,floors,residues,books,psys */ + 2, 2, 1, 2, 2, 14, 2, + /* modes */ + {&_mode_set0C,&_mode_set1C}, + /* maps */ + {0,0},{&_mapping_set0C,&_mapping_set1C}, + /* times */ + {0,0},{&_time_set0C}, + /* floors */ + {0,0},{&_floor_set0C,&_floor_set1C}, + /* residue */ + {0,0},{&_residue_set0C,&_residue_set1C}, + /* books */ + {&_vq_book_lsp12_0, /* 0 */ + &_vq_book_lsp30_0, /* 1 */ + + &_huff_book_res0_192_128aux, + &_huff_book_res0_192_1024aux, + + &_vq_book_res0_192_128_1, + &_vq_book_res0_192_128_2, + &_vq_book_res0_192_128_3, + &_vq_book_res0_192_128_4, + &_vq_book_res0_192_128_5, + + &_vq_book_res0_192_1024_1, + &_vq_book_res0_192_1024_2, + &_vq_book_res0_192_1024_3, + &_vq_book_res0_192_1024_4, + &_vq_book_res0_192_1024_5, + + }, + /* psy */ + {&_psy_set_C0,&_psy_set_C1}, + /* thresh sample period, preecho clamp trigger threshhold, range, minenergy */ + 256, 24.f, 6.f, -96.f +}; + +#define PREDEF_INFO_MAX 0 + +#endif diff --git a/lib/modes/mode_D.h b/lib/modes/mode_D.h new file mode 100644 index 00000000..1a7dbf9c --- /dev/null +++ b/lib/modes/mode_D.h @@ -0,0 +1,236 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: predefined encoding modes + last mod: $Id: mode_D.h,v 1.7.2.1 2000/12/27 23:46:38 xiphmont Exp $ + + ********************************************************************/ + +/* this is really a freeform VBR mode. It roughly centers on 256 kbps stereo */ + +#ifndef _V_MODES_D_H_ +#define _V_MODES_D_H_ + +#include <stdio.h> +#include "vorbis/codec.h" +#include "backends.h" + +#include "books/lsp12_0.vqh" +#include "books/lsp30_0.vqh" + +#include "books/res0_256_128aux.vqh" +#include "books/res0_256_1024aux.vqh" + +#include "books/res0_256_128_1.vqh" +#include "books/res0_256_128_2.vqh" +#include "books/res0_256_128_3.vqh" +#include "books/res0_256_128_4.vqh" +#include "books/res0_256_128_5.vqh" + +#include "books/res0_256_1024_1.vqh" +#include "books/res0_256_1024_2.vqh" +#include "books/res0_256_1024_3.vqh" +#include "books/res0_256_1024_4.vqh" +#include "books/res0_256_1024_5.vqh" + +static vorbis_info_psy _psy_set_D0 ={ + 1,/*athp*/ + 0,/*decayp*/ + 1,/*smoothp*/ + + -100.f, + -140.f, + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 0,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{0}}, + + 1,/* peakattp */ + {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*63*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*88*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*125*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*175*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*250*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*350*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*500*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*700*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*1000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*1400*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*2000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*2800*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*4000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*5600*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*8000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*11500*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*16000*/ + }, + + 0,/*noisemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + .5, + .5, + 25, + 25, + {0}, + + 110.f, + + -0.f, -.004f /* attack/decay control */ +}; +static vorbis_info_psy _psy_set_D1 ={ + 1,/*athp*/ + 0,/*decayp*/ + 1,/*smoothp*/ + + -100.f, + -140.f, + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 1,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*63*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*88*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*125*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*175*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*250*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*350*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*500*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*700*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*1000*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*1400*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*2000*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*2800*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*4000*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*5600*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*8000*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*11500*/ + {-40.f,-40.f,-40.f,-45.f,-45.f,-55.f,-65.f,-75.f,-85.f,-95.f,-105.f}, /*16000*/ + }, + + 1,/* peakattp */ + {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*63*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*88*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*125*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*175*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*250*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*350*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-28.f}, /*500*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*700*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*1000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*1400*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*2000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*2800*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*4000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*5600*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*8000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*11500*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-22.f,-22.f}, /*16000*/ + }, + + 0,/*noisemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + .5, + .5, + 25, + 25, + {0}, + + 110.f, + + -0.f, -.004f /* attack/decay control */ +}; + +/* with GNUisms, this could be short and readable. Oh well */ +static vorbis_info_time0 _time_set0_256={0}; +static vorbis_info_floor0 _floor_set0_256={12, 44100, 64, 12,150, 1, {0} }; +static vorbis_info_floor0 _floor_set1_256={30, 44100, 256, 12,150, 1, {1} }; +static vorbis_info_residue0 _residue_set0_256={0,128, 32,6,2, + {0,1,1,1,1,1}, + {4,5,6,7,8}, + + {0,9999,9999,9999,9999}, + {99.f,2.5f,6.5f,15.5f,29.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + +static vorbis_info_residue0 _residue_set1_256={0,1024, 32,6,3, + {0,1,1,1,1,1}, + {9,10,11,12,13}, + + {0,9999,9999,9999,9999}, + {99.f,2.5f,6.5f,15.5f,29.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + +static vorbis_info_mapping0 _mapping_set0_256={1, {0,0}, {0}, {0}, {0}, {0}}; +static vorbis_info_mapping0 _mapping_set1_256={1, {0,0}, {0}, {1}, {1}, {1}}; +static vorbis_info_mode _mode_set0_256={0,0,0,0}; +static vorbis_info_mode _mode_set1_256={1,0,0,1}; + +/* CD quality stereo, no channel coupling */ +codec_setup_info info_D={ + + /* smallblock, largeblock */ + {256, 2048}, + /* modes,maps,times,floors,residues,books,psys */ + 2, 2, 1, 2, 2, 14, 2, + /* modes */ + {&_mode_set0_256,&_mode_set1_256}, + /* maps */ + {0,0},{&_mapping_set0_256,&_mapping_set1_256}, + /* times */ + {0,0},{&_time_set0_256}, + /* floors */ + {0,0},{&_floor_set0_256,&_floor_set1_256}, + /* residue */ + {0,0},{&_residue_set0_256,&_residue_set1_256}, + /* books */ + {&_vq_book_lsp12_0, /* 0 */ + &_vq_book_lsp30_0, /* 1 */ + + &_huff_book_res0_256_128aux, + &_huff_book_res0_256_1024aux, + + &_vq_book_res0_256_128_1, + &_vq_book_res0_256_128_2, + &_vq_book_res0_256_128_3, + &_vq_book_res0_256_128_4, + &_vq_book_res0_256_128_5, + + &_vq_book_res0_256_1024_1, + &_vq_book_res0_256_1024_2, + &_vq_book_res0_256_1024_3, + &_vq_book_res0_256_1024_4, + &_vq_book_res0_256_1024_5, + + }, + /* psy */ + {&_psy_set_D0,&_psy_set_D1}, + /* thresh sample period, preecho clamp trigger threshhold, range, minenergy */ + 256, 24.f, 6.f, -96.f +}; + +#define PREDEF_INFO_MAX 0 + +#endif diff --git a/lib/modes/mode_E.h b/lib/modes/mode_E.h new file mode 100644 index 00000000..fab0a275 --- /dev/null +++ b/lib/modes/mode_E.h @@ -0,0 +1,169 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: predefined encoding modes + last mod: $Id: mode_E.h,v 1.4.2.1 2000/12/27 23:46:38 xiphmont Exp $ + + ********************************************************************/ + +/* this is really a freeform VBR mode. It roughly centers on 350 kbps stereo */ + +#ifndef _V_MODES_E_H_ +#define _V_MODES_E_H_ + +#include <stdio.h> +#include "vorbis/codec.h" +#include "backends.h" + +#include "books/lsp12_0.vqh" +#include "books/lsp30_0.vqh" + +#include "books/res0_350_128aux.vqh" +#include "books/res0_350_1024aux.vqh" + +#include "books/res0_350_128_1.vqh" +#include "books/res0_350_128_2.vqh" +#include "books/res0_350_128_3.vqh" +#include "books/res0_350_128_4.vqh" +#include "books/res0_350_128_5.vqh" + +#include "books/res0_350_1024_1.vqh" +#include "books/res0_350_1024_2.vqh" +#include "books/res0_350_1024_3.vqh" +#include "books/res0_350_1024_4.vqh" +#include "books/res0_350_1024_5.vqh" + +static vorbis_info_psy _psy_set_E ={ + 1,/*athp*/ + 0,/*decayp*/ + 1,/*smoothp*/ + + -140.f, + -180.f, + + 16, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 0,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{0}}, + + 1,/* peakattp */ + {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-30.f}, /*63*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-30.f}, /*88*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-30.f}, /*125*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-30.f}, /*175*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-30.f}, /*250*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-30.f}, /*350*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-28.f,-28.f,-30.f}, /*500*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*700*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*1000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*1400*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*2000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*2800*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*4000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*5600*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*8000*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*11500*/ + {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-22.f,-24.f,-28.f}, /*16000*/ + }, + + 0,/*noisemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + .5, + .5, + 25, + 25, + {0}, + + 110.f, + + -0.f, -.004f /* attack/decay control */ +}; + +/* with GNUisms, this could be short and readable. Oh well */ +static vorbis_info_time0 _time_set0_E={0}; +static vorbis_info_floor0 _floor_set0_E={12, 44100, 64, 12,150, 1, {0} }; +static vorbis_info_floor0 _floor_set1_E={30, 44100, 256, 12,150, 1, {1} }; +static vorbis_info_residue0 _residue_set0_E={0,128, 32,6,2, + {0,1,1,1,1,1}, + {4,5,6,7,8}, + + {0,9999,9999,9999,9999}, + {99.f,2.5f,6.5f,15.5f,29.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + +static vorbis_info_residue0 _residue_set1_E={0,1024, 32,6,3, + {0,1,1,1,1,1}, + {9,10,11,12,13}, + + {0,9999,9999,9999,9999}, + {99.f,2.5f,6.5f,15.5f,29.5f}, + {5,5,5,5,5}, + {99,99,99,99,99}}; + +static vorbis_info_mapping0 _mapping_set0_E={1, {0,0}, {0}, {0}, {0}, {0}}; +static vorbis_info_mapping0 _mapping_set1_E={1, {0,0}, {0}, {1}, {1}, {0}}; +static vorbis_info_mode _mode_set0_E={0,0,0,0}; +static vorbis_info_mode _mode_set1_E={1,0,0,1}; + +/* CD quality stereo, no channel coupling */ +codec_setup_info info_E={ + + /* smallblock, largeblock */ + {256, 2048}, + /* modes,maps,times,floors,residues,books,psys */ + 2, 2, 1, 2, 2, 14, 1, + /* modes */ + {&_mode_set0_E,&_mode_set1_E}, + /* maps */ + {0,0},{&_mapping_set0_E,&_mapping_set1_E}, + /* times */ + {0,0},{&_time_set0_E}, + /* floors */ + {0,0},{&_floor_set0_E,&_floor_set1_E}, + /* residue */ + {0,0},{&_residue_set0_E,&_residue_set1_E}, + /* books */ + {&_vq_book_lsp12_0, /* 0 */ + &_vq_book_lsp30_0, /* 1 */ + + &_huff_book_res0_350_128aux, + &_huff_book_res0_350_1024aux, + + &_vq_book_res0_350_128_1, + &_vq_book_res0_350_128_2, + &_vq_book_res0_350_128_3, + &_vq_book_res0_350_128_4, + &_vq_book_res0_350_128_5, + + &_vq_book_res0_350_1024_1, + &_vq_book_res0_350_1024_2, + &_vq_book_res0_350_1024_3, + &_vq_book_res0_350_1024_4, + &_vq_book_res0_350_1024_5, + + }, + /* psy */ + {&_psy_set_E}, + /* thresh sample period, preecho clamp trigger threshhold, range, minenergy */ + 256, 24.f, 6.f, -96.f +}; + +#define PREDEF_INFO_MAX 0 + +#endif diff --git a/lib/psy.c b/lib/psy.c new file mode 100644 index 00000000..dff9fb9c --- /dev/null +++ b/lib/psy.c @@ -0,0 +1,654 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: psychoacoustics not including preecho + last mod: $Id: psy.c,v 1.34.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + ********************************************************************/ + +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "vorbis/codec.h" + +#include "masking.h" +#include "psy.h" +#include "os.h" +#include "lpc.h" +#include "smallft.h" +#include "scales.h" +#include "misc.h" + +#define NEGINF -9999.f + +/* Why Bark scale for encoding but not masking computation? Because + masking has a strong harmonic dependancy */ + +/* the beginnings of real psychoacoustic infrastructure. This is + still not tightly tuned */ +void _vi_psy_free(vorbis_info_psy *i){ + if(i){ + memset(i,0,sizeof(vorbis_info_psy)); + _ogg_free(i); + } +} + +vorbis_info_psy *_vi_psy_copy(vorbis_info_psy *i){ + vorbis_info_psy *ret=_ogg_malloc(sizeof(vorbis_info_psy)); + memcpy(ret,i,sizeof(vorbis_info_psy)); + return(ret); +} + +/* Set up decibel threshold slopes on a Bark frequency scale */ +/* ATH is the only bit left on a Bark scale. No reason to change it + right now */ +static void set_curve(float *ref,float *c,int n, float crate){ + int i,j=0; + + for(i=0;i<MAX_BARK-1;i++){ + int endpos=rint(fromBARK(i+1)*2*n/crate); + float base=ref[i]; + if(j<endpos){ + float delta=(ref[i+1]-base)/(endpos-j); + for(;j<endpos && j<n;j++){ + c[j]=base; + base+=delta; + } + } + } +} + +static void min_curve(float *c, + float *c2){ + int i; + for(i=0;i<EHMER_MAX;i++)if(c2[i]<c[i])c[i]=c2[i]; +} +static void max_curve(float *c, + float *c2){ + int i; + for(i=0;i<EHMER_MAX;i++)if(c2[i]>c[i])c[i]=c2[i]; +} + +static void attenuate_curve(float *c,float att){ + int i; + for(i=0;i<EHMER_MAX;i++) + c[i]+=att; +} + +static void interp_curve(float *c,float *c1,float *c2,float del){ + int i; + for(i=0;i<EHMER_MAX;i++) + c[i]=c2[i]*del+c1[i]*(1.f-del); +} + +static void setup_curve(float **c, + int band, + float *curveatt_dB){ + int i,j; + float ath[EHMER_MAX]; + float tempc[P_LEVELS][EHMER_MAX]; + + memcpy(c[0]+2,c[4]+2,sizeof(float)*EHMER_MAX); + memcpy(c[2]+2,c[4]+2,sizeof(float)*EHMER_MAX); + + /* we add back in the ATH to avoid low level curves falling off to + -infinity and unneccessarily cutting off high level curves in the + curve limiting (last step). But again, remember... a half-band's + settings must be valid over the whole band, and it's better to + mask too little than too much, so be pessimal. */ + + for(i=0;i<EHMER_MAX;i++){ + float oc_min=band*.5+(i-EHMER_OFFSET)*.125; + float oc_max=band*.5+(i-EHMER_OFFSET+1)*.125; + float bark=toBARK(fromOC(oc_min)); + int ibark=floor(bark); + float del=bark-ibark; + float ath_min,ath_max; + + if(ibark<26) + ath_min=ATH_Bark_dB[ibark]*(1.f-del)+ATH_Bark_dB[ibark+1]*del; + else + ath_min=ATH_Bark_dB[25]; + + bark=toBARK(fromOC(oc_max)); + ibark=floor(bark); + del=bark-ibark; + + if(ibark<26) + ath_max=ATH_Bark_dB[ibark]*(1.f-del)+ATH_Bark_dB[ibark+1]*del; + else + ath_max=ATH_Bark_dB[25]; + + ath[i]=min(ath_min,ath_max); + } + + /* The c array is comes in as dB curves at 20 40 60 80 100 dB. + interpolate intermediate dB curves */ + for(i=1;i<P_LEVELS;i+=2){ + interp_curve(c[i]+2,c[i-1]+2,c[i+1]+2,.5); + } + + /* normalize curves so the driving amplitude is 0dB */ + /* make temp curves with the ATH overlayed */ + for(i=0;i<P_LEVELS;i++){ + attenuate_curve(c[i]+2,curveatt_dB[i]); + memcpy(tempc[i],ath,EHMER_MAX*sizeof(float)); + attenuate_curve(tempc[i],-i*10.f); + max_curve(tempc[i],c[i]+2); + } + + /* Now limit the louder curves. + + the idea is this: We don't know what the playback attenuation + will be; 0dB SL moves every time the user twiddles the volume + knob. So that means we have to use a single 'most pessimal' curve + for all masking amplitudes, right? Wrong. The *loudest* sound + can be in (we assume) a range of ...+100dB] SL. However, sounds + 20dB down will be in a range ...+80], 40dB down is from ...+60], + etc... */ + + for(j=1;j<P_LEVELS;j++){ + min_curve(tempc[j],tempc[j-1]); + min_curve(c[j]+2,tempc[j]); + } + + /* add fenceposts */ + for(j=0;j<P_LEVELS;j++){ + + for(i=0;i<EHMER_MAX;i++) + if(c[j][i+2]>-200.f){ + c[j][0]=i; + break; + } + + for(i=EHMER_MAX-1;i>=0;i--) + if(c[j][i+2]>-200.f){ + c[j][1]=i; + break; + } + + } +} + +void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,int n,long rate){ + long i,j; + long maxoc; + memset(p,0,sizeof(vorbis_look_psy)); + + + p->eighth_octave_lines=vi->eighth_octave_lines; + p->shiftoc=rint(log(vi->eighth_octave_lines*8)/log(2))-1; + + p->firstoc=toOC(.25f*rate/n)*(1<<(p->shiftoc+1))-vi->eighth_octave_lines; + maxoc=toOC((n*.5f-.25f)*rate/n)*(1<<(p->shiftoc+1))+.5f; + p->total_octave_lines=maxoc-p->firstoc+1; + + p->ath=_ogg_malloc(n*sizeof(float)); + p->octave=_ogg_malloc(n*sizeof(int)); + p->bark=_ogg_malloc(n*sizeof(float)); + p->vi=vi; + p->n=n; + + /* set up the lookups for a given blocksize and sample rate */ + /* Vorbis max sample rate is currently limited by 26 Bark (54kHz) */ + set_curve(ATH_Bark_dB, p->ath,n,rate); + for(i=0;i<n;i++) + p->bark[i]=toBARK(rate/(2*n)*i); + + for(i=0;i<n;i++) + p->octave[i]=toOC((i*.5f+.25f)*rate/n)*(1<<(p->shiftoc+1))+.5f; + + p->tonecurves=_ogg_malloc(P_BANDS*sizeof(float **)); + p->noisemedian=_ogg_malloc(n*sizeof(float *)); + p->peakatt=_ogg_malloc(P_BANDS*sizeof(float *)); + for(i=0;i<P_BANDS;i++){ + p->tonecurves[i]=_ogg_malloc(P_LEVELS*sizeof(float *)); + p->peakatt[i]=_ogg_malloc(P_LEVELS*sizeof(float)); + } + + for(i=0;i<P_BANDS;i++) + for(j=0;j<P_LEVELS;j++){ + p->tonecurves[i][j]=_ogg_malloc((EHMER_MAX+2)*sizeof(float)); + } + + /* OK, yeah, this was a silly way to do it */ + memcpy(p->tonecurves[0][4]+2,tone_125_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[0][6]+2,tone_125_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[0][8]+2,tone_125_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[0][10]+2,tone_125_100dB_SL,sizeof(float)*EHMER_MAX); + + memcpy(p->tonecurves[2][4]+2,tone_125_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[2][6]+2,tone_125_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[2][8]+2,tone_125_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[2][10]+2,tone_125_100dB_SL,sizeof(float)*EHMER_MAX); + + memcpy(p->tonecurves[4][4]+2,tone_250_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[4][6]+2,tone_250_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[4][8]+2,tone_250_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[4][10]+2,tone_250_100dB_SL,sizeof(float)*EHMER_MAX); + + memcpy(p->tonecurves[6][4]+2,tone_500_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[6][6]+2,tone_500_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[6][8]+2,tone_500_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[6][10]+2,tone_500_100dB_SL,sizeof(float)*EHMER_MAX); + + memcpy(p->tonecurves[8][4]+2,tone_1000_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[8][6]+2,tone_1000_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[8][8]+2,tone_1000_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[8][10]+2,tone_1000_100dB_SL,sizeof(float)*EHMER_MAX); + + memcpy(p->tonecurves[10][4]+2,tone_2000_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[10][6]+2,tone_2000_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[10][8]+2,tone_2000_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[10][10]+2,tone_2000_100dB_SL,sizeof(float)*EHMER_MAX); + + memcpy(p->tonecurves[12][4]+2,tone_4000_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[12][6]+2,tone_4000_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[12][8]+2,tone_4000_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[12][10]+2,tone_4000_100dB_SL,sizeof(float)*EHMER_MAX); + + memcpy(p->tonecurves[14][4]+2,tone_8000_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[14][6]+2,tone_8000_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[14][8]+2,tone_8000_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[14][10]+2,tone_8000_100dB_SL,sizeof(float)*EHMER_MAX); + + memcpy(p->tonecurves[16][4]+2,tone_8000_40dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[16][6]+2,tone_8000_60dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[16][8]+2,tone_8000_80dB_SL,sizeof(float)*EHMER_MAX); + memcpy(p->tonecurves[16][10]+2,tone_8000_100dB_SL,sizeof(float)*EHMER_MAX); + + /* interpolate curves between */ + for(i=1;i<P_BANDS;i+=2) + for(j=4;j<P_LEVELS;j+=2){ + memcpy(p->tonecurves[i][j]+2,p->tonecurves[i-1][j]+2,EHMER_MAX*sizeof(float)); + /*interp_curve(p->tonecurves[i][j], + p->tonecurves[i-1][j], + p->tonecurves[i+1][j],.5);*/ + min_curve(p->tonecurves[i][j]+2,p->tonecurves[i+1][j]+2); + } + + /* set up the final curves */ + for(i=0;i<P_BANDS;i++) + setup_curve(p->tonecurves[i],i,vi->toneatt[i]); + + /* set up attenuation levels */ + for(i=0;i<P_BANDS;i++) + for(j=0;j<P_LEVELS;j++){ + p->peakatt[i][j]=p->vi->peakatt[i][j]; + } + + /* set up rolling noise median */ + for(i=0;i<n;i++){ + float halfoc=toOC((i+.5)*rate/(2.*n))*2.+2.; + int inthalfoc; + float del; + + if(halfoc<0)halfoc=0; + if(halfoc>=P_BANDS-1)halfoc=P_BANDS-1; + inthalfoc=(int)halfoc; + del=halfoc-inthalfoc; + + p->noisemedian[i]= + p->vi->noisemedian[inthalfoc]*(1.-del) + + p->vi->noisemedian[inthalfoc+1]*del; + } + /*_analysis_output("mediancurve",0,p->noisemedian,n,0,0);*/ +} + +void _vp_psy_clear(vorbis_look_psy *p){ + int i,j; + if(p){ + if(p->ath)_ogg_free(p->ath); + if(p->octave)_ogg_free(p->octave); + if(p->bark)_ogg_free(p->bark); + if(p->tonecurves){ + for(i=0;i<P_BANDS;i++){ + for(j=0;j<P_LEVELS;j++){ + _ogg_free(p->tonecurves[i][j]); + } + _ogg_free(p->tonecurves[i]); + _ogg_free(p->peakatt[i]); + } + _ogg_free(p->tonecurves); + _ogg_free(p->noisemedian); + _ogg_free(p->peakatt); + } + memset(p,0,sizeof(vorbis_look_psy)); + } +} + +/* octave/(8*eighth_octave_lines) x scale and dB y scale */ +static void seed_curve(float *seed, + float **curves, + float amp, + int oc,int n,int linesper,float dBoffset){ + int i; + long seedptr; + float *posts,*curve; + + int choice=(int)((amp+dBoffset)*.1f); + choice=max(choice,0); + choice=min(choice,8); + posts=curves[choice]; + curve=posts+2; + seedptr=oc+(posts[0]-16)*linesper-(linesper>>1); + + for(i=posts[0];i<posts[1];i++){ + if(seedptr>0){ + float lin=amp+curve[i]; + if(seed[seedptr]<lin)seed[seedptr]=lin; + } + seedptr+=linesper; + if(seedptr>=n)break; + } +} + +static void seed_peak(float *seed, + float *att, + float amp, + int oc, + int linesper, + float dBoffset){ + long seedptr; + + int choice=(int)((amp+dBoffset)*.1f); + choice=max(choice,0); + choice=min(choice,P_LEVELS-1); + seedptr=oc-(linesper>>1); + + amp+=att[choice]; + if(seed[seedptr]<amp)seed[seedptr]=amp; + +} + +static void seed_loop(vorbis_look_psy *p, + float ***curves, + float **att, + float *f, + float *flr, + float *seeds, + float specmax){ + vorbis_info_psy *vi=p->vi; + long n=p->n,i; + float dBoffset=vi->max_curve_dB-specmax; + + /* prime the working vector with peak values */ + + for(i=0;i<n;i++){ + float max=f[i]; + int oc=p->octave[i]; + while(i+1<n && p->octave[i+1]==oc){ + i++; + if(f[i]>max)max=f[i]; + } + + if(max>flr[i]){ + oc=oc>>p->shiftoc; + if(oc>=P_BANDS)oc=P_BANDS-1; + if(oc<0)oc=0; + if(vi->tonemaskp) + seed_curve(seeds, + curves[oc], + max, + p->octave[i]-p->firstoc, + p->total_octave_lines, + p->eighth_octave_lines, + dBoffset); + if(vi->peakattp) + seed_peak(seeds, + att[oc], + max, + p->octave[i]-p->firstoc, + p->eighth_octave_lines, + dBoffset); + } + } +} + +/* bleaugh, this is more complicated than it needs to be */ +static void max_seeds(vorbis_look_psy *p,float *seeds,float *flr){ + long n=p->total_octave_lines,i; + int linesper=p->eighth_octave_lines; + long *posstack=alloca(n*sizeof(long)); + float *ampstack=alloca(n*sizeof(float)); + long stack=0; + + for(i=0;i<n;i++){ + if(stack<2){ + posstack[stack]=i; + ampstack[stack++]=seeds[i]; + }else{ + while(1){ + if(seeds[i]<ampstack[stack-1]){ + posstack[stack]=i; + ampstack[stack++]=seeds[i]; + break; + }else{ + if(i<posstack[stack-1]+linesper){ + if(stack>1 && ampstack[stack-1]<=ampstack[stack-2] && + i<posstack[stack-2]+linesper){ + /* we completely overlap, making stack-1 irrelevant. pop it */ + stack--; + continue; + } + } + posstack[stack]=i; + ampstack[stack++]=seeds[i]; + break; + + } + } + } + } + + /* the stack now contains only the positions that are relevant. Scan + 'em straight through */ + { + long pos=0; + long linpos=0; + for(i=0;i<stack;i++){ + long endpos; + if(i<stack-1 && ampstack[i+1]>ampstack[i]){ + endpos=posstack[i+1]; + }else{ + endpos=posstack[i]+linesper+1; /* +1 is important, else bin 0 is + discarded in short frames */ + } + if(endpos>n)endpos=n; + for(;pos<endpos;pos++) + seeds[pos]=ampstack[i]; + } + + pos=0; + while(linpos+1<p->n){ + float min=seeds[pos]; + long end=((p->octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc; + while(pos+1<=end){ + pos++; + if((seeds[pos]>NEGINF && seeds[pos]<min) || min==NEGINF)min=seeds[pos]; + } + + /* seed scale is log. Floor is linear. Map back to it */ + end=pos+p->firstoc; + for(;linpos<p->n && p->octave[linpos]<=end;linpos++) + if(flr[linpos]<min)flr[linpos]=min; + } + { + float v=seeds[p->total_octave_lines-1]; + for(;linpos<p->n;linpos++) + if(flr[linpos]<v)flr[linpos]=v; + } + } + + /* there. Linear time. I now remember this was on a problem set I + had in Grad Skool... I didn't solve it at the time ;-) */ +} + +#define BIN(x) ((int)((x)*-4.)) +#define BINdB(x) ((x)*-.25) +static void bark_noise_median(long n,float *b,float *f,float *noise, + float lowidth,float hiwidth, + int lomin,int himin, + float *thresh){ + long i=0,lo=0,hi=0; + long *radix=alloca(200*4*sizeof(long)); /* quarter-dB bins */ + + long countabove=0; + long median=200*4-1; + long countbelow=0; + + memset(radix,0,200*4*sizeof(long)); + + for(i=0;i<n;i++){ + /* find new lo/hi */ + for(;hi<n && (b[hi]<=b[i]+hiwidth || hi<i+himin);hi++){ + int bin=BIN(f[hi]); + if(bin>=200*4)bin=200*4-1; + radix[bin]++; + if(bin<median) + countabove++; + else + countbelow++; + } + for(;lo<i && b[lo]+lowidth<=b[i] && lo+lomin<i;lo++){ + int bin=BIN(f[lo]); + if(bin>=200*4)bin=200*4-1; + radix[bin]--; + if(bin<median) + countabove--; + else + countbelow--; + } + + /* move the median if needed */ + if(countabove+countbelow){ + + while(thresh[i]>countbelow/(float)(countabove+countbelow) && median>0){ + median--; + countabove-=radix[median]; + countbelow+=radix[median]; + } + + while(thresh[i]<(countbelow-radix[median])/ + (float)(countabove+countbelow) && median+1<200*4){ + countabove+=radix[median]; + countbelow-=radix[median]; + median++; + } + } + + noise[i]=BINdB(median); + } + +} + +void _vp_compute_mask(vorbis_look_psy *p, + float *fft, + float *mdct, + float *flr, + float *decay){ + int i,n=p->n; + float specmax=NEGINF; + static int seq=0; + + float *seed=alloca(sizeof(float)*p->total_octave_lines); + for(i=0;i<p->total_octave_lines;i++)seed[i]=NEGINF; + + /* go to dB scale. Also find the highest peak so we know the limits */ + for(i=0;i<n;i++){ + fft[i]=todB(fft[i]); + if(fft[i]>specmax)specmax=fft[i]; + } + for(i=0;i<n;i++){ + mdct[i]=todB(mdct[i]); + } + + _analysis_output("mdct",seq,mdct,n,0,0); + _analysis_output("fft",seq,fft,n,0,0); + + /* noise masking */ + if(p->vi->noisemaskp){ + bark_noise_median(n,p->bark,mdct,flr, + p->vi->noisewindowlo, + p->vi->noisewindowhi, + p->vi->noisewindowlomin, + p->vi->noisewindowhimin, + p->noisemedian); + /* suppress any noise curve > specmax+p->vi->noisemaxsupp */ + for(i=0;i<n;i++) + if(flr[i]>specmax+p->vi->noisemaxsupp) + flr[i]=specmax+p->vi->noisemaxsupp; + _analysis_output("noise",seq,flr,n,0,0); + }else{ + for(i=0;i<n;i++)flr[i]=NEGINF; + } + + /* set the ATH (floating below specmax by a specified att) */ + if(p->vi->athp){ + float att=specmax+p->vi->ath_adjatt; + if(att<p->vi->ath_maxatt)att=p->vi->ath_maxatt; + + for(i=0;i<n;i++){ + float av=p->ath[i]+att; + if(av>flr[i])flr[i]=av; + } + } + + _analysis_output("ath",seq,flr,n,0,0); + + /* tone/peak masking */ + + /* XXX apply decay to the fft here */ + + seed_loop(p,p->tonecurves,p->peakatt,fft,flr,seed,specmax); + _analysis_output("seed",seq,seed,p->total_octave_lines,0,0); + max_seeds(p,seed,flr); + + /* treat the near-DC offset bin[s] special care */ + { + float v=mdct[0]+p->vi->nearDCdB; + for(i=0;i<p->vi->nearDCp;i++) + if(flr[i]>v)flr[i]=v; + } + + _analysis_output("final",seq,flr,n,0,0); + + /* doing this here is clean, but we need to find a faster way to do + it than to just tack it on */ + + for(i=0;i<n;i++)if(mdct[i]>=flr[i])break; + if(i==n)for(i=0;i<n;i++)flr[i]=NEGINF; + + seq++; +} + + +/* this applies the floor and (optionally) tries to preserve noise + energy in low resolution portions of the spectrum */ +/* f and flr are *linear* scale, not dB */ +void _vp_apply_floor(vorbis_look_psy *p,float *f, float *flr){ + float *work=alloca(p->n*sizeof(float)); + int j; + + /* subtract the floor */ + for(j=0;j<p->n;j++){ + if(flr[j]<=0) + work[j]=0.f; + else + work[j]=f[j]/flr[j]; + } + + memcpy(f,work,p->n*sizeof(float)); +} + + diff --git a/lib/psy.h b/lib/psy.h new file mode 100644 index 00000000..e94ba596 --- /dev/null +++ b/lib/psy.h @@ -0,0 +1,103 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: random psychoacoustics (not including preecho) + last mod: $Id: psy.h,v 1.16.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_PSY_H_ +#define _V_PSY_H_ +#include "smallft.h" + +#ifndef EHMER_MAX +#define EHMER_MAX 56 +#endif + +/* psychoacoustic setup ********************************************/ +#define MAX_BARK 27 +#define P_BANDS 17 +#define P_LEVELS 11 +typedef struct vorbis_info_psy{ + int athp; + int decayp; + + float ath_adjatt; + float ath_maxatt; + + int eighth_octave_lines; + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + int nearDCp; + float nearDCdB; + + int tonemaskp; + float toneatt[P_BANDS][P_LEVELS]; + + int peakattp; + float peakatt[P_BANDS][P_LEVELS]; + + int noisemaskp; + float noisemaxsupp; + float noisewindowlo; + float noisewindowhi; + int noisewindowlomin; + int noisewindowhimin; + float noisemedian[P_BANDS]; + + float max_curve_dB; + + /* decay setup */ + float attack_coeff; + float decay_coeff; +} vorbis_info_psy; + +typedef struct { + int n; + struct vorbis_info_psy *vi; + + float ***tonecurves; + float **peakatt; + float *noisemedian; + + float *ath; + long *octave; /* in n.ocshift format */ + float *bark; + + long firstoc; + long shiftoc; + int eighth_octave_lines; /* power of two, please */ + int total_octave_lines; + +} vorbis_look_psy; + +extern void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,int n,long rate); +extern void _vp_psy_clear(vorbis_look_psy *p); +extern void *_vi_psy_dup(void *source); + +extern void _vi_psy_free(vorbis_info_psy *i); +extern vorbis_info_psy *_vi_psy_copy(vorbis_info_psy *i); + +extern void _vp_compute_mask(vorbis_look_psy *p, + float *fft, + float *mdct, + float *floor, + float *decay); +extern void _vp_apply_floor(vorbis_look_psy *p,float *f,float *flr); + +#endif + + diff --git a/lib/psytune.c b/lib/psytune.c new file mode 100644 index 00000000..7ae9e8f8 --- /dev/null +++ b/lib/psytune.c @@ -0,0 +1,392 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: simple utility that runs audio through the psychoacoustics + without encoding + last mod: $Id: psytune.c,v 1.11.2.1 2000/12/27 23:46:35 xiphmont Exp $ + + ********************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "vorbis/codec.h" +#include "os.h" +#include "psy.h" +#include "mdct.h" +#include "smallft.h" +#include "window.h" +#include "scales.h" +#include "lpc.h" +#include "lsp.h" + +static vorbis_info_psy _psy_set0={ + 1,/*athp*/ + 0,/*decayp*/ + + -100.f, + -140.f, + + 8, + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */ + /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */ + + 2, + -40.f, /* nearDCdB */ + + 1,/* tonemaskp */ + /* 0 10 20 30 40 50 60 70 80 90 100 */ + {{-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*63*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*88*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*125*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*175*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*250*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*350*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*500*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*700*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*1000*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*1400*/ + {-40.,-40.,-40.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*2000*/ + {-40.,-40.,-40.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*2800*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*4000*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*5600*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*8000*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*11500*/ + {-30.,-35.,-35.,-40.,-40.,-50.,-60.,-70.,-80.,-90.,-100.}, /*16000*/ + }, + + 0,/* peakattp */ + {{-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-28.,-28.,-28.}, /*63*/ + {-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-28.,-28.,-28.}, /*88*/ + {-14.,-16.,-18.,-19.,-20.,-21.,-22.,-22.,-28.,-28.,-28.}, /*125*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-18.,-28.,-28.,-28.}, /*175*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-18.,-28.,-28.,-28.}, /*250*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-18.,-28.,-28.,-28.}, /*350*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-28.,-28.,-28.,-28.}, /*500*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-28.}, /*700*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-28.}, /*1000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-28.}, /*1400*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-28.}, /*2000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-28.}, /*2400*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-28.}, /*4000*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-18.,-20.}, /*5600*/ + { -7., -8., -9.,-10.,-10.,-11.,-12.,-13.,-15.,-16.,-17.}, /*8000*/ + { -6., -7., -9., -9., -9., -9.,-10.,-11.,-12.,-13.,-14.}, /*11500*/ + { -6., -6., -9., -9., -9., -9., -9., -9.,-10.,-11.,-12.}, /*16000*/ + }, + + + 1,/*noisemaskp */ + -40.f, /* suppress any noise curve over maxspec+n */ + .5f, /* low window */ + .5f, /* high window */ + 25, + 25, + {.000f, /*63*/ + .000f, /*88*/ + .000f, /*125*/ + .000f, /*175*/ + .000f, /*250*/ + .000f, /*350*/ + .000f, /*500*/ + .500f, /*700*/ + .500f, /*1000*/ + .500f, /*1400*/ + .500f, /*2000*/ + .500f, /*2800*/ + .700f, /*4000*/ + .800f, /*5600*/ + .850f, /*8000*/ + .850f, /*11500*/ + .900f, /*16000*/ + }, + + 105.f, /* even decade + 5 is important; saves an rint() later in a + tight loop) */ + + -0.f, -.004f /* attack/decay control */ +}; + +static int noisy=0; +void analysis(char *base,int i,float *v,int n,int bark,int dB){ + if(noisy){ + int j; + FILE *of; + char buffer[80]; + sprintf(buffer,"%s_%d.m",base,i); + of=fopen(buffer,"w"); + + for(j=0;j<n;j++){ + if(dB && v[j]==0) + fprintf(of,"\n\n"); + else{ + if(bark) + fprintf(of,"%g ",toBARK(22050.f*j/n)); + else + fprintf(of,"%g ",(float)j); + + if(dB){ + fprintf(of,"%g\n",todB(fabs(v[j]))); + }else{ + fprintf(of,"%g\n",v[j]); + } + } + } + fclose(of); + } +} + +typedef struct { + long n; + int ln; + int m; + int *linearmap; + + lpc_lookup lpclook; +} vorbis_look_floor0; + +long frameno=0; + +/* hacked from floor0.c */ +static void floorinit(vorbis_look_floor0 *look,int n,int m,int ln){ + int j; + float scale; + look->m=m; + look->n=n; + look->ln=ln; + lpc_init(&look->lpclook,look->ln,look->m); + + scale=look->ln/toBARK(22050.f); + + look->linearmap=_ogg_malloc(look->n*sizeof(int)); + for(j=0;j<look->n;j++){ + int val=floor( toBARK(22050.f/n*j) *scale); + if(val>look->ln)val=look->ln; + look->linearmap[j]=val; + } +} + +int main(int argc,char *argv[]){ + int eos=0; + float nonz=0.f; + float acc=0.f; + float tot=0.f; + + int framesize=2048; + int order=32; + int map=256; + + float *pcm[2],*out[2],*window,*lpc,*flr,*mask; + signed char *buffer,*buffer2; + mdct_lookup m_look; + drft_lookup f_look; + vorbis_look_psy p_look; + long i,j,k; + + vorbis_look_floor0 floorlook; + + int ath=0; + int decayp=0; + + argv++; + while(*argv){ + if(*argv[0]=='-'){ + /* option */ + if(argv[0][1]=='v'){ + noisy=0; + } + if(argv[0][1]=='A'){ + ath=0; + } + if(argv[0][1]=='D'){ + decayp=0; + } + if(argv[0][1]=='X'){ + ath=0; + decayp=0; + } + }else + if(*argv[0]=='+'){ + /* option */ + if(argv[0][1]=='v'){ + noisy=1; + } + if(argv[0][1]=='A'){ + ath=1; + } + if(argv[0][1]=='D'){ + decayp=1; + } + if(argv[0][1]=='X'){ + ath=1; + decayp=1; + } + }else + framesize=atoi(argv[0]); + argv++; + } + + mask=_ogg_malloc(framesize*sizeof(float)); + pcm[0]=_ogg_malloc(framesize*sizeof(float)); + pcm[1]=_ogg_malloc(framesize*sizeof(float)); + out[0]=_ogg_calloc(framesize/2,sizeof(float)); + out[1]=_ogg_calloc(framesize/2,sizeof(float)); + flr=_ogg_malloc(framesize*sizeof(float)); + lpc=_ogg_malloc(order*sizeof(float)); + buffer=_ogg_malloc(framesize*4); + buffer2=buffer+framesize*2; + window=_vorbis_window(0,framesize,framesize/2,framesize/2); + mdct_init(&m_look,framesize); + drft_init(&f_look,framesize); + _vp_psy_init(&p_look,&_psy_set0,framesize/2,44100); + floorinit(&floorlook,framesize/2,order,map); + + for(i=0;i<P_BANDS;i++) + for(j=0;j<P_LEVELS;j++) + analysis("Ptonecurve",i*100+j,p_look.tonecurves[i][j],EHMER_MAX,0,0); + + /* we cheat on the WAV header; we just bypass 44 bytes and never + verify that it matches 16bit/stereo/44.1kHz. */ + + fread(buffer,1,44,stdin); + fwrite(buffer,1,44,stdout); + memset(buffer,0,framesize*2); + + analysis("window",0,window,framesize,0,0); + + fprintf(stderr,"Processing for frame size %d...\n",framesize); + + while(!eos){ + long bytes=fread(buffer2,1,framesize*2,stdin); + if(bytes<framesize*2) + memset(buffer2+bytes,0,framesize*2-bytes); + + if(bytes!=0){ + + /* uninterleave samples */ + for(i=0;i<framesize;i++){ + pcm[0][i]=((buffer[i*4+1]<<8)| + (0x00ff&(int)buffer[i*4]))/32768.f; + pcm[1][i]=((buffer[i*4+3]<<8)| + (0x00ff&(int)buffer[i*4+2]))/32768.f; + } + + for(i=0;i<2;i++){ + float amp; + + analysis("pre",frameno,pcm[i],framesize,0,0); + memcpy(mask,pcm[i],sizeof(float)*framesize); + + /* do the psychacoustics */ + for(j=0;j<framesize;j++) + mask[j]=pcm[i][j]*=window[j]; + + drft_forward(&f_look,mask); + + mask[0]/=(framesize/4.); + for(j=1;j<framesize-1;j+=2) + mask[(j+1)>>1]=4*hypot(mask[j],mask[j+1])/framesize; + + mdct_forward(&m_look,pcm[i],pcm[i]); + memcpy(mask+framesize/2,pcm[i],sizeof(float)*framesize/2); + analysis("mdct",frameno,pcm[i],framesize/2,0,1); + analysis("fft",frameno,mask,framesize/2,0,1); + + _vp_compute_mask(&p_look,mask,mask+framesize/2,flr,NULL); + + analysis("floor",frameno,flr,framesize/2,0,0); + + for(j=0;j<framesize/2;j++) + flr[j]=fromdB(flr[j]); + + + /*for(j=0;j<framesize/2;){ + float energy=0.; + float acc=0.; + float *v=pcm[i]+j; + int flag=0; + for(k=0;k<32;k++){ + energy+=v[k]*v[k]; + if(fabs(v[k]/flr[j+k])>.5)acc+=v[k]*v[k]; + } + if(acc*2<energy){ + if(acc>0.)fprintf(stderr,"culling\n"); + for(k=0;k<32;k++)v[k]=0; + } + j+=k; + }*/ + + _vp_apply_floor(&p_look,pcm[i],flr); + + + analysis("quant",frameno,pcm[i],framesize/2,0,0); + + /* re-add floor */ + for(j=0;j<framesize/2;j++){ + float val=rint(pcm[i][j]); + tot++; + if(val){ + nonz++; + acc+=log(fabs(val)*2.f+1.f)/log(2); + pcm[i][j]=val*flr[j]; + }else{ + pcm[i][j]=0.f; + } + } + + analysis("final",frameno,pcm[i],framesize/2,0,1); + + /* take it back to time */ + mdct_backward(&m_look,pcm[i],pcm[i]); + for(j=0;j<framesize/2;j++) + out[i][j]+=pcm[i][j]*window[j]; + + frameno++; + } + + /* write data. Use the part of buffer we're about to shift out */ + for(i=0;i<2;i++){ + char *ptr=buffer+i*2; + float *mono=out[i]; + for(j=0;j<framesize/2;j++){ + int val=mono[j]*32767.; + /* might as well guard against clipping */ + if(val>32767)val=32767; + if(val<-32768)val=-32768; + ptr[0]=val&0xff; + ptr[1]=(val>>8)&0xff; + ptr+=4; + } + } + + fprintf(stderr,"*"); + fwrite(buffer,1,framesize*2,stdout); + memmove(buffer,buffer2,framesize*2); + + for(i=0;i<2;i++){ + for(j=0,k=framesize/2;j<framesize/2;j++,k++) + out[i][j]=pcm[i][k]*window[k]; + } + }else + eos=1; + } + fprintf(stderr,"average raw bits of entropy: %.03g/sample\n",acc/tot); + fprintf(stderr,"average nonzero samples: %.03g/%d\n",nonz/tot*framesize/2, + framesize/2); + fprintf(stderr,"Done\n\n"); + return 0; +} diff --git a/lib/scales.h b/lib/scales.h new file mode 100644 index 00000000..4d80b455 --- /dev/null +++ b/lib/scales.h @@ -0,0 +1,51 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH * + * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 * + * by Monty <monty@xiph.org> and the XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: linear scale -> dB, Bark and Mel scales + last mod: $Id: scales.h,v 1.9.2.1 2000/12/27 23:46:36 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_SCALE_H_ +#define _V_SCALES_H_ + +#include <math.h> + +/* 20log10(x) */ +#define DYNAMIC_RANGE_dB 200.f +#define todB(x) ((x)==0?-400.f:log((x)*(x))*4.34294480f) +#define todB_nn(x) ((x)==0.f?-400.f:log(x)*8.6858896f) +#define fromdB(x) (exp((x)*.11512925f)) + +/* The bark scale equations are approximations, since the original + table was somewhat hand rolled. The below are chosen to have the + best possible fit to the rolled tables, thus their somewhat odd + appearance (these are more accurate and over a longer range than + the oft-quoted bark equations found in the texts I have). The + approximations are valid from 0 - 30kHz (nyquist) or so. + + all f in Hz, z in Bark */ + +#define toBARK(n) (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n)) +#define fromBARK(z) (102.f*(z)-2.f*pow(z,2.f)+.4f*pow(z,3.f)+pow(1.46f,z)-1.f) +#define toMEL(n) (log(1.f+(n)*.001f)*1442.695f) +#define fromMEL(m) (1000.f*exp((m)/1442.695f)-1000.f) + +/* Frequency to octave. We arbitrarily declare 63.5 Hz to be octave + 0.0 */ + +#define toOC(n) (log(n)*1.442695f-5.965784f) +#define fromOC(o) (exp(((o)+5.965784f)*.693147f)) + +#endif + diff --git a/libvorbis.spec b/libvorbis.spec new file mode 100644 index 00000000..c6c0b09b --- /dev/null +++ b/libvorbis.spec @@ -0,0 +1,84 @@ +%define name libvorbis +%define version 1.0prebeta4 +%define release 1 + +Summary: The Vorbis General Audio Compression Codec +Name: %{name} +Version: %{version} +Release: %{release} +Group: Libraries/Multimedia +Copyright: LGPL +URL: http://www.xiph.org/ +Vendor: Xiphophorus <team@xiph.org> +Source: ftp://ftp.xiph.org/pub/ogg/vorbis/%{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-root +Requires: libogg >= 1.0beta3 + +%description +Ogg Vorbis is a fully open, non-proprietary, patent-and-royalty-free, +general-purpose compressed audio format for audio and music at fixed +and variable bitrates from 16 to 128 kbps/channel. + +%package devel +Summary: Vorbis Library Development +Group: Development/Libraries +Requires: libogg-devel >= 1.0beta3 +Requires: libvorbis-devel = %{version} + +%description devel +The libvorbis-devel package contains the header files and documentation +needed to develop applications with libvorbis. + +%prep +%setup -q -n %{name}-%{version} + +%build +if [ ! -f configure ]; then + CFLAGS="$RPM_FLAGS" ./autogen.sh --prefix=/usr +else + CFLAGS="$RPM_FLAGS" ./configure --prefix=/usr +fi +make + +%install +[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT +make DESTDIR=$RPM_BUILD_ROOT install + +%files +%defattr(-,root,root) +%doc COPYING +%doc AUTHORS +%doc README +/usr/lib/libvorbis.so.* +/usr/lib/libvorbisfile.so.* +/usr/lib/libvorbisenc.so.* + +%files devel +%doc doc/*.html +%doc doc/*.png +%doc doc/*.txt +%doc doc/vorbisfile +%doc doc/vorbisenc +/usr/share/aclocal/vorbis.m4 +/usr/include/vorbis/codec.h +/usr/include/vorbis/vorbisfile.h +/usr/include/vorbis/vorbisenc.h +/usr/lib/libvorbis.a +/usr/lib/libvorbis.so +/usr/lib/libvorbisfile.a +/usr/lib/libvorbisfile.so +/usr/lib/libvorbisenc.a +/usr/lib/libvorbisenc.so + +%clean +[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT + +%post +/sbin/ldconfig + +%postun +/sbin/ldconfig + +%changelog +* Sat Oct 21 2000 Jack Moffitt <jack@icecast.org> +- initial spec file created |