--- libvorbis-1.3.2.orig/test/Makefile.in
+++ libvorbis-1.3.2/test/Makefile.in
@@ -205,7 +205,7 @@
 AUTOMAKE_OPTIONS = foreign
 INCLUDES = -I$(top_srcdir)/include @OGG_CFLAGS@
 test_SOURCES = util.c util.h write_read.c write_read.h test.c
-test_LDADD = ../lib/libvorbisenc.la ../lib/libvorbis.la @OGG_LIBS@
+test_LDADD = ../lib/libvorbisenc.la ../lib/libvorbis.la @OGG_LIBS@ -lm
 all: all-am
 
 .SUFFIXES:
--- libvorbis-1.3.2.orig/test/Makefile.am
+++ libvorbis-1.3.2/test/Makefile.am
@@ -10,7 +10,7 @@
 	./test$(EXEEXT)
 
 test_SOURCES = util.c util.h write_read.c write_read.h test.c
-test_LDADD = ../lib/libvorbisenc.la ../lib/libvorbis.la @OGG_LIBS@
+test_LDADD = ../lib/libvorbisenc.la ../lib/libvorbis.la @OGG_LIBS@ -lm
 
 debug:
 	$(MAKE) all CFLAGS="@DEBUG@"
--- libvorbis-1.3.2.orig/lib/psy.c
+++ libvorbis-1.3.2/lib/psy.c
@@ -603,8 +603,9 @@
   for (i = 0, x = 0.f;; i++, x += 1.f) {
 
     lo = b[i] >> 16;
-    if( lo>=0 ) break;
     hi = b[i] & 0xffff;
+    if( lo>=0 ) break;
+    if( hi>=n ) break;
 
     tN = N[hi] + N[-lo];
     tX = X[hi] - X[-lo];
--- libvorbis-1.3.2.orig/lib/info.c
+++ libvorbis-1.3.2/lib/info.c
@@ -574,7 +574,8 @@
   oggpack_buffer opb;
   private_state *b=v->backend_state;
 
-  if(!b){
+  if(!b||vi->channels<=0||vi->channels>256){
+    b = NULL;
     ret=OV_EFAULT;
     goto err_out;
   }
--- libvorbis-1.3.2.orig/lib/vorbisenc.c
+++ libvorbis-1.3.2/lib/vorbisenc.c
@@ -685,6 +685,7 @@
   highlevel_encode_setup *hi=&ci->hi;
 
   if(ci==NULL)return(OV_EINVAL);
+  if(vi->channels<1||vi->channels>255)return(OV_EINVAL);
   if(!hi->impulse_block_p)i0=1;
 
   /* too low/high an ATH floater is nonsensical, but doesn't break anything */
--- libvorbis-1.3.2.orig/lib/floor1.c
+++ libvorbis-1.3.2/lib/floor1.c
@@ -167,6 +167,7 @@
 
   for(j=0,k=0;j<info->partitions;j++){
     count+=info->class_dim[info->partitionclass[j]];
+    if(count>VIF_POSIT) goto err_out;
     for(;k<count;k++){
       int t=info->postlist[k+2]=oggpack_read(opb,rangebits);
       if(t<0 || t>=(1<<rangebits))
--- libvorbis-1.3.2.orig/lib/codebook.c
+++ libvorbis-1.3.2/lib/codebook.c
@@ -380,7 +380,7 @@
       t[i] = book->valuelist+entry[i]*book->dim;
     }
     for(i=0,o=0;i<book->dim;i++,o+=step)
-      for (j=0;j<step;j++)
+      for (j=0;o+j<n && j<step;j++)
         a[o+j]+=t[j][i];
   }
   return(0);
@@ -391,41 +391,12 @@
     int i,j,entry;
     float *t;
 
-    if(book->dim>8){
-      for(i=0;i<n;){
-        entry = decode_packed_entry_number(book,b);
-        if(entry==-1)return(-1);
-        t     = book->valuelist+entry*book->dim;
-        for (j=0;j<book->dim;)
-          a[i++]+=t[j++];
-      }
-    }else{
-      for(i=0;i<n;){
-        entry = decode_packed_entry_number(book,b);
-        if(entry==-1)return(-1);
-        t     = book->valuelist+entry*book->dim;
-        j=0;
-        switch((int)book->dim){
-        case 8:
-          a[i++]+=t[j++];
-        case 7:
-          a[i++]+=t[j++];
-        case 6:
-          a[i++]+=t[j++];
-        case 5:
-          a[i++]+=t[j++];
-        case 4:
-          a[i++]+=t[j++];
-        case 3:
-          a[i++]+=t[j++];
-        case 2:
-          a[i++]+=t[j++];
-        case 1:
-          a[i++]+=t[j++];
-        case 0:
-          break;
-        }
-      }
+    for(i=0;i<n;){
+      entry = decode_packed_entry_number(book,b);
+      if(entry==-1)return(-1);
+      t     = book->valuelist+entry*book->dim;
+      for(j=0;i<n && j<book->dim;)
+        a[i++]+=t[j++];
     }
   }
   return(0);
@@ -460,12 +431,13 @@
   long i,j,entry;
   int chptr=0;
   if(book->used_entries>0){
-    for(i=offset/ch;i<(offset+n)/ch;){
+    int m=(offset+n)/ch;
+    for(i=offset/ch;i<m;){
       entry = decode_packed_entry_number(book,b);
       if(entry==-1)return(-1);
       {
         const float *t = book->valuelist+entry*book->dim;
-        for (j=0;j<book->dim;j++){
+        for (j=0;i<m && j<book->dim;j++){
           a[chptr++][i]+=t[j];
           if(chptr==ch){
             chptr=0;
--- libvorbis-1.3.2.orig/debian/libvorbisenc2.links
+++ libvorbis-1.3.2/debian/libvorbisenc2.links
@@ -0,0 +1,3 @@
+usr/lib/libvorbisenc.so.2.0.8 usr/lib/libvorbisenc.so.2.0.2
+usr/lib/libvorbisenc.so.2.0.8 usr/lib/libvorbisenc.so.2.0.7
+
--- libvorbis-1.3.2.orig/debian/compat
+++ libvorbis-1.3.2/debian/compat
@@ -0,0 +1 @@
+7
--- libvorbis-1.3.2.orig/debian/watch
+++ libvorbis-1.3.2/debian/watch
@@ -0,0 +1,2 @@
+version=3
+http://downloads.xiph.org/releases/vorbis/libvorbis-(.+)\.tar\.gz
--- libvorbis-1.3.2.orig/debian/libvorbisfile3.install
+++ libvorbis-1.3.2/debian/libvorbisfile3.install
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libvorbisfile.so.*
--- libvorbis-1.3.2.orig/debian/libvorbis-dev.examples
+++ libvorbis-1.3.2/debian/libvorbis-dev.examples
@@ -0,0 +1,2 @@
+examples/*.c
+examples/*.pl
--- libvorbis-1.3.2.orig/debian/docs
+++ libvorbis-1.3.2/debian/docs
@@ -0,0 +1 @@
+CHANGES
--- libvorbis-1.3.2.orig/debian/libvorbisfile3.links
+++ libvorbis-1.3.2/debian/libvorbisfile3.links
@@ -0,0 +1,3 @@
+usr/lib/libvorbisfile.so.3.3.3 usr/lib/libvorbisfile.so.3.1.1 
+usr/lib/libvorbisfile.so.3.3.3 usr/lib/libvorbisfile.so.3.3.2
+
--- libvorbis-1.3.2.orig/debian/libvorbis0a.lintian-overrides
+++ libvorbis-1.3.2/debian/libvorbis0a.lintian-overrides
@@ -0,0 +1,2 @@
+# Is now 0a due to past packaging mixup
+libvorbis0a: package-name-doesnt-match-sonames libvorbis0
--- libvorbis-1.3.2.orig/debian/libvorbis-dev.install
+++ libvorbis-1.3.2/debian/libvorbis-dev.install
@@ -0,0 +1,7 @@
+debian/tmp/usr/include/vorbis/*
+debian/tmp/usr/lib/*.a
+debian/tmp/usr/lib/*.la
+debian/tmp/usr/lib/*.so
+debian/tmp/usr/lib/pkgconfig/*.pc
+debian/tmp/usr/share/aclocal/*.m4
+debian/tmp/usr/share/doc/libvorbis-*/*	usr/share/doc/libvorbis-dev/html
--- libvorbis-1.3.2.orig/debian/rules
+++ libvorbis-1.3.2/debian/rules
@@ -0,0 +1,45 @@
+#! /usr/bin/make -f
+
+DEB_HOST_ARCH = $(shell dpkg-architecture -qDEB_HOST_ARCH)
+OPTI_FLAGS_LIBONLY := -fomit-frame-pointer -falign-functions=0 -falign-jumps=0 -falign-loops=0
+### PICCORO optimizer flags for i386 x86 machines
+ifeq ($(DEB_HOST_ARCH),i386)
+	OPTI_FLAGS_LIBONLY += -march=i586 -mtune=pentium -mmmx
+else
+ifeq ($(DEB_HOST_ARCH),i486)
+	OPTI_FLAGS_LIBONLY += -march=i586 -mtune=pentium -mmmx
+endif
+endif
+
+ifeq ($(DEB_HOST_ARCH),amd64)
+	OPTI_FLAGS_LIBONLY += -mmmx -msse
+endif
+
+CFLAGS= -O2 $(OPTI_FLAGS_LIBONLY)
+export CFLAGS= -O2 $(OPTI_FLAGS_LIBONLY)
+
+CXXFLAGS= -O2 $(OPTI_FLAGS_LIBONLY)
+export CXXFLAGS= -O2 $(OPTI_FLAGS_LIBONLY)
+
+
+%:
+	dh $@
+
+override_dh_strip:
+	dh_strip --dbg-package=libvorbis-dbg
+
+# Put config.sub rules in until http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=559098 is fixed
+override_dh_auto_configure:
+	ln -sf /usr/share/misc/config.sub .
+	ln -sf /usr/share/misc/config.guess .
+	dh_auto_configure -- --enable-static --with-pic
+
+override_dh_auto_clean:
+	dh_auto_clean
+	rm -f config.sub config.guess
+
+# Trac bug https://trac.xiph.org/ticket/1673
+override_dh_install:
+	rm debian/tmp/usr/share/doc/libvorbis-*/doxygen-build.stamp
+	sed -i "/dependency_libs/ s/'.*'/''/" `find -name '*.la'`
+	dh_install
--- libvorbis-1.3.2.orig/debian/libvorbis-dev.doc-base
+++ libvorbis-1.3.2/debian/libvorbis-dev.doc-base
@@ -0,0 +1,8 @@
+Document: libvorbis
+Author: The Xiph.org Foundation
+Section: Sound
+Title: The Vorbis library technical reference
+
+Format: HTML
+Index: /usr/share/doc/libvorbis-dev/html/index.html
+Files: /usr/share/doc/libvorbis-dev/html/*
--- libvorbis-1.3.2.orig/debian/libvorbis0a.links
+++ libvorbis-1.3.2/debian/libvorbis0a.links
@@ -0,0 +1,2 @@
+usr/lib/libvorbis.so.0.4.5 usr/lib/libvorbis.so.0.4.4
+usr/lib/libvorbis.so.0.4.5 usr/lib/libvorbis.so.0.3.1
--- libvorbis-1.3.2.orig/debian/changelog
+++ libvorbis-1.3.2/debian/changelog
@@ -0,0 +1,358 @@
+libvorbis (1.3.2-2) wheezy-security; urgency=medium
+
+  * Non-maintainer upload by the ELTS Team. 
+  * CVE-2017-14160, CVE-2018-10393
+    Improve bound checking for very low sample rates.
+  * CVE-2018-10392
+    Not validating the number of channels allows a remote attacker
+    to cause a denial of service.
+  * CVE-2017-14633: In Xiph.Org libvorbis 1.3.5, an out-of-bounds array
+    read vulnerability exists in the function mapping0_forward() in
+    mapping0.c, which may lead to DoS when operating on a crafted audio
+    file with vorbis_analysis().
+  * CVE-2017-14632: Xiph.Org libvorbis 1.3.5 allows Remote Code Execution
+    upon freeing uninitialized memory in the function
+    vorbis_analysis_headerout() in info.c when vi->channels<=0, a similar
+    issue to Mozilla bug 550184.
+  * CVE-2017-11333: The vorbis_analysis_wrote function in lib/block.c in
+    Xiph.Org libvorbis 1.3.5 allows remote attackers to cause a denial of
+    service (OOM) via a crafted wav file.
+  * CVE-2018-5146: out-of-bounds memory write in the codeboook parsing
+    code of the Libvorbis multimedia library could result in the execution
+    of arbitrary code.
+
+ -- PICCORO Lenz McKAY <mckaygerhard@gmail.com>  Wed, 27 Nov 2019 19:03:02 +0100
+
+libvorbis (1.3.2-1.3) unstable; urgency=low
+
+  * Non-maintainer upload to fix release goals
+  * Convert to Multi-Arch, closes: #637578 (Thanks, Steve Langasek)
+  * Remove .la file dependencies, closes: #633339 
+
+ -- Riku Voipio <riku.voipio@linaro.org>  Mon, 07 May 2012 14:53:26 +0300
+
+libvorbis (1.3.2-1.2) unstable; urgency=high
+
+  * Non-maintainer upload by the Security Team.
+  * Fix cve-2012-0444: buffer overflow in floor1.c.
+
+ -- Michael Gilbert <mgilbert@debian.org>  Tue, 17 Apr 2012 22:37:49 -0400
+
+libvorbis (1.3.2-1.1) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Fix FTBFS with ld --no-add-needed (Closes: #604797).
+    patch made by Matthias Klose <doko@ubuntu.com>.
+
+ -- HIGUCHI Daisuke (VDR dai) <dai@debian.org>  Mon, 09 Jan 2012 02:58:52 +0900
+
+libvorbis (1.3.2-1) unstable; urgency=low
+
+  * New upstream release (Closes: #613489)
+    - ov_fopen should have const qualifier for char *path (Closes: #547223)
+  * debian/control
+    - Bumped standards version to 3.9.1
+  * debian/rules
+    - Add --with-pic (Closes: #603195)
+  * debian/docs
+    - CHANGELOG was renamed to CHANGES
+  * Added debian/source/format 1.0
+
+ -- John Francesco Ferlito <johnf@inodes.org>  Tue, 15 Feb 2011 23:32:40 +1100
+
+libvorbis (1.3.1-1) unstable; urgency=low
+
+  * New upstream release.
+    - Please package new upstream version 1.3.1. (Closes: #575676)
+    - libvorbis: additional CVE-2009-3379 security fixes. (Closes: #573562)
+    - libvorbis0a: Incorrect encoding on powerpc. (Closes: #549899)
+    - FTBFS with binutils-gold. (Closes: #555383)
+  * debian/compat
+    - Moved to version 7
+  * debian/control
+    - Added ${misc:Depends}.
+    - Bumped dependency on debhelper to 7.0.50~.
+    - Added strict version depends on libvorbis0a to libvorbisenc2 and
+      libvorbisfile3.
+  * Added debian/docs
+  * Simplified debian/*.install
+  * Updated debian/libvorbis0a.symbols
+  * Moved to debhelper 7 style dh rules
+
+ -- John Francesco Ferlito <johnf@inodes.org>  Fri, 26 Mar 2010 19:10:35 +1100
+
+libvorbis (1.2.3-3) unstable; urgency=low
+
+  * debian/copyright
+    - Add details for doc/rfc5215.txt (Closes: #550687).
+  * Add a -dbg package (Closes: #516661).
+
+ -- John Francesco Ferlito <johnf@inodes.org>  Tue, 13 Oct 2009 09:46:51 +1100
+
+libvorbis (1.2.3-2) unstable; urgency=low
+
+  * Add back in changes from dfsg-5 and dfsg-6.
+  * Remove CVE-2009-2663.patch
+
+ -- John Francesco Ferlito <johnf@inodes.org>  Wed, 30 Sep 2009 09:28:22 +1000
+
+libvorbis (1.2.3-1) unstable; urgency=low
+
+  * New upstream release (Closes: #543549, #249695) (LP: #418059).
+    - Remove upstream-r14811_huffman_sanity_checks.diff
+    - Remove CVE-2008-1420.patch
+    - Remove CVE-2008-1423+CVE-2008-1419.patch
+  * Draft RFCs have been replaced with RFC5215 which is DFSG compliant due to
+    clause 11. SO there is no more need for a dfsg binary.
+  * Update .symbol files.
+  * Update debian/control
+    + Add version dependency on debhelper.
+    + Bump to Standards-Version 3.8.3.
+    + Add John Francesco Ferlito to Uploaders.
+    + Remove Adeodato Simó from Uploaders.
+    + Remove duplicate Section headers.
+    + Update short descriptions.
+  * Remove quilt as there are currently no patches.
+  * Register HTML documentation with doc-base.
+  * Add lintian override for package-name-doesnt-match-sonames.
+
+ -- John Francesco Ferlito <johnf@inodes.org>  Tue, 29 Sep 2009 20:42:57 +1000
+
+libvorbis (1.2.0.dfsg-6) unstable; urgency=high
+
+  * Fix CVE-2009-2663: two bugs in libvorbis that allowed a crafted ogg
+    file to corrupt memory.  (Closes: #540958)
+  * patches/CVE-2008-1420.patch: fix a regression playing files generated
+    by 1.0b1, from upstream trunk.  Thanks Michael Gold.  (Closes: #504421)
+
+ -- Peter Samuelson <peter@p12n.org>  Mon, 10 Aug 2009 23:11:11 -0500
+
+libvorbis (1.2.0.dfsg-5) unstable; urgency=low
+
+  * New maintainer.
+  * Standards-Version: 3.8.1.
+  * gcc -fno-finite-math-only on armel, to work around a gcc bug
+    (fixed upstream in gcc 4.3 and 4.4).  (Closes: #515949)
+  * Fix watch file to unmangle .dfsg in version, thanks Lintian.
+  * Distinguish the short descriptions of the different lib packages, and
+    other tweaks to debian/control.  Thanks Lintian.  (Closes: #432688)
+
+ -- Peter Samuelson <peter@p12n.org>  Thu, 28 May 2009 21:56:02 -0500
+
+libvorbis (1.2.0.dfsg-4) unstable; urgency=low
+
+  * Add upstream-r14811_huffman_sanity_checks.diff.  closes: #482039.
+  * Bump to Standards-Version 3.8.0.
+  * Remove myself from Uploaders.
+
+ -- Clint Adams <schizo@debian.org>  Tue, 10 Jun 2008 12:06:58 -0400
+
+libvorbis (1.2.0.dfsg-3.1) unstable; urgency=high
+
+  * Non-maintainer upload by the security team
+  * Fix integer overflows (and possible DoS attacks) via crafted
+    OGG files (Closes: #482518)
+    Fixes: CVE-2008-1423, CVE-2008-1420, CVE-2008-1419
+
+ -- Steffen Joeris <white@debian.org>  Mon, 26 May 2008 12:48:06 +0000
+
+libvorbis (1.2.0.dfsg-3) unstable; urgency=low
+
+  * Use dpkg-gensymbols, with symbol files obtained from Mole (stripping
+    debian revision and .dfsg suffix).
+
+  * Install upstream CHANGES file as changelog.gz. (Closes: #302037)
+
+  * Bump debian/compat to 5, and Standards-Version to 3.7.3 (no changes
+    needed).
+
+  * Use quilt.make in debian/rules.
+
+ -- Adeodato Simó <dato@net.com.org.es>  Thu, 27 Dec 2007 14:33:45 +0100
+
+libvorbis (1.2.0.dfsg-2) unstable; urgency=high
+
+  * Bump shlibs for libvorbis0a due to new vorbis_synthesis_idheader header.
+    (Closes: #436083)
+
+ -- Adeodato Simó <dato@net.com.org.es>  Tue, 14 Aug 2007 20:55:54 +0200
+
+libvorbis (1.2.0.dfsg-1) unstable; urgency=low
+
+  [ Adeodato Simó ]
+  * Use ${binary:Version} instead of ${Source-Version}.
+
+  [ Clint Adams ]
+  * New upstream release.
+    - Remove upstream_r13198-fix_segfault_in_ov_time_seek.diff .
+    - Fixes: CVE-2007-4029, CVE-2007-4065, CVE-2007-4066
+  * Bump shlibs for libvorbisfile3 to >= 1.2.0 due to new ov_fopen
+    function.
+
+ -- Clint Adams <schizo@debian.org>  Fri, 27 Jul 2007 02:57:44 -0400
+
+libvorbis (1.1.2.dfsg-2) unstable; urgency=low
+
+  * Bump to Standards-Version 3.7.2.
+  * Add upstream_r13198-fix_segfault_in_ov_time_seek.diff. closes: #281995.
+
+ -- Clint Adams <schizo@debian.org>  Fri, 29 Jun 2007 09:46:12 -0400
+
+libvorbis (1.1.2.dfsg-1.2) unstable; urgency=high
+
+  * Fix shlibs files for libvorbisenc and libvorbisfile, which were broken
+    by my first NMU to have dependencies for libvorbis0a. Closes: #395048
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 24 Oct 2006 19:55:19 -0400
+
+libvorbis (1.1.2.dfsg-1.1) unstable; urgency=low
+
+  * NMU
+  * Remove draft RFC files, as they are not under a free license.
+    Closes: #390660
+  * Repackage the source package without these files.
+  * Add README.Source documenting how the upstream source is repackaged.
+  * Modify dh_makeshlibs call to avoid generating a shlibs file that has
+    an unncessarily tight versioned dependency on this new pseudo-version
+    of libvorbis.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 15 Oct 2006 17:21:37 -0400
+
+libvorbis (1.1.2-1) unstable; urgency=low
+
+  * Switch maintenance to the Debian Xiph.org Maintainers (alioth/pkg-xiph).
+
+  * New upstream release packaged. (Closes: #327586)
+
+  * Move HTML documentation from /usr/share/doc/libvorbis-dev itself to an
+    html/ subdirectory of it.
+
+  * Update debian/control:
+    + drop unnecessary build-dependency on devscripts.
+    + drop version restriction on debhelper and libogg-dev build-dependencies,
+      since they're already satisfied with stable.
+
+  * Overhaul debian/rules, and switch to quilt for patch management.
+
+  * Add debian/compat file, instead of exporting DH_COMPAT.
+
+  * Update download URL in debian/copyright.
+
+  * Add debian/watch file.
+
+  * Bumped Standards-Version to 3.6.2 (no changes required).
+
+ -- Adeodato Simó <dato@net.com.org.es>  Thu, 26 Jan 2006 01:35:39 +0100
+
+libvorbis (1.1.0-1) unstable; urgency=low
+
+  * New upstream.
+
+ -- Christopher L Cheney <ccheney@debian.org>  Thu, 17 Mar 2005 21:30:00 -0600
+
+libvorbis (1.0.1-1) unstable; urgency=low
+
+  * New upstream.
+  * Improved descriptions. (Closes: #166649)
+  * Updated DEB_BUILD_OPTIONS support. (Closes: #188464)
+
+ -- Christopher L Cheney <ccheney@debian.org>  Tue,  9 Dec 2003 01:00:00 -0600
+
+libvorbis (1.0.0-3) unstable; urgency=low
+
+  * Add libvorbis0 conflict to libvorbis0a.
+
+ -- Christopher L Cheney <ccheney@debian.org>  Wed, 12 Mar 2003 17:00:00 -0600
+
+libvorbis (1.0.0-2) unstable; urgency=low
+
+  * Rename libvorbis0 -> libvorbis0a to keep packages from upgrading to it
+    by mistake. (Closes: #156227, #156365, #161961, #171548, #172466,
+    #172469, #178756)
+  * GNU config automated update: config.sub (20020621 to 20030103),
+    config.guess (20020529 to 20030110)
+
+ -- Christopher L Cheney <ccheney@debian.org>  Sat,  8 Mar 2003 13:00:00 -0600
+
+libvorbis (1.0.0-1) unstable; urgency=low
+
+  * New upstream.
+  * Split libvorbis package into libvorbis libvorbisenc libvorbisfile due to
+    shared object major versions going out of sync.
+
+ -- Christopher L Cheney <ccheney@debian.org>  Fri, 19 Jul 2002 09:00:00 -0500
+
+libvorbis (1.0rc3-1) unstable; urgency=low
+
+  * New upstream. (Closes: #121995, #123472)
+  * added autotools target (config.* updater) to rules
+
+ -- Christopher L Cheney <ccheney@debian.org>  Mon, 24 Dec 2001 11:00:00 -0600
+
+libvorbis (1.0rc2-1) unstable; urgency=low
+
+  * New upstream.
+
+ -- Christopher L Cheney <ccheney@debian.org>  Sun, 12 Aug 2001 22:00:00 -0500
+
+libvorbis (1.0rc1-1) unstable; urgency=low
+
+  * New upstream. (Closes: #84977, #95330)
+  * Upstream says lame at fault. See bug details. (Closes: #98010)
+  * Fixed versioned depends.
+  * Changed clean method to distclean.
+
+ -- Christopher L Cheney <ccheney@debian.org>  Sun, 17 Jun 2001 20:00:00 -0500
+
+libvorbis (1.0beta4-1) unstable; urgency=low
+
+  * New upstream.
+  * Appears to be fixed, can't reproduce bug (closes: #78848)
+
+ -- Christopher L Cheney <ccheney@debian.org>  Mon, 26 Feb 2001 08:00:00 -0600
+
+libvorbis (1.0beta3-3) unstable; urgency=low
+
+  * Fixed Build-Depends libogg-dev version dependency.
+  * Fixed Sections.
+  * Updated to Standards-Version to 3.5.1.0
+
+ -- Christopher L Cheney <ccheney@debian.org>  Sat, 17 Feb 2001 18:14:53 -0600
+
+libvorbis (1.0beta3-2) unstable; urgency=low
+
+  * Added dependency for libogg-dev (closes: #78262)
+  * Added dependency for libogg-dev (closes: #81432)
+  * Corrected development library package name (closes: #82464)
+
+ -- Christopher L Cheney <ccheney@debian.org>  Sat,  3 Feb 2001 13:29:30 -0600
+
+libvorbis (1.0beta3-1) unstable; urgency=low
+
+  * New Maintainer.
+  * Upstream source was reorganized.
+  * Package split according to the upstream reorganization.
+
+ -- Christopher L Cheney <ccheney@debian.org>  Tue, 31 Oct 2000 15:08:22 -0600
+
+vorbis (1.0beta2-1) unstable; urgency=low
+
+  * New upstream version. Closes: #67326, #68416
+  * Changed xmms-vorbis to Architechture: any.  Closes: #67395
+  * Added Build-deps. Closes: #66628
+  * Moved vorbize to vorbis-tools along with oggenc and vorbiscomment
+
+ -- Michael Beattie <mjb@debian.org>  Wed,  9 Aug 2000 00:30:15 +1200
+
+vorbis (1.0beta1-1) unstable; urgency=low
+
+  * First Beta, Ready for debian release.
+
+ -- Michael Beattie <mickyb@es.co.nz>  Fri, 30 Jun 2000 19:26:59 +1200
+
+vorbis (0.0-1) unstable; urgency=low
+
+  * Initial Release.
+  * Initial package, not placed in archive.
+
+ -- Michael Beattie <mickyb@es.co.nz>  Mon, 26 Jun 2000 18:59:56 +1200
--- libvorbis-1.3.2.orig/debian/copyright
+++ libvorbis-1.3.2/debian/copyright
@@ -0,0 +1,50 @@
+This package was debianized by Christopher L Cheney <ccheney@debian.org> on
+Tue, 31 Oct 2000 15:08:22 -0600.
+
+It was downloaded from http://www.xiph.org/downloads/:
+
+    URL:<http://downloads.xiph.org/releases/vorbis/libvorbis-1.1.2.tar.gz>
+
+Upstream Author: Monty <monty@xiph.org>
+
+Copyright:
+
+  Copyright (c) 2002, Xiph.org Foundation
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  - Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  - Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  - Neither the name of the Xiph.org Foundation nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The file doc/rfc5215.txt is available under the
+following license:
+
+   The authors agree to grant third parties the irrevocable right to
+   copy, use, and distribute the work, with or without modification, in
+   any medium, without royalty, provided that, unless separate
+   permission is granted, redistributed modified works do not contain
+   misleading author, version, name of work, or endorsement information.
+
+
--- libvorbis-1.3.2.orig/debian/libvorbisenc2.install
+++ libvorbis-1.3.2/debian/libvorbisenc2.install
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libvorbisenc.so.*
--- libvorbis-1.3.2.orig/debian/libvorbis0a.install
+++ libvorbis-1.3.2/debian/libvorbis0a.install
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libvorbis.so.*
--- libvorbis-1.3.2.orig/debian/libvorbisfile3.lintian-overrides
+++ libvorbis-1.3.2/debian/libvorbisfile3.lintian-overrides
@@ -0,0 +1 @@
+libvorbisfile3: using-first-person-in-description line 5: I
--- libvorbis-1.3.2.orig/debian/control
+++ libvorbis-1.3.2/debian/control
@@ -0,0 +1,71 @@
+Source: libvorbis
+Section: libs
+Priority: optional
+Maintainer: Debian Xiph.org Maintainers <pkg-xiph-maint@lists.alioth.debian.org>
+Uploaders: Peter Samuelson <peter@p12n.org>, John Francesco Ferlito <johnf@inodes.org>
+Build-Depends: autotools-dev, debhelper (>= 7.0.50~), libogg-dev
+Standards-Version: 3.9.1
+Vcs-Bzr: http://bzr.debian.org/bzr/pkg-xiph/libvorbis
+
+Package: libvorbis0a
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Conflicts: libvorbis0
+Replaces: libvorbis0
+Description: The Vorbis General Audio Compression Codec (Decoder library)
+ 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.
+ .
+ The Vorbis library is the primary Ogg Vorbis library.
+
+Package: libvorbisenc2
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, libvorbis0a (= ${binary:Version})
+Conflicts: libvorbis0 (<< 1.0.0)
+Replaces: libvorbis0 (<< 1.0.0)
+Description: The Vorbis General Audio Compression Codec (Encoder library)
+ 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.
+ .
+ The Vorbisenc library provides a convenient API for setting up an encoding
+ environment using libvorbis.
+
+Package: libvorbisfile3
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, libvorbis0a (= ${binary:Version})
+Conflicts: libvorbis0 (<< 1.0.0)
+Replaces: libvorbis0 (<< 1.0.0)
+Description: The Vorbis General Audio Compression Codec (High Level API)
+ 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.
+ .
+ The Vorbisfile library provides a convenient high-level API for decoding
+ and basic manipulation of all Vorbis I audio streams.
+
+Package: libvorbis-dev
+Architecture: any
+Section: libdevel
+Depends: ${misc:Depends}, libogg-dev, libvorbis0a (= ${binary:Version}), libvorbisenc2 (= ${binary:Version}), libvorbisfile3 (= ${binary:Version})
+Description: The Vorbis General Audio Compression Codec (development files)
+ 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.
+ .
+ This package contains the header files and documentation needed to develop
+ applications with libvorbis.
+
+Package: libvorbis-dbg
+Architecture: any
+Section: debug
+Priority: extra
+Depends: ${misc:Depends}, libvorbis0a (= ${binary:Version}), libvorbisenc2 (= ${binary:Version}), libvorbisfile3 (= ${binary:Version})
+Description: The Vorbis General Audio Compression Codec (debug files)
+ 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.
+ .
+ This package contains debugging symbols useful for tracking bugs in
+ applications with libvorbis.
--- libvorbis-1.3.2.orig/debian/source/format
+++ libvorbis-1.3.2/debian/source/format
@@ -0,0 +1 @@
+1.0
--- libvorbis-1.3.2.orig/debian/patches/CVE-2017-14633.patch
+++ libvorbis-1.3.2/debian/patches/CVE-2017-14633.patch
@@ -0,0 +1,35 @@
+Description: CVE-2017-14633: Don't allow for more than 256 channels
+ This is a modified version of the following upstream commit. While
+ we're here, also handle invalid channels<=0, which introduces
+ CVE-2017-14633, but we fix that in a separate patch. 
+From a79ec216cd119069c68b8f3542c6a425a74ab993 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Tue, 31 Oct 2017 18:32:46 +0100
+Subject: [PATCH] CVE-2017-14633: Don't allow for more than 256 channels
+
+Otherwise
+
+ for(i=0;i<vi->channels;i++){
+      /* the encoder setup assumes that all the modes used by any
+         specific bitrate tweaking use the same floor */
+      int submap=info->chmuxlist[i];
+
+overreads later in mapping0_forward since chmuxlist is a fixed array of
+256 elements max.
+---
+ lib/info.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: b/lib/info.c
+===================================================================
+--- a/lib/info.c	2018-04-19 12:01:12.864866736 -0400
++++ b/lib/info.c	2018-04-19 12:01:12.860866654 -0400
+@@ -574,7 +574,7 @@ int vorbis_analysis_headerout(vorbis_dsp
+   oggpack_buffer opb;
+   private_state *b=v->backend_state;
+ 
+-  if(!b){
++  if(!b||vi->channels<=0||vi->channels>256){
+     ret=OV_EFAULT;
+     goto err_out;
+   }
--- libvorbis-1.3.2.orig/debian/patches/CVE-2017-14160--CVE-2018-10393.patch
+++ libvorbis-1.3.2/debian/patches/CVE-2017-14160--CVE-2018-10393.patch
@@ -0,0 +1,15 @@
+Index: libvorbis-1.3.2/lib/psy.c
+===================================================================
+--- libvorbis-1.3.2.orig/lib/psy.c	2019-11-27 16:00:11.560482376 +0100
++++ libvorbis-1.3.2/lib/psy.c	2019-11-27 16:00:11.556482176 +0100
+@@ -603,8 +603,9 @@
+   for (i = 0, x = 0.f;; i++, x += 1.f) {
+ 
+     lo = b[i] >> 16;
+-    if( lo>=0 ) break;
+     hi = b[i] & 0xffff;
++    if( lo>=0 ) break;
++    if( hi>=n ) break;
+ 
+     tN = N[hi] + N[-lo];
+     tX = X[hi] - X[-lo];
--- libvorbis-1.3.2.orig/debian/patches/CVE-2017-14632.patch
+++ libvorbis-1.3.2/debian/patches/CVE-2017-14632.patch
@@ -0,0 +1,55 @@
+Description: backport fix
+ While fixing CVE-2017-14633, an extra check was added which might
+ have triggered CVE-2017-14632, normally not present in 1.3.2. The fix
+ for CVE-2017-14632 was therefore backported here.
+From c1c2831fc7306d5fbd7bc800324efd12b28d327f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Wed, 15 Nov 2017 18:22:59 +0100
+Subject: [PATCH] CVE-2017-14632: vorbis_analysis_header_out: Don't clear opb
+ if not initialized
+
+If the number of channels is not within the allowed range
+we call oggback_writeclear altough it's not initialized yet.
+
+This fixes
+
+    =23371== Invalid free() / delete / delete[] / realloc()
+    ==23371==    at 0x4C2CE1B: free (vg_replace_malloc.c:530)
+    ==23371==    by 0x829CA31: oggpack_writeclear (in /usr/lib/x86_64-linux-gnu/libogg.so.0.8.2)
+    ==23371==    by 0x84B96EE: vorbis_analysis_headerout (info.c:652)
+    ==23371==    by 0x9FBCBCC: ??? (in /usr/lib/x86_64-linux-gnu/sox/libsox_fmt_vorbis.so)
+    ==23371==    by 0x4E524F1: ??? (in /usr/lib/x86_64-linux-gnu/libsox.so.2.0.1)
+    ==23371==    by 0x4E52CCA: sox_open_write (in /usr/lib/x86_64-linux-gnu/libsox.so.2.0.1)
+    ==23371==    by 0x10D82A: open_output_file (sox.c:1556)
+    ==23371==    by 0x10D82A: process (sox.c:1753)
+    ==23371==    by 0x10D82A: main (sox.c:3012)
+    ==23371==  Address 0x68768c8 is 488 bytes inside a block of size 880 alloc'd
+    ==23371==    at 0x4C2BB1F: malloc (vg_replace_malloc.c:298)
+    ==23371==    by 0x4C2DE9F: realloc (vg_replace_malloc.c:785)
+    ==23371==    by 0x4E545C2: lsx_realloc (in /usr/lib/x86_64-linux-gnu/libsox.so.2.0.1)
+    ==23371==    by 0x9FBC9A0: ??? (in /usr/lib/x86_64-linux-gnu/sox/libsox_fmt_vorbis.so)
+    ==23371==    by 0x4E524F1: ??? (in /usr/lib/x86_64-linux-gnu/libsox.so.2.0.1)
+    ==23371==    by 0x4E52CCA: sox_open_write (in /usr/lib/x86_64-linux-gnu/libsox.so.2.0.1)
+    ==23371==    by 0x10D82A: open_output_file (sox.c:1556)
+    ==23371==    by 0x10D82A: process (sox.c:1753)
+    ==23371==    by 0x10D82A: main (sox.c:3012)
+
+as seen when using the testcase from CVE-2017-11333 with
+008d23b782be09c8d75ba8190b1794abd66c7121 applied. However the error was
+there before.
+---
+ lib/info.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+Index: b/lib/info.c
+===================================================================
+--- a/lib/info.c	2018-04-19 12:01:24.321102192 -0400
++++ b/lib/info.c	2018-04-19 12:01:24.317102110 -0400
+@@ -575,6 +575,7 @@ int vorbis_analysis_headerout(vorbis_dsp
+   private_state *b=v->backend_state;
+ 
+   if(!b||vi->channels<=0||vi->channels>256){
++    b = NULL;
+     ret=OV_EFAULT;
+     goto err_out;
+   }
--- libvorbis-1.3.2.orig/debian/patches/CVE-2018-10392.patch
+++ libvorbis-1.3.2/debian/patches/CVE-2018-10392.patch
@@ -0,0 +1,12 @@
+Index: libvorbis-1.3.2/lib/vorbisenc.c
+===================================================================
+--- libvorbis-1.3.2.orig/lib/vorbisenc.c	2010-03-26 07:20:51.000000000 +0100
++++ libvorbis-1.3.2/lib/vorbisenc.c	2019-11-27 16:02:26.611211473 +0100
+@@ -685,6 +685,7 @@
+   highlevel_encode_setup *hi=&ci->hi;
+ 
+   if(ci==NULL)return(OV_EINVAL);
++  if(vi->channels<1||vi->channels>255)return(OV_EINVAL);
+   if(!hi->impulse_block_p)i0=1;
+ 
+   /* too low/high an ATH floater is nonsensical, but doesn't break anything */
--- libvorbis-1.3.2.orig/debian/patches/series
+++ libvorbis-1.3.2/debian/patches/series
@@ -0,0 +1,6 @@
+CVE-2017-14633.patch
+CVE-2017-14632.patch
+CVE-2018-5146.patch
+
+CVE-2017-14160--CVE-2018-10393.patch
+CVE-2018-10392.patch
--- libvorbis-1.3.2.orig/debian/patches/CVE-2018-5146.patch
+++ libvorbis-1.3.2/debian/patches/CVE-2018-5146.patch
@@ -0,0 +1,89 @@
+From: Thomas Daede <daede003@umn.edu>
+Date: Thu, 15 Mar 2018 14:15:31 -0700
+Subject: CVE-2018-5146: Prevent out-of-bounds write in codebook decoding.
+Origin: https://git.xiph.org/?p=vorbis.git;a=commit;h=667ceb4aab60c1f74060143bb24e5f427b3cce5f
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-5146
+
+Codebooks that are not an exact divisor of the partition size are now
+truncated to fit within the partition.
+---
+ lib/codebook.c | 48 ++++++++++--------------------------------------
+ 1 file changed, 10 insertions(+), 38 deletions(-)
+
+Index: b/lib/codebook.c
+===================================================================
+--- a/lib/codebook.c	2018-04-19 12:01:33.685294652 -0400
++++ b/lib/codebook.c	2018-04-19 12:01:33.681294570 -0400
+@@ -380,7 +380,7 @@ long vorbis_book_decodevs_add(codebook *
+       t[i] = book->valuelist+entry[i]*book->dim;
+     }
+     for(i=0,o=0;i<book->dim;i++,o+=step)
+-      for (j=0;j<step;j++)
++      for (j=0;o+j<n && j<step;j++)
+         a[o+j]+=t[j][i];
+   }
+   return(0);
+@@ -391,41 +391,12 @@ long vorbis_book_decodev_add(codebook *b
+     int i,j,entry;
+     float *t;
+ 
+-    if(book->dim>8){
+-      for(i=0;i<n;){
+-        entry = decode_packed_entry_number(book,b);
+-        if(entry==-1)return(-1);
+-        t     = book->valuelist+entry*book->dim;
+-        for (j=0;j<book->dim;)
+-          a[i++]+=t[j++];
+-      }
+-    }else{
+-      for(i=0;i<n;){
+-        entry = decode_packed_entry_number(book,b);
+-        if(entry==-1)return(-1);
+-        t     = book->valuelist+entry*book->dim;
+-        j=0;
+-        switch((int)book->dim){
+-        case 8:
+-          a[i++]+=t[j++];
+-        case 7:
+-          a[i++]+=t[j++];
+-        case 6:
+-          a[i++]+=t[j++];
+-        case 5:
+-          a[i++]+=t[j++];
+-        case 4:
+-          a[i++]+=t[j++];
+-        case 3:
+-          a[i++]+=t[j++];
+-        case 2:
+-          a[i++]+=t[j++];
+-        case 1:
+-          a[i++]+=t[j++];
+-        case 0:
+-          break;
+-        }
+-      }
++    for(i=0;i<n;){
++      entry = decode_packed_entry_number(book,b);
++      if(entry==-1)return(-1);
++      t     = book->valuelist+entry*book->dim;
++      for(j=0;i<n && j<book->dim;)
++        a[i++]+=t[j++];
+     }
+   }
+   return(0);
+@@ -460,12 +431,13 @@ long vorbis_book_decodevv_add(codebook *
+   long i,j,entry;
+   int chptr=0;
+   if(book->used_entries>0){
+-    for(i=offset/ch;i<(offset+n)/ch;){
++    int m=(offset+n)/ch;
++    for(i=offset/ch;i<m;){
+       entry = decode_packed_entry_number(book,b);
+       if(entry==-1)return(-1);
+       {
+         const float *t = book->valuelist+entry*book->dim;
+-        for (j=0;j<book->dim;j++){
++        for (j=0;i<m && j<book->dim;j++){
+           a[chptr++][i]+=t[j];
+           if(chptr==ch){
+             chptr=0;
--- libvorbis-1.3.2.orig/.pc/.quilt_patches
+++ libvorbis-1.3.2/.pc/.quilt_patches
@@ -0,0 +1 @@
+debian/patches
--- libvorbis-1.3.2.orig/.pc/applied-patches
+++ libvorbis-1.3.2/.pc/applied-patches
@@ -0,0 +1,5 @@
+CVE-2017-14633.patch
+CVE-2017-14632.patch
+CVE-2018-5146.patch
+CVE-2017-14160--CVE-2018-10393.patch
+CVE-2018-10392.patch
--- libvorbis-1.3.2.orig/.pc/.quilt_series
+++ libvorbis-1.3.2/.pc/.quilt_series
@@ -0,0 +1 @@
+series
--- libvorbis-1.3.2.orig/.pc/.version
+++ libvorbis-1.3.2/.pc/.version
@@ -0,0 +1 @@
+2
--- libvorbis-1.3.2.orig/.pc/CVE-2017-14633.patch/lib/info.c
+++ libvorbis-1.3.2/.pc/CVE-2017-14633.patch/lib/info.c
@@ -0,0 +1,664 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+ *                                                                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+ function: maintain the info structure, info <-> header packets
+ last mod: $Id: info.c 17584 2010-11-01 19:26:16Z xiphmont $
+
+ ********************************************************************/
+
+/* 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 "codec_internal.h"
+#include "codebook.h"
+#include "registry.h"
+#include "window.h"
+#include "psy.h"
+#include "misc.h"
+#include "os.h"
+
+#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.2"
+#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20101101 (Schaufenugget)"
+
+/* helpers */
+static int ilog2(unsigned int v){
+  int ret=0;
+  if(v)--v;
+  while(v){
+    ret++;
+    v>>=1;
+  }
+  return(ret);
+}
+
+static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){
+
+  while(bytes--){
+    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(*vc));
+}
+
+void vorbis_comment_add(vorbis_comment *vc,const char *comment){
+  vc->user_comments=_ogg_realloc(vc->user_comments,
+                            (vc->comments+2)*sizeof(*vc->user_comments));
+  vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
+                                  (vc->comments+2)*sizeof(*vc->comment_lengths));
+  vc->comment_lengths[vc->comments]=strlen(comment);
+  vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
+  strcpy(vc->user_comments[vc->comments], comment);
+  vc->comments++;
+  vc->user_comments[vc->comments]=NULL;
+}
+
+void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const 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, const 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, const 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;
+    if(vc->user_comments){
+      for(i=0;i<vc->comments;i++)
+        if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
+      _ogg_free(vc->user_comments);
+    }
+    if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
+    if(vc->vendor)_ogg_free(vc->vendor);
+    memset(vc,0,sizeof(*vc));
+  }
+}
+
+/* blocksize 0 is guaranteed to be short, 1 is guaranteed to be long.
+   They may be equal, but short will never ge greater than long */
+int vorbis_info_blocksize(vorbis_info *vi,int zo){
+  codec_setup_info *ci = vi->codec_setup;
+  return ci ? ci->blocksizes[zo] : -1;
+}
+
+/* used by synthesis, which has a full, alloced vi */
+void vorbis_info_init(vorbis_info *vi){
+  memset(vi,0,sizeof(*vi));
+  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 */
+      if(ci->map_param[i]) /* this may be cleaning up an aborted
+                              unpack, in which case the below type
+                              cannot be trusted */
+        _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
+
+    for(i=0;i<ci->floors;i++) /* unpack does the range checking */
+      if(ci->floor_param[i]) /* this may be cleaning up an aborted
+                                unpack, in which case the below type
+                                cannot be trusted */
+        _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
+
+    for(i=0;i<ci->residues;i++) /* unpack does the range checking */
+      if(ci->residue_param[i]) /* this may be cleaning up an aborted
+                                  unpack, in which case the below type
+                                  cannot be trusted */
+        _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
+
+    for(i=0;i<ci->books;i++){
+      if(ci->book_param[i]){
+        /* knows if the book was not alloced */
+        vorbis_staticbook_destroy(ci->book_param[i]);
+      }
+      if(ci->fullbooks)
+        vorbis_book_clear(ci->fullbooks+i);
+    }
+    if(ci->fullbooks)
+        _ogg_free(ci->fullbooks);
+
+    for(i=0;i<ci->psys;i++)
+      _vi_psy_free(ci->psy_param[i]);
+
+    _ogg_free(ci);
+  }
+
+  memset(vi,0,sizeof(*vi));
+}
+
+/* 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]<64)goto err_out;
+  if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
+  if(ci->blocksizes[1]>8192)goto err_out;
+
+  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
+
+  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;
+  if(vendorlen>opb->storage-8)goto err_out;
+  vc->vendor=_ogg_calloc(vendorlen+1,1);
+  _v_readstring(opb,vc->vendor,vendorlen);
+  i=oggpack_read(opb,32);
+  if(i<0)goto err_out;
+  if(i>((opb->storage-oggpack_bytes(opb))>>2))goto err_out;
+  vc->comments=i;
+  vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
+  vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
+
+  for(i=0;i<vc->comments;i++){
+    int len=oggpack_read(opb,32);
+    if(len<0)goto err_out;
+    if(len>opb->storage-oggpack_bytes(opb))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;
+  if(ci->books<=0)goto err_out;
+  for(i=0;i<ci->books;i++){
+    ci->book_param[i]=vorbis_staticbook_unpack(opb);
+    if(!ci->book_param[i])goto err_out;
+  }
+
+  /* time backend settings; hooks are unused */
+  {
+    int times=oggpack_read(opb,6)+1;
+    if(times<=0)goto err_out;
+    for(i=0;i<times;i++){
+      int test=oggpack_read(opb,16);
+      if(test<0 || test>=VI_TIMEB)goto err_out;
+    }
+  }
+
+  /* floor backend settings */
+  ci->floors=oggpack_read(opb,6)+1;
+  if(ci->floors<=0)goto err_out;
+  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;
+  if(ci->residues<=0)goto err_out;
+  for(i=0;i<ci->residues;i++){
+    ci->residue_type[i]=oggpack_read(opb,16);
+    if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
+    ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
+    if(!ci->residue_param[i])goto err_out;
+  }
+
+  /* map backend settings */
+  ci->maps=oggpack_read(opb,6)+1;
+  if(ci->maps<=0)goto err_out;
+  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;
+  if(ci->modes<=0)goto err_out;
+  for(i=0;i<ci->modes;i++){
+    ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i]));
+    ci->mode_param[i]->blockflag=oggpack_read(opb,1);
+    ci->mode_param[i]->windowtype=oggpack_read(opb,16);
+    ci->mode_param[i]->transformtype=oggpack_read(opb,16);
+    ci->mode_param[i]->mapping=oggpack_read(opb,8);
+
+    if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
+    if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
+    if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
+    if(ci->mode_param[i]->mapping<0)goto err_out;
+  }
+
+  if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
+
+  return(0);
+ err_out:
+  vorbis_info_clear(vi);
+  return(OV_EBADHEADER);
+}
+
+/* Is this packet a vorbis ID header? */
+int vorbis_synthesis_idheader(ogg_packet *op){
+  oggpack_buffer opb;
+  char buffer[6];
+
+  if(op){
+    oggpack_readinit(&opb,op->packet,op->bytes);
+
+    if(!op->b_o_s)
+      return(0); /* Not the initial packet */
+
+    if(oggpack_read(&opb,8) != 1)
+      return 0; /* not an ID header */
+
+    memset(buffer,0,6);
+    _v_readstring(&opb,buffer,6);
+    if(memcmp(buffer,"vorbis",6))
+      return 0; /* not vorbis */
+
+    return 1;
+  }
+
+  return 0;
+}
+
+/* The Vorbis header is in three packets; the initial small packet in
+   the first page that identifies basic parameters, a second packet
+   with bitstream comments and a third packet that holds the
+   codebook. */
+
+int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
+  oggpack_buffer opb;
+
+  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", 6);
+
+  /* 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){
+  int bytes = strlen(ENCODE_VENDOR_STRING);
+
+  /* preamble */
+  oggpack_write(opb,0x03,8);
+  _v_writestring(opb,"vorbis", 6);
+
+  /* vendor */
+  oggpack_write(opb,bytes,32);
+  _v_writestring(opb,ENCODE_VENDOR_STRING, bytes);
+
+  /* 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], vc->comment_lengths[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", 6);
+
+  /* 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; hook placeholders */
+  oggpack_write(opb,0,6);
+  oggpack_write(opb,0,16);
+
+  /* floors */
+  oggpack_write(opb,ci->floors-1,6);
+  for(i=0;i<ci->floors;i++){
+    oggpack_write(opb,ci->floor_type[i],16);
+    if(_floor_P[ci->floor_type[i]]->pack)
+      _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
+    else
+      goto err_out;
+  }
+
+  /* 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_commentheader_out(vorbis_comment *vc,
+                                          ogg_packet *op){
+
+  oggpack_buffer opb;
+
+  oggpack_writeinit(&opb);
+  if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL;
+
+  op->packet = _ogg_malloc(oggpack_bytes(&opb));
+  memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
+
+  op->bytes=oggpack_bytes(&opb);
+  op->b_o_s=0;
+  op->e_o_s=0;
+  op->granulepos=0;
+  op->packetno=1;
+
+  return 0;
+}
+
+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;
+  private_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;
+  op->packetno=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;
+  op_comm->packetno=1;
+
+  /* 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;
+  op_code->packetno=2;
+
+  oggpack_writeclear(&opb);
+  return(0);
+ err_out:
+  memset(op,0,sizeof(*op));
+  memset(op_comm,0,sizeof(*op_comm));
+  memset(op_code,0,sizeof(*op_code));
+
+  if(b){
+    oggpack_writeclear(&opb);
+    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);
+}
+
+double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
+  if(granulepos == -1) return -1;
+
+  /* We're not guaranteed a 64 bit unsigned type everywhere, so we
+     have to put the unsigned granpo in a signed type. */
+  if(granulepos>=0){
+    return((double)granulepos/v->vi->rate);
+  }else{
+    ogg_int64_t granuleoff=0xffffffff;
+    granuleoff<<=31;
+    granuleoff|=0x7ffffffff;
+    return(((double)granulepos+2+granuleoff+granuleoff)/v->vi->rate);
+  }
+}
+
+const char *vorbis_version_string(void){
+  return GENERAL_VENDOR_STRING;
+}
--- libvorbis-1.3.2.orig/.pc/CVE-2017-14160--CVE-2018-10393.patch/lib/psy.c
+++ libvorbis-1.3.2/.pc/CVE-2017-14160--CVE-2018-10393.patch/lib/psy.c
@@ -0,0 +1,1203 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+ *                                                                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+ function: psychoacoustics not including preecho
+ last mod: $Id: psy.c 17569 2010-10-26 17:09:47Z xiphmont $
+
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "vorbis/codec.h"
+#include "codec_internal.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
+static const double stereo_threshholds[]={0.0, .5, 1.0, 1.5, 2.5, 4.5, 8.5, 16.5, 9e10};
+static const double stereo_threshholds_limited[]={0.0, .5, 1.0, 1.5, 2.0, 2.5, 4.5, 8.5, 9e10};
+
+vorbis_look_psy_global *_vp_global_look(vorbis_info *vi){
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy_global *gi=&ci->psy_g_param;
+  vorbis_look_psy_global *look=_ogg_calloc(1,sizeof(*look));
+
+  look->channels=vi->channels;
+
+  look->ampmax=-9999.;
+  look->gi=gi;
+  return(look);
+}
+
+void _vp_global_free(vorbis_look_psy_global *look){
+  if(look){
+    memset(look,0,sizeof(*look));
+    _ogg_free(look);
+  }
+}
+
+void _vi_gpsy_free(vorbis_info_psy_global *i){
+  if(i){
+    memset(i,0,sizeof(*i));
+    _ogg_free(i);
+  }
+}
+
+void _vi_psy_free(vorbis_info_psy *i){
+  if(i){
+    memset(i,0,sizeof(*i));
+    _ogg_free(i);
+  }
+}
+
+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 float ***setup_tone_curves(float curveatt_dB[P_BANDS],float binHz,int n,
+                                  float center_boost, float center_decay_rate){
+  int i,j,k,m;
+  float ath[EHMER_MAX];
+  float workc[P_BANDS][P_LEVELS][EHMER_MAX];
+  float athc[P_LEVELS][EHMER_MAX];
+  float *brute_buffer=alloca(n*sizeof(*brute_buffer));
+
+  float ***ret=_ogg_malloc(sizeof(*ret)*P_BANDS);
+
+  memset(workc,0,sizeof(workc));
+
+  for(i=0;i<P_BANDS;i++){
+    /* we add back in the ATH to avoid low level curves falling off to
+       -infinity and unnecessarily cutting off high level curves in the
+       curve limiting (last step). */
+
+    /* A half-band's settings must be valid over the whole band, and
+       it's better to mask too little than too much */
+    int ath_offset=i*4;
+    for(j=0;j<EHMER_MAX;j++){
+      float min=999.;
+      for(k=0;k<4;k++)
+        if(j+k+ath_offset<MAX_ATH){
+          if(min>ATH[j+k+ath_offset])min=ATH[j+k+ath_offset];
+        }else{
+          if(min>ATH[MAX_ATH-1])min=ATH[MAX_ATH-1];
+        }
+      ath[j]=min;
+    }
+
+    /* copy curves into working space, replicate the 50dB curve to 30
+       and 40, replicate the 100dB curve to 110 */
+    for(j=0;j<6;j++)
+      memcpy(workc[i][j+2],tonemasks[i][j],EHMER_MAX*sizeof(*tonemasks[i][j]));
+    memcpy(workc[i][0],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0]));
+    memcpy(workc[i][1],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0]));
+
+    /* apply centered curve boost/decay */
+    for(j=0;j<P_LEVELS;j++){
+      for(k=0;k<EHMER_MAX;k++){
+        float adj=center_boost+abs(EHMER_OFFSET-k)*center_decay_rate;
+        if(adj<0. && center_boost>0)adj=0.;
+        if(adj>0. && center_boost<0)adj=0.;
+        workc[i][j][k]+=adj;
+      }
+    }
+
+    /* normalize curves so the driving amplitude is 0dB */
+    /* make temp curves with the ATH overlayed */
+    for(j=0;j<P_LEVELS;j++){
+      attenuate_curve(workc[i][j],curveatt_dB[i]+100.-(j<2?2:j)*10.-P_LEVEL_0);
+      memcpy(athc[j],ath,EHMER_MAX*sizeof(**athc));
+      attenuate_curve(athc[j],+100.-j*10.f-P_LEVEL_0);
+      max_curve(athc[j],workc[i][j]);
+    }
+
+    /* 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(athc[j],athc[j-1]);
+      min_curve(workc[i][j],athc[j]);
+    }
+  }
+
+  for(i=0;i<P_BANDS;i++){
+    int hi_curve,lo_curve,bin;
+    ret[i]=_ogg_malloc(sizeof(**ret)*P_LEVELS);
+
+    /* low frequency curves are measured with greater resolution than
+       the MDCT/FFT will actually give us; we want the curve applied
+       to the tone data to be pessimistic and thus apply the minimum
+       masking possible for a given bin.  That means that a single bin
+       could span more than one octave and that the curve will be a
+       composite of multiple octaves.  It also may mean that a single
+       bin may span > an eighth of an octave and that the eighth
+       octave values may also be composited. */
+
+    /* which octave curves will we be compositing? */
+    bin=floor(fromOC(i*.5)/binHz);
+    lo_curve=  ceil(toOC(bin*binHz+1)*2);
+    hi_curve=  floor(toOC((bin+1)*binHz)*2);
+    if(lo_curve>i)lo_curve=i;
+    if(lo_curve<0)lo_curve=0;
+    if(hi_curve>=P_BANDS)hi_curve=P_BANDS-1;
+
+    for(m=0;m<P_LEVELS;m++){
+      ret[i][m]=_ogg_malloc(sizeof(***ret)*(EHMER_MAX+2));
+
+      for(j=0;j<n;j++)brute_buffer[j]=999.;
+
+      /* render the curve into bins, then pull values back into curve.
+         The point is that any inherent subsampling aliasing results in
+         a safe minimum */
+      for(k=lo_curve;k<=hi_curve;k++){
+        int l=0;
+
+        for(j=0;j<EHMER_MAX;j++){
+          int lo_bin= fromOC(j*.125+k*.5-2.0625)/binHz;
+          int hi_bin= fromOC(j*.125+k*.5-1.9375)/binHz+1;
+
+          if(lo_bin<0)lo_bin=0;
+          if(lo_bin>n)lo_bin=n;
+          if(lo_bin<l)l=lo_bin;
+          if(hi_bin<0)hi_bin=0;
+          if(hi_bin>n)hi_bin=n;
+
+          for(;l<hi_bin && l<n;l++)
+            if(brute_buffer[l]>workc[k][m][j])
+              brute_buffer[l]=workc[k][m][j];
+        }
+
+        for(;l<n;l++)
+          if(brute_buffer[l]>workc[k][m][EHMER_MAX-1])
+            brute_buffer[l]=workc[k][m][EHMER_MAX-1];
+
+      }
+
+      /* be equally paranoid about being valid up to next half ocatve */
+      if(i+1<P_BANDS){
+        int l=0;
+        k=i+1;
+        for(j=0;j<EHMER_MAX;j++){
+          int lo_bin= fromOC(j*.125+i*.5-2.0625)/binHz;
+          int hi_bin= fromOC(j*.125+i*.5-1.9375)/binHz+1;
+
+          if(lo_bin<0)lo_bin=0;
+          if(lo_bin>n)lo_bin=n;
+          if(lo_bin<l)l=lo_bin;
+          if(hi_bin<0)hi_bin=0;
+          if(hi_bin>n)hi_bin=n;
+
+          for(;l<hi_bin && l<n;l++)
+            if(brute_buffer[l]>workc[k][m][j])
+              brute_buffer[l]=workc[k][m][j];
+        }
+
+        for(;l<n;l++)
+          if(brute_buffer[l]>workc[k][m][EHMER_MAX-1])
+            brute_buffer[l]=workc[k][m][EHMER_MAX-1];
+
+      }
+
+
+      for(j=0;j<EHMER_MAX;j++){
+        int bin=fromOC(j*.125+i*.5-2.)/binHz;
+        if(bin<0){
+          ret[i][m][j+2]=-999.;
+        }else{
+          if(bin>=n){
+            ret[i][m][j+2]=-999.;
+          }else{
+            ret[i][m][j+2]=brute_buffer[bin];
+          }
+        }
+      }
+
+      /* add fenceposts */
+      for(j=0;j<EHMER_OFFSET;j++)
+        if(ret[i][m][j+2]>-200.f)break;
+      ret[i][m][0]=j;
+
+      for(j=EHMER_MAX-1;j>EHMER_OFFSET+1;j--)
+        if(ret[i][m][j+2]>-200.f)
+          break;
+      ret[i][m][1]=j;
+
+    }
+  }
+
+  return(ret);
+}
+
+void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,
+                  vorbis_info_psy_global *gi,int n,long rate){
+  long i,j,lo=-99,hi=1;
+  long maxoc;
+  memset(p,0,sizeof(*p));
+
+  p->eighth_octave_lines=gi->eighth_octave_lines;
+  p->shiftoc=rint(log(gi->eighth_octave_lines*8.f)/log(2.f))-1;
+
+  p->firstoc=toOC(.25f*rate*.5/n)*(1<<(p->shiftoc+1))-gi->eighth_octave_lines;
+  maxoc=toOC((n+.25f)*rate*.5/n)*(1<<(p->shiftoc+1))+.5f;
+  p->total_octave_lines=maxoc-p->firstoc+1;
+  p->ath=_ogg_malloc(n*sizeof(*p->ath));
+
+  p->octave=_ogg_malloc(n*sizeof(*p->octave));
+  p->bark=_ogg_malloc(n*sizeof(*p->bark));
+  p->vi=vi;
+  p->n=n;
+  p->rate=rate;
+
+  /* AoTuV HF weighting */
+  p->m_val = 1.;
+  if(rate < 26000) p->m_val = 0;
+  else if(rate < 38000) p->m_val = .94;   /* 32kHz */
+  else if(rate > 46000) p->m_val = 1.275; /* 48kHz */
+
+  /* set up the lookups for a given blocksize and sample rate */
+
+  for(i=0,j=0;i<MAX_ATH-1;i++){
+    int endpos=rint(fromOC((i+1)*.125-2.)*2*n/rate);
+    float base=ATH[i];
+    if(j<endpos){
+      float delta=(ATH[i+1]-base)/(endpos-j);
+      for(;j<endpos && j<n;j++){
+        p->ath[j]=base+100.;
+        base+=delta;
+      }
+    }
+  }
+
+  for(;j<n;j++){
+    p->ath[j]=p->ath[j-1];
+  }
+
+  for(i=0;i<n;i++){
+    float bark=toBARK(rate/(2*n)*i);
+
+    for(;lo+vi->noisewindowlomin<i &&
+          toBARK(rate/(2*n)*lo)<(bark-vi->noisewindowlo);lo++);
+
+    for(;hi<=n && (hi<i+vi->noisewindowhimin ||
+          toBARK(rate/(2*n)*hi)<(bark+vi->noisewindowhi));hi++);
+
+    p->bark[i]=((lo-1)<<16)+(hi-1);
+
+  }
+
+  for(i=0;i<n;i++)
+    p->octave[i]=toOC((i+.25f)*.5*rate/n)*(1<<(p->shiftoc+1))+.5f;
+
+  p->tonecurves=setup_tone_curves(vi->toneatt,rate*.5/n,n,
+                                  vi->tone_centerboost,vi->tone_decay);
+
+  /* set up rolling noise median */
+  p->noiseoffset=_ogg_malloc(P_NOISECURVES*sizeof(*p->noiseoffset));
+  for(i=0;i<P_NOISECURVES;i++)
+    p->noiseoffset[i]=_ogg_malloc(n*sizeof(**p->noiseoffset));
+
+  for(i=0;i<n;i++){
+    float halfoc=toOC((i+.5)*rate/(2.*n))*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;
+
+    for(j=0;j<P_NOISECURVES;j++)
+      p->noiseoffset[j][i]=
+        p->vi->noiseoff[j][inthalfoc]*(1.-del) +
+        p->vi->noiseoff[j][inthalfoc+1]*del;
+
+  }
+#if 0
+  {
+    static int ls=0;
+    _analysis_output_always("noiseoff0",ls,p->noiseoffset[0],n,1,0,0);
+    _analysis_output_always("noiseoff1",ls,p->noiseoffset[1],n,1,0,0);
+    _analysis_output_always("noiseoff2",ls++,p->noiseoffset[2],n,1,0,0);
+  }
+#endif
+}
+
+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->tonecurves);
+    }
+    if(p->noiseoffset){
+      for(i=0;i<P_NOISECURVES;i++){
+        _ogg_free(p->noiseoffset[i]);
+      }
+      _ogg_free(p->noiseoffset);
+    }
+    memset(p,0,sizeof(*p));
+  }
+}
+
+/* octave/(8*eighth_octave_lines) x scale and dB y scale */
+static void seed_curve(float *seed,
+                       const float **curves,
+                       float amp,
+                       int oc, int n,
+                       int linesper,float dBoffset){
+  int i,post1;
+  int seedptr;
+  const float *posts,*curve;
+
+  int choice=(int)((amp+dBoffset-P_LEVEL_0)*.1f);
+  choice=max(choice,0);
+  choice=min(choice,P_LEVELS-1);
+  posts=curves[choice];
+  curve=posts+2;
+  post1=(int)posts[1];
+  seedptr=oc+(posts[0]-EHMER_OFFSET)*linesper-(linesper>>1);
+
+  for(i=posts[0];i<post1;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_loop(vorbis_look_psy *p,
+                      const float ***curves,
+                      const float *f,
+                      const float *flr,
+                      float *seed,
+                      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];
+    long oc=p->octave[i];
+    while(i+1<n && p->octave[i+1]==oc){
+      i++;
+      if(f[i]>max)max=f[i];
+    }
+
+    if(max+6.f>flr[i]){
+      oc=oc>>p->shiftoc;
+
+      if(oc>=P_BANDS)oc=P_BANDS-1;
+      if(oc<0)oc=0;
+
+      seed_curve(seed,
+                 curves[oc],
+                 max,
+                 p->octave[i]-p->firstoc,
+                 p->total_octave_lines,
+                 p->eighth_octave_lines,
+                 dBoffset);
+    }
+  }
+}
+
+static void seed_chase(float *seeds, int linesper, long n){
+  long  *posstack=alloca(n*sizeof(*posstack));
+  float *ampstack=alloca(n*sizeof(*ampstack));
+  long   stack=0;
+  long   pos=0;
+  long   i;
+
+  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 */
+
+  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];
+  }
+
+  /* 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 ;-) */
+
+}
+
+/* bleaugh, this is more complicated than it needs to be */
+#include<stdio.h>
+static void max_seeds(vorbis_look_psy *p,
+                      float *seed,
+                      float *flr){
+  long   n=p->total_octave_lines;
+  int    linesper=p->eighth_octave_lines;
+  long   linpos=0;
+  long   pos;
+
+  seed_chase(seed,linesper,n); /* for masking */
+
+  pos=p->octave[0]-p->firstoc-(linesper>>1);
+
+  while(linpos+1<p->n){
+    float minV=seed[pos];
+    long end=((p->octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc;
+    if(minV>p->vi->tone_abs_limit)minV=p->vi->tone_abs_limit;
+    while(pos+1<=end){
+      pos++;
+      if((seed[pos]>NEGINF && seed[pos]<minV) || minV==NEGINF)
+        minV=seed[pos];
+    }
+
+    end=pos+p->firstoc;
+    for(;linpos<p->n && p->octave[linpos]<=end;linpos++)
+      if(flr[linpos]<minV)flr[linpos]=minV;
+  }
+
+  {
+    float minV=seed[p->total_octave_lines-1];
+    for(;linpos<p->n;linpos++)
+      if(flr[linpos]<minV)flr[linpos]=minV;
+  }
+
+}
+
+static void bark_noise_hybridmp(int n,const long *b,
+                                const float *f,
+                                float *noise,
+                                const float offset,
+                                const int fixed){
+
+  float *N=alloca(n*sizeof(*N));
+  float *X=alloca(n*sizeof(*N));
+  float *XX=alloca(n*sizeof(*N));
+  float *Y=alloca(n*sizeof(*N));
+  float *XY=alloca(n*sizeof(*N));
+
+  float tN, tX, tXX, tY, tXY;
+  int i;
+
+  int lo, hi;
+  float R=0.f;
+  float A=0.f;
+  float B=0.f;
+  float D=1.f;
+  float w, x, y;
+
+  tN = tX = tXX = tY = tXY = 0.f;
+
+  y = f[0] + offset;
+  if (y < 1.f) y = 1.f;
+
+  w = y * y * .5;
+
+  tN += w;
+  tX += w;
+  tY += w * y;
+
+  N[0] = tN;
+  X[0] = tX;
+  XX[0] = tXX;
+  Y[0] = tY;
+  XY[0] = tXY;
+
+  for (i = 1, x = 1.f; i < n; i++, x += 1.f) {
+
+    y = f[i] + offset;
+    if (y < 1.f) y = 1.f;
+
+    w = y * y;
+
+    tN += w;
+    tX += w * x;
+    tXX += w * x * x;
+    tY += w * y;
+    tXY += w * x * y;
+
+    N[i] = tN;
+    X[i] = tX;
+    XX[i] = tXX;
+    Y[i] = tY;
+    XY[i] = tXY;
+  }
+
+  for (i = 0, x = 0.f;; i++, x += 1.f) {
+
+    lo = b[i] >> 16;
+    if( lo>=0 ) break;
+    hi = b[i] & 0xffff;
+
+    tN = N[hi] + N[-lo];
+    tX = X[hi] - X[-lo];
+    tXX = XX[hi] + XX[-lo];
+    tY = Y[hi] + Y[-lo];
+    tXY = XY[hi] - XY[-lo];
+
+    A = tY * tXX - tX * tXY;
+    B = tN * tXY - tX * tY;
+    D = tN * tXX - tX * tX;
+    R = (A + x * B) / D;
+    if (R < 0.f)
+      R = 0.f;
+
+    noise[i] = R - offset;
+  }
+
+  for ( ;; i++, x += 1.f) {
+
+    lo = b[i] >> 16;
+    hi = b[i] & 0xffff;
+    if(hi>=n)break;
+
+    tN = N[hi] - N[lo];
+    tX = X[hi] - X[lo];
+    tXX = XX[hi] - XX[lo];
+    tY = Y[hi] - Y[lo];
+    tXY = XY[hi] - XY[lo];
+
+    A = tY * tXX - tX * tXY;
+    B = tN * tXY - tX * tY;
+    D = tN * tXX - tX * tX;
+    R = (A + x * B) / D;
+    if (R < 0.f) R = 0.f;
+
+    noise[i] = R - offset;
+  }
+  for ( ; i < n; i++, x += 1.f) {
+
+    R = (A + x * B) / D;
+    if (R < 0.f) R = 0.f;
+
+    noise[i] = R - offset;
+  }
+
+  if (fixed <= 0) return;
+
+  for (i = 0, x = 0.f;; i++, x += 1.f) {
+    hi = i + fixed / 2;
+    lo = hi - fixed;
+    if(lo>=0)break;
+
+    tN = N[hi] + N[-lo];
+    tX = X[hi] - X[-lo];
+    tXX = XX[hi] + XX[-lo];
+    tY = Y[hi] + Y[-lo];
+    tXY = XY[hi] - XY[-lo];
+
+
+    A = tY * tXX - tX * tXY;
+    B = tN * tXY - tX * tY;
+    D = tN * tXX - tX * tX;
+    R = (A + x * B) / D;
+
+    if (R - offset < noise[i]) noise[i] = R - offset;
+  }
+  for ( ;; i++, x += 1.f) {
+
+    hi = i + fixed / 2;
+    lo = hi - fixed;
+    if(hi>=n)break;
+
+    tN = N[hi] - N[lo];
+    tX = X[hi] - X[lo];
+    tXX = XX[hi] - XX[lo];
+    tY = Y[hi] - Y[lo];
+    tXY = XY[hi] - XY[lo];
+
+    A = tY * tXX - tX * tXY;
+    B = tN * tXY - tX * tY;
+    D = tN * tXX - tX * tX;
+    R = (A + x * B) / D;
+
+    if (R - offset < noise[i]) noise[i] = R - offset;
+  }
+  for ( ; i < n; i++, x += 1.f) {
+    R = (A + x * B) / D;
+    if (R - offset < noise[i]) noise[i] = R - offset;
+  }
+}
+
+void _vp_noisemask(vorbis_look_psy *p,
+                   float *logmdct,
+                   float *logmask){
+
+  int i,n=p->n;
+  float *work=alloca(n*sizeof(*work));
+
+  bark_noise_hybridmp(n,p->bark,logmdct,logmask,
+                      140.,-1);
+
+  for(i=0;i<n;i++)work[i]=logmdct[i]-logmask[i];
+
+  bark_noise_hybridmp(n,p->bark,work,logmask,0.,
+                      p->vi->noisewindowfixed);
+
+  for(i=0;i<n;i++)work[i]=logmdct[i]-work[i];
+
+#if 0
+  {
+    static int seq=0;
+
+    float work2[n];
+    for(i=0;i<n;i++){
+      work2[i]=logmask[i]+work[i];
+    }
+
+    if(seq&1)
+      _analysis_output("median2R",seq/2,work,n,1,0,0);
+    else
+      _analysis_output("median2L",seq/2,work,n,1,0,0);
+
+    if(seq&1)
+      _analysis_output("envelope2R",seq/2,work2,n,1,0,0);
+    else
+      _analysis_output("envelope2L",seq/2,work2,n,1,0,0);
+    seq++;
+  }
+#endif
+
+  for(i=0;i<n;i++){
+    int dB=logmask[i]+.5;
+    if(dB>=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1;
+    if(dB<0)dB=0;
+    logmask[i]= work[i]+p->vi->noisecompand[dB];
+  }
+
+}
+
+void _vp_tonemask(vorbis_look_psy *p,
+                  float *logfft,
+                  float *logmask,
+                  float global_specmax,
+                  float local_specmax){
+
+  int i,n=p->n;
+
+  float *seed=alloca(sizeof(*seed)*p->total_octave_lines);
+  float att=local_specmax+p->vi->ath_adjatt;
+  for(i=0;i<p->total_octave_lines;i++)seed[i]=NEGINF;
+
+  /* set the ATH (floating below localmax, not global max by a
+     specified att) */
+  if(att<p->vi->ath_maxatt)att=p->vi->ath_maxatt;
+
+  for(i=0;i<n;i++)
+    logmask[i]=p->ath[i]+att;
+
+  /* tone masking */
+  seed_loop(p,(const float ***)p->tonecurves,logfft,logmask,seed,global_specmax);
+  max_seeds(p,seed,logmask);
+
+}
+
+void _vp_offset_and_mix(vorbis_look_psy *p,
+                        float *noise,
+                        float *tone,
+                        int offset_select,
+                        float *logmask,
+                        float *mdct,
+                        float *logmdct){
+  int i,n=p->n;
+  float de, coeffi, cx;/* AoTuV */
+  float toneatt=p->vi->tone_masteratt[offset_select];
+
+  cx = p->m_val;
+
+  for(i=0;i<n;i++){
+    float val= noise[i]+p->noiseoffset[offset_select][i];
+    if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp;
+    logmask[i]=max(val,tone[i]+toneatt);
+
+
+    /* AoTuV */
+    /** @ M1 **
+        The following codes improve a noise problem.
+        A fundamental idea uses the value of masking and carries out
+        the relative compensation of the MDCT.
+        However, this code is not perfect and all noise problems cannot be solved.
+        by Aoyumi @ 2004/04/18
+    */
+
+    if(offset_select == 1) {
+      coeffi = -17.2;       /* coeffi is a -17.2dB threshold */
+      val = val - logmdct[i];  /* val == mdct line value relative to floor in dB */
+
+      if(val > coeffi){
+        /* mdct value is > -17.2 dB below floor */
+
+        de = 1.0-((val-coeffi)*0.005*cx);
+        /* pro-rated attenuation:
+           -0.00 dB boost if mdct value is -17.2dB (relative to floor)
+           -0.77 dB boost if mdct value is 0dB (relative to floor)
+           -1.64 dB boost if mdct value is +17.2dB (relative to floor)
+           etc... */
+
+        if(de < 0) de = 0.0001;
+      }else
+        /* mdct value is <= -17.2 dB below floor */
+
+        de = 1.0-((val-coeffi)*0.0003*cx);
+      /* pro-rated attenuation:
+         +0.00 dB atten if mdct value is -17.2dB (relative to floor)
+         +0.45 dB atten if mdct value is -34.4dB (relative to floor)
+         etc... */
+
+      mdct[i] *= de;
+
+    }
+  }
+}
+
+float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd){
+  vorbis_info *vi=vd->vi;
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy_global *gi=&ci->psy_g_param;
+
+  int n=ci->blocksizes[vd->W]/2;
+  float secs=(float)n/vi->rate;
+
+  amp+=secs*gi->ampmax_att_per_sec;
+  if(amp<-9999)amp=-9999;
+  return(amp);
+}
+
+static float FLOOR1_fromdB_LOOKUP[256]={
+  1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F,
+  1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F,
+  1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F,
+  2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F,
+  2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F,
+  3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F,
+  4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F,
+  6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F,
+  7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F,
+  1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F,
+  1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F,
+  1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F,
+  2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F,
+  2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F,
+  3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F,
+  4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F,
+  5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F,
+  7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F,
+  9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F,
+  1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F,
+  1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F,
+  2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F,
+  2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F,
+  3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F,
+  4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F,
+  5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F,
+  7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F,
+  9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F,
+  0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F,
+  0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F,
+  0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F,
+  0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F,
+  0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F,
+  0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F,
+  0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F,
+  0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F,
+  0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F,
+  0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F,
+  0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F,
+  0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F,
+  0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F,
+  0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F,
+  0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F,
+  0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F,
+  0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F,
+  0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F,
+  0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F,
+  0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F,
+  0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F,
+  0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F,
+  0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F,
+  0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F,
+  0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F,
+  0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F,
+  0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F,
+  0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F,
+  0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F,
+  0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F,
+  0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F,
+  0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F,
+  0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F,
+  0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F,
+  0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F,
+  0.82788260F, 0.88168307F, 0.9389798F, 1.F,
+};
+
+/* this is for per-channel noise normalization */
+static int apsort(const void *a, const void *b){
+  float f1=**(float**)a;
+  float f2=**(float**)b;
+  return (f1<f2)-(f1>f2);
+}
+
+static void flag_lossless(int limit, float prepoint, float postpoint, float *mdct,
+                         float *floor, int *flag, int i, int jn){
+  int j;
+  for(j=0;j<jn;j++){
+    float point = j>=limit-i ? postpoint : prepoint;
+    float r = fabs(mdct[j])/floor[j];
+    if(r<point)
+      flag[j]=0;
+    else
+      flag[j]=1;
+  }
+}
+
+/* Overload/Side effect: On input, the *q vector holds either the
+   quantized energy (for elements with the flag set) or the absolute
+   values of the *r vector (for elements with flag unset).  On output,
+   *q holds the quantized energy for all elements */
+static float noise_normalize(vorbis_look_psy *p, int limit, float *r, float *q, float *f, int *flags, float acc, int i, int n, int *out){
+
+  vorbis_info_psy *vi=p->vi;
+  float **sort = alloca(n*sizeof(*sort));
+  int j,count=0;
+  int start = (vi->normal_p ? vi->normal_start-i : n);
+  if(start>n)start=n;
+
+  /* force classic behavior where only energy in the current band is considered */
+  acc=0.f;
+
+  /* still responsible for populating *out where noise norm not in
+     effect.  There's no need to [re]populate *q in these areas */
+  for(j=0;j<start;j++){
+    if(!flags || !flags[j]){ /* lossless coupling already quantized.
+                                Don't touch; requantizing based on
+                                energy would be incorrect. */
+      float ve = q[j]/f[j];
+      if(r[j]<0)
+        out[j] = -rint(sqrt(ve));
+      else
+        out[j] = rint(sqrt(ve));
+    }
+  }
+
+  /* sort magnitudes for noise norm portion of partition */
+  for(;j<n;j++){
+    if(!flags || !flags[j]){ /* can't noise norm elements that have
+                                already been loslessly coupled; we can
+                                only account for their energy error */
+      float ve = q[j]/f[j];
+      /* Despite all the new, more capable coupling code, for now we
+         implement noise norm as it has been up to this point. Only
+         consider promotions to unit magnitude from 0.  In addition
+         the only energy error counted is quantizations to zero. */
+      /* also-- the original point code only applied noise norm at > pointlimit */
+      if(ve<.25f && (!flags || j>=limit-i)){
+        acc += ve;
+        sort[count++]=q+j; /* q is fabs(r) for unflagged element */
+      }else{
+        /* For now: no acc adjustment for nonzero quantization.  populate *out and q as this value is final. */
+        if(r[j]<0)
+          out[j] = -rint(sqrt(ve));
+        else
+          out[j] = rint(sqrt(ve));
+        q[j] = out[j]*out[j]*f[j];
+      }
+    }/* else{
+        again, no energy adjustment for error in nonzero quant-- for now
+        }*/
+  }
+
+  if(count){
+    /* noise norm to do */
+    qsort(sort,count,sizeof(*sort),apsort);
+    for(j=0;j<count;j++){
+      int k=sort[j]-q;
+      if(acc>=vi->normal_thresh){
+        out[k]=unitnorm(r[k]);
+        acc-=1.f;
+        q[k]=f[k];
+      }else{
+        out[k]=0;
+        q[k]=0.f;
+      }
+    }
+  }
+
+  return acc;
+}
+
+/* Noise normalization, quantization and coupling are not wholly
+   seperable processes in depth>1 coupling. */
+void _vp_couple_quantize_normalize(int blobno,
+                                   vorbis_info_psy_global *g,
+                                   vorbis_look_psy *p,
+                                   vorbis_info_mapping0 *vi,
+                                   float **mdct,
+                                   int   **iwork,
+                                   int    *nonzero,
+                                   int     sliding_lowpass,
+                                   int     ch){
+
+  int i;
+  int n = p->n;
+  int partition=(p->vi->normal_p ? p->vi->normal_partition : 16);
+  int limit = g->coupling_pointlimit[p->vi->blockflag][blobno];
+  float prepoint=stereo_threshholds[g->coupling_prepointamp[blobno]];
+  float postpoint=stereo_threshholds[g->coupling_postpointamp[blobno]];
+  float de=0.1*p->m_val; /* a blend of the AoTuV M2 and M3 code here and below */
+
+  /* mdct is our raw mdct output, floor not removed. */
+  /* inout passes in the ifloor, passes back quantized result */
+
+  /* unquantized energy (negative indicates amplitude has negative sign) */
+  float **raw = alloca(ch*sizeof(*raw));
+
+  /* dual pupose; quantized energy (if flag set), othersize fabs(raw) */
+  float **quant = alloca(ch*sizeof(*quant));
+
+  /* floor energy */
+  float **floor = alloca(ch*sizeof(*floor));
+
+  /* flags indicating raw/quantized status of elements in raw vector */
+  int   **flag  = alloca(ch*sizeof(*flag));
+
+  /* non-zero flag working vector */
+  int    *nz    = alloca(ch*sizeof(*nz));
+
+  /* energy surplus/defecit tracking */
+  float  *acc   = alloca((ch+vi->coupling_steps)*sizeof(*acc));
+
+  /* The threshold of a stereo is changed with the size of n */
+  if(n > 1000)
+    postpoint=stereo_threshholds_limited[g->coupling_postpointamp[blobno]];
+
+  raw[0]   = alloca(ch*partition*sizeof(**raw));
+  quant[0] = alloca(ch*partition*sizeof(**quant));
+  floor[0] = alloca(ch*partition*sizeof(**floor));
+  flag[0]  = alloca(ch*partition*sizeof(**flag));
+
+  for(i=1;i<ch;i++){
+    raw[i]   = &raw[0][partition*i];
+    quant[i] = &quant[0][partition*i];
+    floor[i] = &floor[0][partition*i];
+    flag[i]  = &flag[0][partition*i];
+  }
+  for(i=0;i<ch+vi->coupling_steps;i++)
+    acc[i]=0.f;
+
+  for(i=0;i<n;i+=partition){
+    int k,j,jn = partition > n-i ? n-i : partition;
+    int step,track = 0;
+
+    memcpy(nz,nonzero,sizeof(*nz)*ch);
+
+    /* prefill */
+    memset(flag[0],0,ch*partition*sizeof(**flag));
+    for(k=0;k<ch;k++){
+      int *iout = &iwork[k][i];
+      if(nz[k]){
+
+        for(j=0;j<jn;j++)
+          floor[k][j] = FLOOR1_fromdB_LOOKUP[iout[j]];
+
+        flag_lossless(limit,prepoint,postpoint,&mdct[k][i],floor[k],flag[k],i,jn);
+
+        for(j=0;j<jn;j++){
+          quant[k][j] = raw[k][j] = mdct[k][i+j]*mdct[k][i+j];
+          if(mdct[k][i+j]<0.f) raw[k][j]*=-1.f;
+          floor[k][j]*=floor[k][j];
+        }
+
+        acc[track]=noise_normalize(p,limit,raw[k],quant[k],floor[k],NULL,acc[track],i,jn,iout);
+
+      }else{
+        for(j=0;j<jn;j++){
+          floor[k][j] = 1e-10f;
+          raw[k][j] = 0.f;
+          quant[k][j] = 0.f;
+          flag[k][j] = 0;
+          iout[j]=0;
+        }
+        acc[track]=0.f;
+      }
+      track++;
+    }
+
+    /* coupling */
+    for(step=0;step<vi->coupling_steps;step++){
+      int Mi = vi->coupling_mag[step];
+      int Ai = vi->coupling_ang[step];
+      int *iM = &iwork[Mi][i];
+      int *iA = &iwork[Ai][i];
+      float *reM = raw[Mi];
+      float *reA = raw[Ai];
+      float *qeM = quant[Mi];
+      float *qeA = quant[Ai];
+      float *floorM = floor[Mi];
+      float *floorA = floor[Ai];
+      int *fM = flag[Mi];
+      int *fA = flag[Ai];
+
+      if(nz[Mi] || nz[Ai]){
+        nz[Mi] = nz[Ai] = 1;
+
+        for(j=0;j<jn;j++){
+
+          if(j<sliding_lowpass-i){
+            if(fM[j] || fA[j]){
+              /* lossless coupling */
+
+              reM[j] = fabs(reM[j])+fabs(reA[j]);
+              qeM[j] = qeM[j]+qeA[j];
+              fM[j]=fA[j]=1;
+
+              /* couple iM/iA */
+              {
+                int A = iM[j];
+                int B = iA[j];
+
+                if(abs(A)>abs(B)){
+                  iA[j]=(A>0?A-B:B-A);
+                }else{
+                  iA[j]=(B>0?A-B:B-A);
+                  iM[j]=B;
+                }
+
+                /* collapse two equivalent tuples to one */
+                if(iA[j]>=abs(iM[j])*2){
+                  iA[j]= -iA[j];
+                  iM[j]= -iM[j];
+                }
+
+              }
+
+            }else{
+              /* lossy (point) coupling */
+              if(j<limit-i){
+                /* dipole */
+                reM[j] += reA[j];
+                qeM[j] = fabs(reM[j]);
+              }else{
+                /* AoTuV */
+                /** @ M2 **
+                    The boost problem by the combination of noise normalization and point stereo is eased.
+                    However, this is a temporary patch.
+                    by Aoyumi @ 2004/04/18
+                */
+                /*float derate = (1.0 - de*((float)(j-limit+i) / (float)(n-limit)));
+                /* elliptical 
+                if(reM[j]+reA[j]<0){
+                  reM[j] = - (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate);
+                }else{
+                  reM[j] =   (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate);
+                  }*/
+
+                /* elliptical */
+                if(reM[j]+reA[j]<0){
+                  reM[j] = - (qeM[j] = fabs(reM[j])+fabs(reA[j]));
+                }else{
+                  reM[j] =   (qeM[j] = fabs(reM[j])+fabs(reA[j]));
+                }
+
+
+              }
+              reA[j]=qeA[j]=0.f;
+              fA[j]=1;
+              iA[j]=0;
+            }
+          }
+          floorM[j]=floorA[j]=floorM[j]+floorA[j];
+        }
+        /* normalize the resulting mag vector */
+        acc[track]=noise_normalize(p,limit,raw[Mi],quant[Mi],floor[Mi],flag[Mi],acc[track],i,jn,iM);
+        track++;
+      }
+    }
+  }
+
+  for(i=0;i<vi->coupling_steps;i++){
+    /* make sure coupling a zero and a nonzero channel results in two
+       nonzero channels. */
+    if(nonzero[vi->coupling_mag[i]] ||
+       nonzero[vi->coupling_ang[i]]){
+      nonzero[vi->coupling_mag[i]]=1;
+      nonzero[vi->coupling_ang[i]]=1;
+    }
+  }
+}
--- libvorbis-1.3.2.orig/.pc/CVE-2017-14632.patch/lib/info.c
+++ libvorbis-1.3.2/.pc/CVE-2017-14632.patch/lib/info.c
@@ -0,0 +1,664 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+ *                                                                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+ function: maintain the info structure, info <-> header packets
+ last mod: $Id: info.c 17584 2010-11-01 19:26:16Z xiphmont $
+
+ ********************************************************************/
+
+/* 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 "codec_internal.h"
+#include "codebook.h"
+#include "registry.h"
+#include "window.h"
+#include "psy.h"
+#include "misc.h"
+#include "os.h"
+
+#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.2"
+#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20101101 (Schaufenugget)"
+
+/* helpers */
+static int ilog2(unsigned int v){
+  int ret=0;
+  if(v)--v;
+  while(v){
+    ret++;
+    v>>=1;
+  }
+  return(ret);
+}
+
+static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){
+
+  while(bytes--){
+    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(*vc));
+}
+
+void vorbis_comment_add(vorbis_comment *vc,const char *comment){
+  vc->user_comments=_ogg_realloc(vc->user_comments,
+                            (vc->comments+2)*sizeof(*vc->user_comments));
+  vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
+                                  (vc->comments+2)*sizeof(*vc->comment_lengths));
+  vc->comment_lengths[vc->comments]=strlen(comment);
+  vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
+  strcpy(vc->user_comments[vc->comments], comment);
+  vc->comments++;
+  vc->user_comments[vc->comments]=NULL;
+}
+
+void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const 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, const 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, const 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;
+    if(vc->user_comments){
+      for(i=0;i<vc->comments;i++)
+        if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
+      _ogg_free(vc->user_comments);
+    }
+    if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
+    if(vc->vendor)_ogg_free(vc->vendor);
+    memset(vc,0,sizeof(*vc));
+  }
+}
+
+/* blocksize 0 is guaranteed to be short, 1 is guaranteed to be long.
+   They may be equal, but short will never ge greater than long */
+int vorbis_info_blocksize(vorbis_info *vi,int zo){
+  codec_setup_info *ci = vi->codec_setup;
+  return ci ? ci->blocksizes[zo] : -1;
+}
+
+/* used by synthesis, which has a full, alloced vi */
+void vorbis_info_init(vorbis_info *vi){
+  memset(vi,0,sizeof(*vi));
+  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 */
+      if(ci->map_param[i]) /* this may be cleaning up an aborted
+                              unpack, in which case the below type
+                              cannot be trusted */
+        _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
+
+    for(i=0;i<ci->floors;i++) /* unpack does the range checking */
+      if(ci->floor_param[i]) /* this may be cleaning up an aborted
+                                unpack, in which case the below type
+                                cannot be trusted */
+        _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
+
+    for(i=0;i<ci->residues;i++) /* unpack does the range checking */
+      if(ci->residue_param[i]) /* this may be cleaning up an aborted
+                                  unpack, in which case the below type
+                                  cannot be trusted */
+        _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
+
+    for(i=0;i<ci->books;i++){
+      if(ci->book_param[i]){
+        /* knows if the book was not alloced */
+        vorbis_staticbook_destroy(ci->book_param[i]);
+      }
+      if(ci->fullbooks)
+        vorbis_book_clear(ci->fullbooks+i);
+    }
+    if(ci->fullbooks)
+        _ogg_free(ci->fullbooks);
+
+    for(i=0;i<ci->psys;i++)
+      _vi_psy_free(ci->psy_param[i]);
+
+    _ogg_free(ci);
+  }
+
+  memset(vi,0,sizeof(*vi));
+}
+
+/* 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]<64)goto err_out;
+  if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
+  if(ci->blocksizes[1]>8192)goto err_out;
+
+  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
+
+  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;
+  if(vendorlen>opb->storage-8)goto err_out;
+  vc->vendor=_ogg_calloc(vendorlen+1,1);
+  _v_readstring(opb,vc->vendor,vendorlen);
+  i=oggpack_read(opb,32);
+  if(i<0)goto err_out;
+  if(i>((opb->storage-oggpack_bytes(opb))>>2))goto err_out;
+  vc->comments=i;
+  vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
+  vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
+
+  for(i=0;i<vc->comments;i++){
+    int len=oggpack_read(opb,32);
+    if(len<0)goto err_out;
+    if(len>opb->storage-oggpack_bytes(opb))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;
+  if(ci->books<=0)goto err_out;
+  for(i=0;i<ci->books;i++){
+    ci->book_param[i]=vorbis_staticbook_unpack(opb);
+    if(!ci->book_param[i])goto err_out;
+  }
+
+  /* time backend settings; hooks are unused */
+  {
+    int times=oggpack_read(opb,6)+1;
+    if(times<=0)goto err_out;
+    for(i=0;i<times;i++){
+      int test=oggpack_read(opb,16);
+      if(test<0 || test>=VI_TIMEB)goto err_out;
+    }
+  }
+
+  /* floor backend settings */
+  ci->floors=oggpack_read(opb,6)+1;
+  if(ci->floors<=0)goto err_out;
+  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;
+  if(ci->residues<=0)goto err_out;
+  for(i=0;i<ci->residues;i++){
+    ci->residue_type[i]=oggpack_read(opb,16);
+    if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
+    ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
+    if(!ci->residue_param[i])goto err_out;
+  }
+
+  /* map backend settings */
+  ci->maps=oggpack_read(opb,6)+1;
+  if(ci->maps<=0)goto err_out;
+  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;
+  if(ci->modes<=0)goto err_out;
+  for(i=0;i<ci->modes;i++){
+    ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i]));
+    ci->mode_param[i]->blockflag=oggpack_read(opb,1);
+    ci->mode_param[i]->windowtype=oggpack_read(opb,16);
+    ci->mode_param[i]->transformtype=oggpack_read(opb,16);
+    ci->mode_param[i]->mapping=oggpack_read(opb,8);
+
+    if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
+    if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
+    if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
+    if(ci->mode_param[i]->mapping<0)goto err_out;
+  }
+
+  if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
+
+  return(0);
+ err_out:
+  vorbis_info_clear(vi);
+  return(OV_EBADHEADER);
+}
+
+/* Is this packet a vorbis ID header? */
+int vorbis_synthesis_idheader(ogg_packet *op){
+  oggpack_buffer opb;
+  char buffer[6];
+
+  if(op){
+    oggpack_readinit(&opb,op->packet,op->bytes);
+
+    if(!op->b_o_s)
+      return(0); /* Not the initial packet */
+
+    if(oggpack_read(&opb,8) != 1)
+      return 0; /* not an ID header */
+
+    memset(buffer,0,6);
+    _v_readstring(&opb,buffer,6);
+    if(memcmp(buffer,"vorbis",6))
+      return 0; /* not vorbis */
+
+    return 1;
+  }
+
+  return 0;
+}
+
+/* The Vorbis header is in three packets; the initial small packet in
+   the first page that identifies basic parameters, a second packet
+   with bitstream comments and a third packet that holds the
+   codebook. */
+
+int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
+  oggpack_buffer opb;
+
+  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", 6);
+
+  /* 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){
+  int bytes = strlen(ENCODE_VENDOR_STRING);
+
+  /* preamble */
+  oggpack_write(opb,0x03,8);
+  _v_writestring(opb,"vorbis", 6);
+
+  /* vendor */
+  oggpack_write(opb,bytes,32);
+  _v_writestring(opb,ENCODE_VENDOR_STRING, bytes);
+
+  /* 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], vc->comment_lengths[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", 6);
+
+  /* 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; hook placeholders */
+  oggpack_write(opb,0,6);
+  oggpack_write(opb,0,16);
+
+  /* floors */
+  oggpack_write(opb,ci->floors-1,6);
+  for(i=0;i<ci->floors;i++){
+    oggpack_write(opb,ci->floor_type[i],16);
+    if(_floor_P[ci->floor_type[i]]->pack)
+      _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
+    else
+      goto err_out;
+  }
+
+  /* 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_commentheader_out(vorbis_comment *vc,
+                                          ogg_packet *op){
+
+  oggpack_buffer opb;
+
+  oggpack_writeinit(&opb);
+  if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL;
+
+  op->packet = _ogg_malloc(oggpack_bytes(&opb));
+  memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
+
+  op->bytes=oggpack_bytes(&opb);
+  op->b_o_s=0;
+  op->e_o_s=0;
+  op->granulepos=0;
+  op->packetno=1;
+
+  return 0;
+}
+
+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;
+  private_state *b=v->backend_state;
+
+  if(!b||vi->channels<=0||vi->channels>256){
+    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;
+  op->packetno=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;
+  op_comm->packetno=1;
+
+  /* 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;
+  op_code->packetno=2;
+
+  oggpack_writeclear(&opb);
+  return(0);
+ err_out:
+  memset(op,0,sizeof(*op));
+  memset(op_comm,0,sizeof(*op_comm));
+  memset(op_code,0,sizeof(*op_code));
+
+  if(b){
+    oggpack_writeclear(&opb);
+    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);
+}
+
+double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
+  if(granulepos == -1) return -1;
+
+  /* We're not guaranteed a 64 bit unsigned type everywhere, so we
+     have to put the unsigned granpo in a signed type. */
+  if(granulepos>=0){
+    return((double)granulepos/v->vi->rate);
+  }else{
+    ogg_int64_t granuleoff=0xffffffff;
+    granuleoff<<=31;
+    granuleoff|=0x7ffffffff;
+    return(((double)granulepos+2+granuleoff+granuleoff)/v->vi->rate);
+  }
+}
+
+const char *vorbis_version_string(void){
+  return GENERAL_VENDOR_STRING;
+}
--- libvorbis-1.3.2.orig/.pc/CVE-2018-10392.patch/lib/vorbisenc.c
+++ libvorbis-1.3.2/.pc/CVE-2018-10392.patch/lib/vorbisenc.c
@@ -0,0 +1,1215 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+ *                                                                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+ function: simple programmatic interface for encoder mode setup
+ last mod: $Id: vorbisenc.c 17028 2010-03-25 05:22:15Z xiphmont $
+
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "vorbis/codec.h"
+#include "vorbis/vorbisenc.h"
+
+#include "codec_internal.h"
+
+#include "os.h"
+#include "misc.h"
+
+/* careful with this; it's using static array sizing to make managing
+   all the modes a little less annoying.  If we use a residue backend
+   with > 12 partition types, or a different division of iteration,
+   this needs to be updated. */
+typedef struct {
+  const static_codebook *books[12][4];
+} static_bookblock;
+
+typedef struct {
+  int res_type;
+  int limit_type; /* 0 lowpass limited, 1 point stereo limited */
+  int grouping;
+  const vorbis_info_residue0 *res;
+  const static_codebook  *book_aux;
+  const static_codebook  *book_aux_managed;
+  const static_bookblock *books_base;
+  const static_bookblock *books_base_managed;
+} vorbis_residue_template;
+
+typedef struct {
+  const vorbis_info_mapping0    *map;
+  const vorbis_residue_template *res;
+} vorbis_mapping_template;
+
+typedef struct vp_adjblock{
+  int block[P_BANDS];
+} vp_adjblock;
+
+typedef struct {
+  int data[NOISE_COMPAND_LEVELS];
+} compandblock;
+
+/* high level configuration information for setting things up
+   step-by-step with the detailed vorbis_encode_ctl interface.
+   There's a fair amount of redundancy such that interactive setup
+   does not directly deal with any vorbis_info or codec_setup_info
+   initialization; it's all stored (until full init) in this highlevel
+   setup, then flushed out to the real codec setup structs later. */
+
+typedef struct {
+  int att[P_NOISECURVES];
+  float boost;
+  float decay;
+} att3;
+typedef struct { int data[P_NOISECURVES]; } adj3;
+
+typedef struct {
+  int   pre[PACKETBLOBS];
+  int   post[PACKETBLOBS];
+  float kHz[PACKETBLOBS];
+  float lowpasskHz[PACKETBLOBS];
+} adj_stereo;
+
+typedef struct {
+  int lo;
+  int hi;
+  int fixed;
+} noiseguard;
+typedef struct {
+  int data[P_NOISECURVES][17];
+} noise3;
+
+typedef struct {
+  int      mappings;
+  const double  *rate_mapping;
+  const double  *quality_mapping;
+  int      coupling_restriction;
+  long     samplerate_min_restriction;
+  long     samplerate_max_restriction;
+
+
+  const int     *blocksize_short;
+  const int     *blocksize_long;
+
+  const att3    *psy_tone_masteratt;
+  const int     *psy_tone_0dB;
+  const int     *psy_tone_dBsuppress;
+
+  const vp_adjblock *psy_tone_adj_impulse;
+  const vp_adjblock *psy_tone_adj_long;
+  const vp_adjblock *psy_tone_adj_other;
+
+  const noiseguard  *psy_noiseguards;
+  const noise3      *psy_noise_bias_impulse;
+  const noise3      *psy_noise_bias_padding;
+  const noise3      *psy_noise_bias_trans;
+  const noise3      *psy_noise_bias_long;
+  const int         *psy_noise_dBsuppress;
+
+  const compandblock  *psy_noise_compand;
+  const double        *psy_noise_compand_short_mapping;
+  const double        *psy_noise_compand_long_mapping;
+
+  const int      *psy_noise_normal_start[2];
+  const int      *psy_noise_normal_partition[2];
+  const double   *psy_noise_normal_thresh;
+
+  const int      *psy_ath_float;
+  const int      *psy_ath_abs;
+
+  const double   *psy_lowpass;
+
+  const vorbis_info_psy_global *global_params;
+  const double     *global_mapping;
+  const adj_stereo *stereo_modes;
+
+  const static_codebook *const *const *const floor_books;
+  const vorbis_info_floor1 *floor_params;
+  const int floor_mappings;
+  const int **floor_mapping_list;
+
+  const vorbis_mapping_template *maps;
+} ve_setup_data_template;
+
+/* a few static coder conventions */
+static const vorbis_info_mode _mode_template[2]={
+  {0,0,0,0},
+  {1,0,0,1}
+};
+
+static const vorbis_info_mapping0 _map_nominal[2]={
+  {1, {0,0}, {0}, {0}, 1,{0},{1}},
+  {1, {0,0}, {1}, {1}, 1,{0},{1}}
+};
+
+#include "modes/setup_44.h"
+#include "modes/setup_44u.h"
+#include "modes/setup_44p51.h"
+#include "modes/setup_32.h"
+#include "modes/setup_8.h"
+#include "modes/setup_11.h"
+#include "modes/setup_16.h"
+#include "modes/setup_22.h"
+#include "modes/setup_X.h"
+
+static const ve_setup_data_template *const setup_list[]={
+  &ve_setup_44_stereo,
+  &ve_setup_44_51,
+  &ve_setup_44_uncoupled,
+
+  &ve_setup_32_stereo,
+  &ve_setup_32_uncoupled,
+
+  &ve_setup_22_stereo,
+  &ve_setup_22_uncoupled,
+  &ve_setup_16_stereo,
+  &ve_setup_16_uncoupled,
+
+  &ve_setup_11_stereo,
+  &ve_setup_11_uncoupled,
+  &ve_setup_8_stereo,
+  &ve_setup_8_uncoupled,
+
+  &ve_setup_X_stereo,
+  &ve_setup_X_uncoupled,
+  &ve_setup_XX_stereo,
+  &ve_setup_XX_uncoupled,
+  0
+};
+
+static void vorbis_encode_floor_setup(vorbis_info *vi,int s,
+                                     const static_codebook *const *const *const books,
+                                     const vorbis_info_floor1 *in,
+                                     const int *x){
+  int i,k,is=s;
+  vorbis_info_floor1 *f=_ogg_calloc(1,sizeof(*f));
+  codec_setup_info *ci=vi->codec_setup;
+
+  memcpy(f,in+x[is],sizeof(*f));
+
+  /* books */
+  {
+    int partitions=f->partitions;
+    int maxclass=-1;
+    int maxbook=-1;
+    for(i=0;i<partitions;i++)
+      if(f->partitionclass[i]>maxclass)maxclass=f->partitionclass[i];
+    for(i=0;i<=maxclass;i++){
+      if(f->class_book[i]>maxbook)maxbook=f->class_book[i];
+      f->class_book[i]+=ci->books;
+      for(k=0;k<(1<<f->class_subs[i]);k++){
+        if(f->class_subbook[i][k]>maxbook)maxbook=f->class_subbook[i][k];
+        if(f->class_subbook[i][k]>=0)f->class_subbook[i][k]+=ci->books;
+      }
+    }
+
+    for(i=0;i<=maxbook;i++)
+      ci->book_param[ci->books++]=(static_codebook *)books[x[is]][i];
+  }
+
+  /* for now, we're only using floor 1 */
+  ci->floor_type[ci->floors]=1;
+  ci->floor_param[ci->floors]=f;
+  ci->floors++;
+
+  return;
+}
+
+static void vorbis_encode_global_psych_setup(vorbis_info *vi,double s,
+                                            const vorbis_info_psy_global *in,
+                                            const double *x){
+  int i,is=s;
+  double ds=s-is;
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy_global *g=&ci->psy_g_param;
+
+  memcpy(g,in+(int)x[is],sizeof(*g));
+
+  ds=x[is]*(1.-ds)+x[is+1]*ds;
+  is=(int)ds;
+  ds-=is;
+  if(ds==0 && is>0){
+    is--;
+    ds=1.;
+  }
+
+  /* interpolate the trigger threshholds */
+  for(i=0;i<4;i++){
+    g->preecho_thresh[i]=in[is].preecho_thresh[i]*(1.-ds)+in[is+1].preecho_thresh[i]*ds;
+    g->postecho_thresh[i]=in[is].postecho_thresh[i]*(1.-ds)+in[is+1].postecho_thresh[i]*ds;
+  }
+  g->ampmax_att_per_sec=ci->hi.amplitude_track_dBpersec;
+  return;
+}
+
+static void vorbis_encode_global_stereo(vorbis_info *vi,
+                                        const highlevel_encode_setup *const hi,
+                                        const adj_stereo *p){
+  float s=hi->stereo_point_setting;
+  int i,is=s;
+  double ds=s-is;
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy_global *g=&ci->psy_g_param;
+
+  if(p){
+    memcpy(g->coupling_prepointamp,p[is].pre,sizeof(*p[is].pre)*PACKETBLOBS);
+    memcpy(g->coupling_postpointamp,p[is].post,sizeof(*p[is].post)*PACKETBLOBS);
+
+    if(hi->managed){
+      /* interpolate the kHz threshholds */
+      for(i=0;i<PACKETBLOBS;i++){
+        float kHz=p[is].kHz[i]*(1.-ds)+p[is+1].kHz[i]*ds;
+        g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0];
+        g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1];
+        g->coupling_pkHz[i]=kHz;
+
+        kHz=p[is].lowpasskHz[i]*(1.-ds)+p[is+1].lowpasskHz[i]*ds;
+        g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0];
+        g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1];
+
+      }
+    }else{
+      float kHz=p[is].kHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].kHz[PACKETBLOBS/2]*ds;
+      for(i=0;i<PACKETBLOBS;i++){
+        g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0];
+        g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1];
+        g->coupling_pkHz[i]=kHz;
+      }
+
+      kHz=p[is].lowpasskHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].lowpasskHz[PACKETBLOBS/2]*ds;
+      for(i=0;i<PACKETBLOBS;i++){
+        g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0];
+        g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1];
+      }
+    }
+  }else{
+    for(i=0;i<PACKETBLOBS;i++){
+      g->sliding_lowpass[0][i]=ci->blocksizes[0];
+      g->sliding_lowpass[1][i]=ci->blocksizes[1];
+    }
+  }
+  return;
+}
+
+static void vorbis_encode_psyset_setup(vorbis_info *vi,double s,
+                                       const int *nn_start,
+                                       const int *nn_partition,
+                                       const double *nn_thresh,
+                                       int block){
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy *p=ci->psy_param[block];
+  highlevel_encode_setup *hi=&ci->hi;
+  int is=s;
+
+  if(block>=ci->psys)
+    ci->psys=block+1;
+  if(!p){
+    p=_ogg_calloc(1,sizeof(*p));
+    ci->psy_param[block]=p;
+  }
+
+  memcpy(p,&_psy_info_template,sizeof(*p));
+  p->blockflag=block>>1;
+
+  if(hi->noise_normalize_p){
+    p->normal_p=1;
+    p->normal_start=nn_start[is];
+    p->normal_partition=nn_partition[is];
+    p->normal_thresh=nn_thresh[is];
+  }
+
+  return;
+}
+
+static void vorbis_encode_tonemask_setup(vorbis_info *vi,double s,int block,
+                                         const att3 *att,
+                                         const int  *max,
+                                         const vp_adjblock *in){
+  int i,is=s;
+  double ds=s-is;
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy *p=ci->psy_param[block];
+
+  /* 0 and 2 are only used by bitmanagement, but there's no harm to always
+     filling the values in here */
+  p->tone_masteratt[0]=att[is].att[0]*(1.-ds)+att[is+1].att[0]*ds;
+  p->tone_masteratt[1]=att[is].att[1]*(1.-ds)+att[is+1].att[1]*ds;
+  p->tone_masteratt[2]=att[is].att[2]*(1.-ds)+att[is+1].att[2]*ds;
+  p->tone_centerboost=att[is].boost*(1.-ds)+att[is+1].boost*ds;
+  p->tone_decay=att[is].decay*(1.-ds)+att[is+1].decay*ds;
+
+  p->max_curve_dB=max[is]*(1.-ds)+max[is+1]*ds;
+
+  for(i=0;i<P_BANDS;i++)
+    p->toneatt[i]=in[is].block[i]*(1.-ds)+in[is+1].block[i]*ds;
+  return;
+}
+
+
+static void vorbis_encode_compand_setup(vorbis_info *vi,double s,int block,
+                                        const compandblock *in,
+                                        const double *x){
+  int i,is=s;
+  double ds=s-is;
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy *p=ci->psy_param[block];
+
+  ds=x[is]*(1.-ds)+x[is+1]*ds;
+  is=(int)ds;
+  ds-=is;
+  if(ds==0 && is>0){
+    is--;
+    ds=1.;
+  }
+
+  /* interpolate the compander settings */
+  for(i=0;i<NOISE_COMPAND_LEVELS;i++)
+    p->noisecompand[i]=in[is].data[i]*(1.-ds)+in[is+1].data[i]*ds;
+  return;
+}
+
+static void vorbis_encode_peak_setup(vorbis_info *vi,double s,int block,
+                                    const int *suppress){
+  int is=s;
+  double ds=s-is;
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy *p=ci->psy_param[block];
+
+  p->tone_abs_limit=suppress[is]*(1.-ds)+suppress[is+1]*ds;
+
+  return;
+}
+
+static void vorbis_encode_noisebias_setup(vorbis_info *vi,double s,int block,
+                                         const int *suppress,
+                                         const noise3 *in,
+                                         const noiseguard *guard,
+                                         double userbias){
+  int i,is=s,j;
+  double ds=s-is;
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy *p=ci->psy_param[block];
+
+  p->noisemaxsupp=suppress[is]*(1.-ds)+suppress[is+1]*ds;
+  p->noisewindowlomin=guard[block].lo;
+  p->noisewindowhimin=guard[block].hi;
+  p->noisewindowfixed=guard[block].fixed;
+
+  for(j=0;j<P_NOISECURVES;j++)
+    for(i=0;i<P_BANDS;i++)
+      p->noiseoff[j][i]=in[is].data[j][i]*(1.-ds)+in[is+1].data[j][i]*ds;
+
+  /* impulse blocks may take a user specified bias to boost the
+     nominal/high noise encoding depth */
+  for(j=0;j<P_NOISECURVES;j++){
+    float min=p->noiseoff[j][0]+6; /* the lowest it can go */
+    for(i=0;i<P_BANDS;i++){
+      p->noiseoff[j][i]+=userbias;
+      if(p->noiseoff[j][i]<min)p->noiseoff[j][i]=min;
+    }
+  }
+
+  return;
+}
+
+static void vorbis_encode_ath_setup(vorbis_info *vi,int block){
+  codec_setup_info *ci=vi->codec_setup;
+  vorbis_info_psy *p=ci->psy_param[block];
+
+  p->ath_adjatt=ci->hi.ath_floating_dB;
+  p->ath_maxatt=ci->hi.ath_absolute_dB;
+  return;
+}
+
+
+static int book_dup_or_new(codec_setup_info *ci,const static_codebook *book){
+  int i;
+  for(i=0;i<ci->books;i++)
+    if(ci->book_param[i]==book)return(i);
+
+  return(ci->books++);
+}
+
+static void vorbis_encode_blocksize_setup(vorbis_info *vi,double s,
+                                         const int *shortb,const int *longb){
+
+  codec_setup_info *ci=vi->codec_setup;
+  int is=s;
+
+  int blockshort=shortb[is];
+  int blocklong=longb[is];
+  ci->blocksizes[0]=blockshort;
+  ci->blocksizes[1]=blocklong;
+
+}
+
+static void vorbis_encode_residue_setup(vorbis_info *vi,
+                                        int number, int block,
+                                        const vorbis_residue_template *res){
+
+  codec_setup_info *ci=vi->codec_setup;
+  int i;
+
+  vorbis_info_residue0 *r=ci->residue_param[number]=
+    _ogg_malloc(sizeof(*r));
+
+  memcpy(r,res->res,sizeof(*r));
+  if(ci->residues<=number)ci->residues=number+1;
+
+  r->grouping=res->grouping;
+  ci->residue_type[number]=res->res_type;
+
+  /* fill in all the books */
+  {
+    int booklist=0,k;
+
+    if(ci->hi.managed){
+      for(i=0;i<r->partitions;i++)
+        for(k=0;k<4;k++)
+          if(res->books_base_managed->books[i][k])
+            r->secondstages[i]|=(1<<k);
+
+      r->groupbook=book_dup_or_new(ci,res->book_aux_managed);
+      ci->book_param[r->groupbook]=(static_codebook *)res->book_aux_managed;
+
+      for(i=0;i<r->partitions;i++){
+        for(k=0;k<4;k++){
+          if(res->books_base_managed->books[i][k]){
+            int bookid=book_dup_or_new(ci,res->books_base_managed->books[i][k]);
+            r->booklist[booklist++]=bookid;
+            ci->book_param[bookid]=(static_codebook *)res->books_base_managed->books[i][k];
+          }
+        }
+      }
+
+    }else{
+
+      for(i=0;i<r->partitions;i++)
+        for(k=0;k<4;k++)
+          if(res->books_base->books[i][k])
+            r->secondstages[i]|=(1<<k);
+
+      r->groupbook=book_dup_or_new(ci,res->book_aux);
+      ci->book_param[r->groupbook]=(static_codebook *)res->book_aux;
+
+      for(i=0;i<r->partitions;i++){
+        for(k=0;k<4;k++){
+          if(res->books_base->books[i][k]){
+            int bookid=book_dup_or_new(ci,res->books_base->books[i][k]);
+            r->booklist[booklist++]=bookid;
+            ci->book_param[bookid]=(static_codebook *)res->books_base->books[i][k];
+          }
+        }
+      }
+    }
+  }
+
+  /* lowpass setup/pointlimit */
+  {
+    double freq=ci->hi.lowpass_kHz*1000.;
+    vorbis_info_floor1 *f=ci->floor_param[block]; /* by convention */
+    double nyq=vi->rate/2.;
+    long blocksize=ci->blocksizes[block]>>1;
+
+    /* lowpass needs to be set in the floor and the residue. */
+    if(freq>nyq)freq=nyq;
+    /* in the floor, the granularity can be very fine; it doesn't alter
+       the encoding structure, only the samples used to fit the floor
+       approximation */
+    f->n=freq/nyq*blocksize;
+
+    /* this res may by limited by the maximum pointlimit of the mode,
+       not the lowpass. the floor is always lowpass limited. */
+    switch(res->limit_type){
+    case 1: /* point stereo limited */
+      if(ci->hi.managed)
+        freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS-1]*1000.;
+      else
+        freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS/2]*1000.;
+      if(freq>nyq)freq=nyq;
+      break;
+    case 2: /* LFE channel; lowpass at ~ 250Hz */
+      freq=250;
+      break;
+    default:
+      /* already set */
+      break;
+    }
+
+    /* in the residue, we're constrained, physically, by partition
+       boundaries.  We still lowpass 'wherever', but we have to round up
+       here to next boundary, or the vorbis spec will round it *down* to
+       previous boundary in encode/decode */
+    if(ci->residue_type[number]==2){
+      /* residue 2 bundles together multiple channels; used by stereo
+         and surround.  Count the channels in use */
+      /* Multiple maps/submaps can point to the same residue.  In the case
+         of residue 2, they all better have the same number of
+         channels/samples. */
+      int j,k,ch=0;
+      for(i=0;i<ci->maps&&ch==0;i++){
+        vorbis_info_mapping0 *mi=(vorbis_info_mapping0 *)ci->map_param[i];
+        for(j=0;j<mi->submaps && ch==0;j++)
+          if(mi->residuesubmap[j]==number) /* we found a submap referencing theis residue backend */
+            for(k=0;k<vi->channels;k++)
+              if(mi->chmuxlist[k]==j) /* this channel belongs to the submap */
+                ch++;
+      }
+
+      r->end=(int)((freq/nyq*blocksize*ch)/r->grouping+.9)* /* round up only if we're well past */
+        r->grouping;
+      /* the blocksize and grouping may disagree at the end */
+      if(r->end>blocksize*ch)r->end=blocksize*ch/r->grouping*r->grouping;
+
+    }else{
+
+      r->end=(int)((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */
+        r->grouping;
+      /* the blocksize and grouping may disagree at the end */
+      if(r->end>blocksize)r->end=blocksize/r->grouping*r->grouping;
+
+    }
+
+    if(r->end==0)r->end=r->grouping; /* LFE channel */
+
+  }
+}
+
+/* we assume two maps in this encoder */
+static void vorbis_encode_map_n_res_setup(vorbis_info *vi,double s,
+                                          const vorbis_mapping_template *maps){
+
+  codec_setup_info *ci=vi->codec_setup;
+  int i,j,is=s,modes=2;
+  const vorbis_info_mapping0 *map=maps[is].map;
+  const vorbis_info_mode *mode=_mode_template;
+  const vorbis_residue_template *res=maps[is].res;
+
+  if(ci->blocksizes[0]==ci->blocksizes[1])modes=1;
+
+  for(i=0;i<modes;i++){
+
+    ci->map_param[i]=_ogg_calloc(1,sizeof(*map));
+    ci->mode_param[i]=_ogg_calloc(1,sizeof(*mode));
+
+    memcpy(ci->mode_param[i],mode+i,sizeof(*_mode_template));
+    if(i>=ci->modes)ci->modes=i+1;
+
+    ci->map_type[i]=0;
+    memcpy(ci->map_param[i],map+i,sizeof(*map));
+    if(i>=ci->maps)ci->maps=i+1;
+
+    for(j=0;j<map[i].submaps;j++)
+      vorbis_encode_residue_setup(vi,map[i].residuesubmap[j],i
+                                  ,res+map[i].residuesubmap[j]);
+  }
+}
+
+static double setting_to_approx_bitrate(vorbis_info *vi){
+  codec_setup_info *ci=vi->codec_setup;
+  highlevel_encode_setup *hi=&ci->hi;
+  ve_setup_data_template *setup=(ve_setup_data_template *)hi->setup;
+  int is=hi->base_setting;
+  double ds=hi->base_setting-is;
+  int ch=vi->channels;
+  const double *r=setup->rate_mapping;
+
+  if(r==NULL)
+    return(-1);
+
+  return((r[is]*(1.-ds)+r[is+1]*ds)*ch);
+}
+
+static const void *get_setup_template(long ch,long srate,
+                                      double req,int q_or_bitrate,
+                                      double *base_setting){
+  int i=0,j;
+  if(q_or_bitrate)req/=ch;
+
+  while(setup_list[i]){
+    if(setup_list[i]->coupling_restriction==-1 ||
+       setup_list[i]->coupling_restriction==ch){
+      if(srate>=setup_list[i]->samplerate_min_restriction &&
+         srate<=setup_list[i]->samplerate_max_restriction){
+        int mappings=setup_list[i]->mappings;
+        const double *map=(q_or_bitrate?
+                     setup_list[i]->rate_mapping:
+                     setup_list[i]->quality_mapping);
+
+        /* the template matches.  Does the requested quality mode
+           fall within this template's modes? */
+        if(req<map[0]){++i;continue;}
+        if(req>map[setup_list[i]->mappings]){++i;continue;}
+        for(j=0;j<mappings;j++)
+          if(req>=map[j] && req<map[j+1])break;
+        /* an all-points match */
+        if(j==mappings)
+          *base_setting=j-.001;
+        else{
+          float low=map[j];
+          float high=map[j+1];
+          float del=(req-low)/(high-low);
+          *base_setting=j+del;
+        }
+
+        return(setup_list[i]);
+      }
+    }
+    i++;
+  }
+
+  return NULL;
+}
+
+/* encoders will need to use vorbis_info_init beforehand and call
+   vorbis_info clear when all done */
+
+/* two interfaces; this, more detailed one, and later a convenience
+   layer on top */
+
+/* the final setup call */
+int vorbis_encode_setup_init(vorbis_info *vi){
+  int i,i0=0,singleblock=0;
+  codec_setup_info *ci=vi->codec_setup;
+  ve_setup_data_template *setup=NULL;
+  highlevel_encode_setup *hi=&ci->hi;
+
+  if(ci==NULL)return(OV_EINVAL);
+  if(!hi->impulse_block_p)i0=1;
+
+  /* too low/high an ATH floater is nonsensical, but doesn't break anything */
+  if(hi->ath_floating_dB>-80)hi->ath_floating_dB=-80;
+  if(hi->ath_floating_dB<-200)hi->ath_floating_dB=-200;
+
+  /* again, bound this to avoid the app shooting itself int he foot
+     too badly */
+  if(hi->amplitude_track_dBpersec>0.)hi->amplitude_track_dBpersec=0.;
+  if(hi->amplitude_track_dBpersec<-99999.)hi->amplitude_track_dBpersec=-99999.;
+
+  /* get the appropriate setup template; matches the fetch in previous
+     stages */
+  setup=(ve_setup_data_template *)hi->setup;
+  if(setup==NULL)return(OV_EINVAL);
+
+  hi->set_in_stone=1;
+  /* choose block sizes from configured sizes as well as paying
+     attention to long_block_p and short_block_p.  If the configured
+     short and long blocks are the same length, we set long_block_p
+     and unset short_block_p */
+  vorbis_encode_blocksize_setup(vi,hi->base_setting,
+                                setup->blocksize_short,
+                                setup->blocksize_long);
+  if(ci->blocksizes[0]==ci->blocksizes[1])singleblock=1;
+
+  /* floor setup; choose proper floor params.  Allocated on the floor
+     stack in order; if we alloc only a single long floor, it's 0 */
+  for(i=0;i<setup->floor_mappings;i++)
+    vorbis_encode_floor_setup(vi,hi->base_setting,
+                              setup->floor_books,
+                              setup->floor_params,
+                              setup->floor_mapping_list[i]);
+
+  /* setup of [mostly] short block detection and stereo*/
+  vorbis_encode_global_psych_setup(vi,hi->trigger_setting,
+                                   setup->global_params,
+                                   setup->global_mapping);
+  vorbis_encode_global_stereo(vi,hi,setup->stereo_modes);
+
+  /* basic psych setup and noise normalization */
+  vorbis_encode_psyset_setup(vi,hi->base_setting,
+                             setup->psy_noise_normal_start[0],
+                             setup->psy_noise_normal_partition[0],
+                             setup->psy_noise_normal_thresh,
+                             0);
+  vorbis_encode_psyset_setup(vi,hi->base_setting,
+                             setup->psy_noise_normal_start[0],
+                             setup->psy_noise_normal_partition[0],
+                             setup->psy_noise_normal_thresh,
+                             1);
+  if(!singleblock){
+    vorbis_encode_psyset_setup(vi,hi->base_setting,
+                               setup->psy_noise_normal_start[1],
+                               setup->psy_noise_normal_partition[1],
+                                    setup->psy_noise_normal_thresh,
+                               2);
+    vorbis_encode_psyset_setup(vi,hi->base_setting,
+                               setup->psy_noise_normal_start[1],
+                               setup->psy_noise_normal_partition[1],
+                               setup->psy_noise_normal_thresh,
+                               3);
+  }
+
+  /* tone masking setup */
+  vorbis_encode_tonemask_setup(vi,hi->block[i0].tone_mask_setting,0,
+                               setup->psy_tone_masteratt,
+                               setup->psy_tone_0dB,
+                               setup->psy_tone_adj_impulse);
+  vorbis_encode_tonemask_setup(vi,hi->block[1].tone_mask_setting,1,
+                               setup->psy_tone_masteratt,
+                               setup->psy_tone_0dB,
+                               setup->psy_tone_adj_other);
+  if(!singleblock){
+    vorbis_encode_tonemask_setup(vi,hi->block[2].tone_mask_setting,2,
+                                 setup->psy_tone_masteratt,
+                                 setup->psy_tone_0dB,
+                                 setup->psy_tone_adj_other);
+    vorbis_encode_tonemask_setup(vi,hi->block[3].tone_mask_setting,3,
+                                 setup->psy_tone_masteratt,
+                                 setup->psy_tone_0dB,
+                                 setup->psy_tone_adj_long);
+  }
+
+  /* noise companding setup */
+  vorbis_encode_compand_setup(vi,hi->block[i0].noise_compand_setting,0,
+                              setup->psy_noise_compand,
+                              setup->psy_noise_compand_short_mapping);
+  vorbis_encode_compand_setup(vi,hi->block[1].noise_compand_setting,1,
+                              setup->psy_noise_compand,
+                              setup->psy_noise_compand_short_mapping);
+  if(!singleblock){
+    vorbis_encode_compand_setup(vi,hi->block[2].noise_compand_setting,2,
+                                setup->psy_noise_compand,
+                                setup->psy_noise_compand_long_mapping);
+    vorbis_encode_compand_setup(vi,hi->block[3].noise_compand_setting,3,
+                                setup->psy_noise_compand,
+                                setup->psy_noise_compand_long_mapping);
+  }
+
+  /* peak guarding setup  */
+  vorbis_encode_peak_setup(vi,hi->block[i0].tone_peaklimit_setting,0,
+                           setup->psy_tone_dBsuppress);
+  vorbis_encode_peak_setup(vi,hi->block[1].tone_peaklimit_setting,1,
+                           setup->psy_tone_dBsuppress);
+  if(!singleblock){
+    vorbis_encode_peak_setup(vi,hi->block[2].tone_peaklimit_setting,2,
+                             setup->psy_tone_dBsuppress);
+    vorbis_encode_peak_setup(vi,hi->block[3].tone_peaklimit_setting,3,
+                             setup->psy_tone_dBsuppress);
+  }
+
+  /* noise bias setup */
+  vorbis_encode_noisebias_setup(vi,hi->block[i0].noise_bias_setting,0,
+                                setup->psy_noise_dBsuppress,
+                                setup->psy_noise_bias_impulse,
+                                setup->psy_noiseguards,
+                                (i0==0?hi->impulse_noisetune:0.));
+  vorbis_encode_noisebias_setup(vi,hi->block[1].noise_bias_setting,1,
+                                setup->psy_noise_dBsuppress,
+                                setup->psy_noise_bias_padding,
+                                setup->psy_noiseguards,0.);
+  if(!singleblock){
+    vorbis_encode_noisebias_setup(vi,hi->block[2].noise_bias_setting,2,
+                                  setup->psy_noise_dBsuppress,
+                                  setup->psy_noise_bias_trans,
+                                  setup->psy_noiseguards,0.);
+    vorbis_encode_noisebias_setup(vi,hi->block[3].noise_bias_setting,3,
+                                  setup->psy_noise_dBsuppress,
+                                  setup->psy_noise_bias_long,
+                                  setup->psy_noiseguards,0.);
+  }
+
+  vorbis_encode_ath_setup(vi,0);
+  vorbis_encode_ath_setup(vi,1);
+  if(!singleblock){
+    vorbis_encode_ath_setup(vi,2);
+    vorbis_encode_ath_setup(vi,3);
+  }
+
+  vorbis_encode_map_n_res_setup(vi,hi->base_setting,setup->maps);
+
+  /* set bitrate readonlies and management */
+  if(hi->bitrate_av>0)
+    vi->bitrate_nominal=hi->bitrate_av;
+  else{
+    vi->bitrate_nominal=setting_to_approx_bitrate(vi);
+  }
+
+  vi->bitrate_lower=hi->bitrate_min;
+  vi->bitrate_upper=hi->bitrate_max;
+  if(hi->bitrate_av)
+    vi->bitrate_window=(double)hi->bitrate_reservoir/hi->bitrate_av;
+  else
+    vi->bitrate_window=0.;
+
+  if(hi->managed){
+    ci->bi.avg_rate=hi->bitrate_av;
+    ci->bi.min_rate=hi->bitrate_min;
+    ci->bi.max_rate=hi->bitrate_max;
+
+    ci->bi.reservoir_bits=hi->bitrate_reservoir;
+    ci->bi.reservoir_bias=
+      hi->bitrate_reservoir_bias;
+
+    ci->bi.slew_damp=hi->bitrate_av_damp;
+
+  }
+
+  return(0);
+
+}
+
+static void vorbis_encode_setup_setting(vorbis_info *vi,
+                                       long  channels,
+                                       long  rate){
+  int i,is;
+  codec_setup_info *ci=vi->codec_setup;
+  highlevel_encode_setup *hi=&ci->hi;
+  const ve_setup_data_template *setup=hi->setup;
+  double ds;
+
+  vi->version=0;
+  vi->channels=channels;
+  vi->rate=rate;
+
+  hi->impulse_block_p=1;
+  hi->noise_normalize_p=1;
+
+  is=hi->base_setting;
+  ds=hi->base_setting-is;
+
+  hi->stereo_point_setting=hi->base_setting;
+
+  if(!hi->lowpass_altered)
+    hi->lowpass_kHz=
+      setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds;
+
+  hi->ath_floating_dB=setup->psy_ath_float[is]*(1.-ds)+
+    setup->psy_ath_float[is+1]*ds;
+  hi->ath_absolute_dB=setup->psy_ath_abs[is]*(1.-ds)+
+    setup->psy_ath_abs[is+1]*ds;
+
+  hi->amplitude_track_dBpersec=-6.;
+  hi->trigger_setting=hi->base_setting;
+
+  for(i=0;i<4;i++){
+    hi->block[i].tone_mask_setting=hi->base_setting;
+    hi->block[i].tone_peaklimit_setting=hi->base_setting;
+    hi->block[i].noise_bias_setting=hi->base_setting;
+    hi->block[i].noise_compand_setting=hi->base_setting;
+  }
+}
+
+int vorbis_encode_setup_vbr(vorbis_info *vi,
+                            long  channels,
+                            long  rate,
+                            float quality){
+  codec_setup_info *ci=vi->codec_setup;
+  highlevel_encode_setup *hi=&ci->hi;
+
+  quality+=.0000001;
+  if(quality>=1.)quality=.9999;
+
+  hi->req=quality;
+  hi->setup=get_setup_template(channels,rate,quality,0,&hi->base_setting);
+  if(!hi->setup)return OV_EIMPL;
+
+  vorbis_encode_setup_setting(vi,channels,rate);
+  hi->managed=0;
+  hi->coupling_p=1;
+
+  return 0;
+}
+
+int vorbis_encode_init_vbr(vorbis_info *vi,
+                           long channels,
+                           long rate,
+
+                           float base_quality /* 0. to 1. */
+                           ){
+  int ret=0;
+
+  ret=vorbis_encode_setup_vbr(vi,channels,rate,base_quality);
+
+  if(ret){
+    vorbis_info_clear(vi);
+    return ret;
+  }
+  ret=vorbis_encode_setup_init(vi);
+  if(ret)
+    vorbis_info_clear(vi);
+  return(ret);
+}
+
+int vorbis_encode_setup_managed(vorbis_info *vi,
+                                long channels,
+                                long rate,
+
+                                long max_bitrate,
+                                long nominal_bitrate,
+                                long min_bitrate){
+
+  codec_setup_info *ci=vi->codec_setup;
+  highlevel_encode_setup *hi=&ci->hi;
+  double tnominal=nominal_bitrate;
+
+  if(nominal_bitrate<=0.){
+    if(max_bitrate>0.){
+      if(min_bitrate>0.)
+        nominal_bitrate=(max_bitrate+min_bitrate)*.5;
+      else
+        nominal_bitrate=max_bitrate*.875;
+    }else{
+      if(min_bitrate>0.){
+        nominal_bitrate=min_bitrate;
+      }else{
+        return(OV_EINVAL);
+      }
+    }
+  }
+
+  hi->req=nominal_bitrate;
+  hi->setup=get_setup_template(channels,rate,nominal_bitrate,1,&hi->base_setting);
+  if(!hi->setup)return OV_EIMPL;
+
+  vorbis_encode_setup_setting(vi,channels,rate);
+
+  /* initialize management with sane defaults */
+  hi->coupling_p=1;
+  hi->managed=1;
+  hi->bitrate_min=min_bitrate;
+  hi->bitrate_max=max_bitrate;
+  hi->bitrate_av=tnominal;
+  hi->bitrate_av_damp=1.5f; /* full range in no less than 1.5 second */
+  hi->bitrate_reservoir=nominal_bitrate*2;
+  hi->bitrate_reservoir_bias=.1; /* bias toward hoarding bits */
+
+  return(0);
+
+}
+
+int vorbis_encode_init(vorbis_info *vi,
+                       long channels,
+                       long rate,
+
+                       long max_bitrate,
+                       long nominal_bitrate,
+                       long min_bitrate){
+
+  int ret=vorbis_encode_setup_managed(vi,channels,rate,
+                                      max_bitrate,
+                                      nominal_bitrate,
+                                      min_bitrate);
+  if(ret){
+    vorbis_info_clear(vi);
+    return(ret);
+  }
+
+  ret=vorbis_encode_setup_init(vi);
+  if(ret)
+    vorbis_info_clear(vi);
+  return(ret);
+}
+
+int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){
+  if(vi){
+    codec_setup_info *ci=vi->codec_setup;
+    highlevel_encode_setup *hi=&ci->hi;
+    int setp=(number&0xf); /* a read request has a low nibble of 0 */
+
+    if(setp && hi->set_in_stone)return(OV_EINVAL);
+
+    switch(number){
+
+    /* now deprecated *****************/
+    case OV_ECTL_RATEMANAGE_GET:
+      {
+
+        struct ovectl_ratemanage_arg *ai=
+          (struct ovectl_ratemanage_arg *)arg;
+
+        ai->management_active=hi->managed;
+        ai->bitrate_hard_window=ai->bitrate_av_window=
+          (double)hi->bitrate_reservoir/vi->rate;
+        ai->bitrate_av_window_center=1.;
+        ai->bitrate_hard_min=hi->bitrate_min;
+        ai->bitrate_hard_max=hi->bitrate_max;
+        ai->bitrate_av_lo=hi->bitrate_av;
+        ai->bitrate_av_hi=hi->bitrate_av;
+
+      }
+      return(0);
+
+    /* now deprecated *****************/
+    case OV_ECTL_RATEMANAGE_SET:
+      {
+        struct ovectl_ratemanage_arg *ai=
+          (struct ovectl_ratemanage_arg *)arg;
+        if(ai==NULL){
+          hi->managed=0;
+        }else{
+          hi->managed=ai->management_active;
+          vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_AVG,arg);
+          vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_HARD,arg);
+        }
+      }
+      return 0;
+
+    /* now deprecated *****************/
+    case OV_ECTL_RATEMANAGE_AVG:
+      {
+        struct ovectl_ratemanage_arg *ai=
+          (struct ovectl_ratemanage_arg *)arg;
+        if(ai==NULL){
+          hi->bitrate_av=0;
+        }else{
+          hi->bitrate_av=(ai->bitrate_av_lo+ai->bitrate_av_hi)*.5;
+        }
+      }
+      return(0);
+    /* now deprecated *****************/
+    case OV_ECTL_RATEMANAGE_HARD:
+      {
+        struct ovectl_ratemanage_arg *ai=
+          (struct ovectl_ratemanage_arg *)arg;
+        if(ai==NULL){
+          hi->bitrate_min=0;
+          hi->bitrate_max=0;
+        }else{
+          hi->bitrate_min=ai->bitrate_hard_min;
+          hi->bitrate_max=ai->bitrate_hard_max;
+          hi->bitrate_reservoir=ai->bitrate_hard_window*
+            (hi->bitrate_max+hi->bitrate_min)*.5;
+        }
+        if(hi->bitrate_reservoir<128.)
+          hi->bitrate_reservoir=128.;
+      }
+      return(0);
+
+      /* replacement ratemanage interface */
+    case OV_ECTL_RATEMANAGE2_GET:
+      {
+        struct ovectl_ratemanage2_arg *ai=
+          (struct ovectl_ratemanage2_arg *)arg;
+        if(ai==NULL)return OV_EINVAL;
+
+        ai->management_active=hi->managed;
+        ai->bitrate_limit_min_kbps=hi->bitrate_min/1000;
+        ai->bitrate_limit_max_kbps=hi->bitrate_max/1000;
+        ai->bitrate_average_kbps=hi->bitrate_av/1000;
+        ai->bitrate_average_damping=hi->bitrate_av_damp;
+        ai->bitrate_limit_reservoir_bits=hi->bitrate_reservoir;
+        ai->bitrate_limit_reservoir_bias=hi->bitrate_reservoir_bias;
+      }
+      return (0);
+    case OV_ECTL_RATEMANAGE2_SET:
+      {
+        struct ovectl_ratemanage2_arg *ai=
+          (struct ovectl_ratemanage2_arg *)arg;
+        if(ai==NULL){
+          hi->managed=0;
+        }else{
+          /* sanity check; only catch invariant violations */
+          if(ai->bitrate_limit_min_kbps>0 &&
+             ai->bitrate_average_kbps>0 &&
+             ai->bitrate_limit_min_kbps>ai->bitrate_average_kbps)
+            return OV_EINVAL;
+
+          if(ai->bitrate_limit_max_kbps>0 &&
+             ai->bitrate_average_kbps>0 &&
+             ai->bitrate_limit_max_kbps<ai->bitrate_average_kbps)
+            return OV_EINVAL;
+
+          if(ai->bitrate_limit_min_kbps>0 &&
+             ai->bitrate_limit_max_kbps>0 &&
+             ai->bitrate_limit_min_kbps>ai->bitrate_limit_max_kbps)
+            return OV_EINVAL;
+
+          if(ai->bitrate_average_damping <= 0.)
+            return OV_EINVAL;
+
+          if(ai->bitrate_limit_reservoir_bits < 0)
+            return OV_EINVAL;
+
+          if(ai->bitrate_limit_reservoir_bias < 0.)
+            return OV_EINVAL;
+
+          if(ai->bitrate_limit_reservoir_bias > 1.)
+            return OV_EINVAL;
+
+          hi->managed=ai->management_active;
+          hi->bitrate_min=ai->bitrate_limit_min_kbps * 1000;
+          hi->bitrate_max=ai->bitrate_limit_max_kbps * 1000;
+          hi->bitrate_av=ai->bitrate_average_kbps * 1000;
+          hi->bitrate_av_damp=ai->bitrate_average_damping;
+          hi->bitrate_reservoir=ai->bitrate_limit_reservoir_bits;
+          hi->bitrate_reservoir_bias=ai->bitrate_limit_reservoir_bias;
+        }
+      }
+      return 0;
+
+    case OV_ECTL_LOWPASS_GET:
+      {
+        double *farg=(double *)arg;
+        *farg=hi->lowpass_kHz;
+      }
+      return(0);
+    case OV_ECTL_LOWPASS_SET:
+      {
+        double *farg=(double *)arg;
+        hi->lowpass_kHz=*farg;
+
+        if(hi->lowpass_kHz<2.)hi->lowpass_kHz=2.;
+        if(hi->lowpass_kHz>99.)hi->lowpass_kHz=99.;
+        hi->lowpass_altered=1;
+      }
+      return(0);
+    case OV_ECTL_IBLOCK_GET:
+      {
+        double *farg=(double *)arg;
+        *farg=hi->impulse_noisetune;
+      }
+      return(0);
+    case OV_ECTL_IBLOCK_SET:
+      {
+        double *farg=(double *)arg;
+        hi->impulse_noisetune=*farg;
+
+        if(hi->impulse_noisetune>0.)hi->impulse_noisetune=0.;
+        if(hi->impulse_noisetune<-15.)hi->impulse_noisetune=-15.;
+      }
+      return(0);
+    case OV_ECTL_COUPLING_GET:
+      {
+        int *iarg=(int *)arg;
+        *iarg=hi->coupling_p;
+      }
+      return(0);
+    case OV_ECTL_COUPLING_SET:
+      {
+        const void *new_template;
+        double new_base=0.;
+        int *iarg=(int *)arg;
+        hi->coupling_p=((*iarg)!=0);
+
+        /* Fetching a new template can alter the base_setting, which
+           many other parameters are based on.  Right now, the only
+           parameter drawn from the base_setting that can be altered
+           by an encctl is the lowpass, so that is explictly flagged
+           to not be overwritten when we fetch a new template and
+           recompute the dependant settings */
+        new_template = get_setup_template(hi->coupling_p?vi->channels:-1,
+                                          vi->rate,
+                                          hi->req,
+                                          hi->managed,
+                                          &new_base);
+        if(!hi->setup)return OV_EIMPL;
+        hi->setup=new_template;
+        hi->base_setting=new_base;
+        vorbis_encode_setup_setting(vi,vi->channels,vi->rate);
+      }
+      return(0);
+    }
+    return(OV_EIMPL);
+  }
+  return(OV_EINVAL);
+}
--- libvorbis-1.3.2.orig/.pc/CVE-2018-5146.patch/lib/codebook.c
+++ libvorbis-1.3.2/.pc/CVE-2018-5146.patch/lib/codebook.c
@@ -0,0 +1,479 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+ *                                                                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+ function: basic codebook pack/unpack/code/decode operations
+ last mod: $Id: codebook.c 17553 2010-10-21 17:54:26Z tterribe $
+
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ogg/ogg.h>
+#include "vorbis/codec.h"
+#include "codebook.h"
+#include "scales.h"
+#include "misc.h"
+#include "os.h"
+
+/* packs the given codebook into the bitstream **************************/
+
+int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){
+  long i,j;
+  int ordered=0;
+
+  /* first the basic parameters */
+  oggpack_write(opb,0x564342,24);
+  oggpack_write(opb,c->dim,16);
+  oggpack_write(opb,c->entries,24);
+
+  /* pack the codewords.  There are two packings; length ordered and
+     length random.  Decide between the two now. */
+
+  for(i=1;i<c->entries;i++)
+    if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break;
+  if(i==c->entries)ordered=1;
+
+  if(ordered){
+    /* length ordered.  We only need to say how many codewords of
+       each length.  The actual codewords are generated
+       deterministically */
+
+    long count=0;
+    oggpack_write(opb,1,1);  /* ordered */
+    oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */
+
+    for(i=1;i<c->entries;i++){
+      long this=c->lengthlist[i];
+      long last=c->lengthlist[i-1];
+      if(this>last){
+        for(j=last;j<this;j++){
+          oggpack_write(opb,i-count,_ilog(c->entries-count));
+          count=i;
+        }
+      }
+    }
+    oggpack_write(opb,i-count,_ilog(c->entries-count));
+
+  }else{
+    /* length random.  Again, we don't code the codeword itself, just
+       the length.  This time, though, we have to encode each length */
+    oggpack_write(opb,0,1);   /* unordered */
+
+    /* algortihmic mapping has use for 'unused entries', which we tag
+       here.  The algorithmic mapping happens as usual, but the unused
+       entry has no codeword. */
+    for(i=0;i<c->entries;i++)
+      if(c->lengthlist[i]==0)break;
+
+    if(i==c->entries){
+      oggpack_write(opb,0,1); /* no unused entries */
+      for(i=0;i<c->entries;i++)
+        oggpack_write(opb,c->lengthlist[i]-1,5);
+    }else{
+      oggpack_write(opb,1,1); /* we have unused entries; thus we tag */
+      for(i=0;i<c->entries;i++){
+        if(c->lengthlist[i]==0){
+          oggpack_write(opb,0,1);
+        }else{
+          oggpack_write(opb,1,1);
+          oggpack_write(opb,c->lengthlist[i]-1,5);
+        }
+      }
+    }
+  }
+
+  /* is the entry number the desired return value, or do we have a
+     mapping? If we have a mapping, what type? */
+  oggpack_write(opb,c->maptype,4);
+  switch(c->maptype){
+  case 0:
+    /* no mapping */
+    break;
+  case 1:case 2:
+    /* implicitly populated value mapping */
+    /* explicitly populated value mapping */
+
+    if(!c->quantlist){
+      /* no quantlist?  error */
+      return(-1);
+    }
+
+    /* values that define the dequantization */
+    oggpack_write(opb,c->q_min,32);
+    oggpack_write(opb,c->q_delta,32);
+    oggpack_write(opb,c->q_quant-1,4);
+    oggpack_write(opb,c->q_sequencep,1);
+
+    {
+      int quantvals;
+      switch(c->maptype){
+      case 1:
+        /* a single column of (c->entries/c->dim) quantized values for
+           building a full value list algorithmically (square lattice) */
+        quantvals=_book_maptype1_quantvals(c);
+        break;
+      case 2:
+        /* every value (c->entries*c->dim total) specified explicitly */
+        quantvals=c->entries*c->dim;
+        break;
+      default: /* NOT_REACHABLE */
+        quantvals=-1;
+      }
+
+      /* quantized values */
+      for(i=0;i<quantvals;i++)
+        oggpack_write(opb,labs(c->quantlist[i]),c->q_quant);
+
+    }
+    break;
+  default:
+    /* error case; we don't have any other map types now */
+    return(-1);
+  }
+
+  return(0);
+}
+
+/* unpacks a codebook from the packet buffer into the codebook struct,
+   readies the codebook auxiliary structures for decode *************/
+static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
+  long i,j;
+  static_codebook *s=_ogg_calloc(1,sizeof(*s));
+  s->allocedp=1;
+
+  /* make sure alignment is correct */
+  if(oggpack_read(opb,24)!=0x564342)goto _eofout;
+
+  /* first the basic parameters */
+  s->dim=oggpack_read(opb,16);
+  s->entries=oggpack_read(opb,24);
+  if(s->entries==-1)goto _eofout;
+
+  if(_ilog(s->dim)+_ilog(s->entries)>24)goto _eofout;
+
+  /* codeword ordering.... length ordered or unordered? */
+  switch((int)oggpack_read(opb,1)){
+  case 0:{
+    long unused;
+    /* allocated but unused entries? */
+    unused=oggpack_read(opb,1);
+    if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb))
+      goto _eofout;
+    /* unordered */
+    s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
+
+    /* allocated but unused entries? */
+    if(unused){
+      /* yes, unused entries */
+
+      for(i=0;i<s->entries;i++){
+        if(oggpack_read(opb,1)){
+          long num=oggpack_read(opb,5);
+          if(num==-1)goto _eofout;
+          s->lengthlist[i]=num+1;
+        }else
+          s->lengthlist[i]=0;
+      }
+    }else{
+      /* all entries used; no tagging */
+      for(i=0;i<s->entries;i++){
+        long num=oggpack_read(opb,5);
+        if(num==-1)goto _eofout;
+        s->lengthlist[i]=num+1;
+      }
+    }
+
+    break;
+  }
+  case 1:
+    /* ordered */
+    {
+      long length=oggpack_read(opb,5)+1;
+      if(length==0)goto _eofout;
+      s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
+
+      for(i=0;i<s->entries;){
+        long num=oggpack_read(opb,_ilog(s->entries-i));
+        if(num==-1)goto _eofout;
+        if(length>32 || num>s->entries-i ||
+           (num>0 && (num-1)>>(length-1)>1)){
+          goto _errout;
+        }
+        if(length>32)goto _errout;
+        for(j=0;j<num;j++,i++)
+          s->lengthlist[i]=length;
+        length++;
+      }
+    }
+    break;
+  default:
+    /* EOF */
+    goto _eofout;
+  }
+
+  /* Do we have a mapping to unpack? */
+  switch((s->maptype=oggpack_read(opb,4))){
+  case 0:
+    /* no mapping */
+    break;
+  case 1: case 2:
+    /* implicitly populated value mapping */
+    /* explicitly populated value mapping */
+
+    s->q_min=oggpack_read(opb,32);
+    s->q_delta=oggpack_read(opb,32);
+    s->q_quant=oggpack_read(opb,4)+1;
+    s->q_sequencep=oggpack_read(opb,1);
+    if(s->q_sequencep==-1)goto _eofout;
+
+    {
+      int quantvals=0;
+      switch(s->maptype){
+      case 1:
+        quantvals=(s->dim==0?0:_book_maptype1_quantvals(s));
+        break;
+      case 2:
+        quantvals=s->entries*s->dim;
+        break;
+      }
+
+      /* quantized values */
+      if((quantvals*s->q_quant+7>>3)>opb->storage-oggpack_bytes(opb))
+        goto _eofout;
+      s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals);
+      for(i=0;i<quantvals;i++)
+        s->quantlist[i]=oggpack_read(opb,s->q_quant);
+
+      if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout;
+    }
+    break;
+  default:
+    goto _errout;
+  }
+
+  /* all set */
+  return(s);
+
+ _errout:
+ _eofout:
+  vorbis_staticbook_destroy(s);
+  return(NULL);
+}
+
+/* returns the number of bits ************************************************/
+int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){
+  if(a<0 || a>=book->c->entries)return(0);
+  oggpack_write(b,book->codelist[a],book->c->lengthlist[a]);
+  return(book->c->lengthlist[a]);
+}
+
+/* the 'eliminate the decode tree' optimization actually requires the
+   codewords to be MSb first, not LSb.  This is an annoying inelegancy
+   (and one of the first places where carefully thought out design
+   turned out to be wrong; Vorbis II and future Ogg codecs should go
+   to an MSb bitpacker), but not actually the huge hit it appears to
+   be.  The first-stage decode table catches most words so that
+   bitreverse is not in the main execution path. */
+
+static ogg_uint32_t bitreverse(ogg_uint32_t x){
+  x=    ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
+  x=    ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
+  x=    ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
+  x=    ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
+  return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
+}
+
+STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
+  int  read=book->dec_maxlength;
+  long lo,hi;
+  long lok = oggpack_look(b,book->dec_firsttablen);
+
+  if (lok >= 0) {
+    long entry = book->dec_firsttable[lok];
+    if(entry&0x80000000UL){
+      lo=(entry>>15)&0x7fff;
+      hi=book->used_entries-(entry&0x7fff);
+    }else{
+      oggpack_adv(b, book->dec_codelengths[entry-1]);
+      return(entry-1);
+    }
+  }else{
+    lo=0;
+    hi=book->used_entries;
+  }
+
+  lok = oggpack_look(b, read);
+
+  while(lok<0 && read>1)
+    lok = oggpack_look(b, --read);
+  if(lok<0)return -1;
+
+  /* bisect search for the codeword in the ordered list */
+  {
+    ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
+
+    while(hi-lo>1){
+      long p=(hi-lo)>>1;
+      long test=book->codelist[lo+p]>testword;
+      lo+=p&(test-1);
+      hi-=p&(-test);
+      }
+
+    if(book->dec_codelengths[lo]<=read){
+      oggpack_adv(b, book->dec_codelengths[lo]);
+      return(lo);
+    }
+  }
+
+  oggpack_adv(b, read);
+
+  return(-1);
+}
+
+/* Decode side is specced and easier, because we don't need to find
+   matches using different criteria; we simply read and map.  There are
+   two things we need to do 'depending':
+
+   We may need to support interleave.  We don't really, but it's
+   convenient to do it here rather than rebuild the vector later.
+
+   Cascades may be additive or multiplicitive; this is not inherent in
+   the codebook, but set in the code using the codebook.  Like
+   interleaving, it's easiest to do it here.
+   addmul==0 -> declarative (set the value)
+   addmul==1 -> additive
+   addmul==2 -> multiplicitive */
+
+/* returns the [original, not compacted] entry number or -1 on eof *********/
+long vorbis_book_decode(codebook *book, oggpack_buffer *b){
+  if(book->used_entries>0){
+    long packed_entry=decode_packed_entry_number(book,b);
+    if(packed_entry>=0)
+      return(book->dec_index[packed_entry]);
+  }
+
+  /* if there's no dec_index, the codebook unpacking isn't collapsed */
+  return(-1);
+}
+
+/* returns 0 on OK or -1 on eof *************************************/
+long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
+  if(book->used_entries>0){
+    int step=n/book->dim;
+    long *entry = alloca(sizeof(*entry)*step);
+    float **t = alloca(sizeof(*t)*step);
+    int i,j,o;
+
+    for (i = 0; i < step; i++) {
+      entry[i]=decode_packed_entry_number(book,b);
+      if(entry[i]==-1)return(-1);
+      t[i] = book->valuelist+entry[i]*book->dim;
+    }
+    for(i=0,o=0;i<book->dim;i++,o+=step)
+      for (j=0;j<step;j++)
+        a[o+j]+=t[j][i];
+  }
+  return(0);
+}
+
+long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
+  if(book->used_entries>0){
+    int i,j,entry;
+    float *t;
+
+    if(book->dim>8){
+      for(i=0;i<n;){
+        entry = decode_packed_entry_number(book,b);
+        if(entry==-1)return(-1);
+        t     = book->valuelist+entry*book->dim;
+        for (j=0;j<book->dim;)
+          a[i++]+=t[j++];
+      }
+    }else{
+      for(i=0;i<n;){
+        entry = decode_packed_entry_number(book,b);
+        if(entry==-1)return(-1);
+        t     = book->valuelist+entry*book->dim;
+        j=0;
+        switch((int)book->dim){
+        case 8:
+          a[i++]+=t[j++];
+        case 7:
+          a[i++]+=t[j++];
+        case 6:
+          a[i++]+=t[j++];
+        case 5:
+          a[i++]+=t[j++];
+        case 4:
+          a[i++]+=t[j++];
+        case 3:
+          a[i++]+=t[j++];
+        case 2:
+          a[i++]+=t[j++];
+        case 1:
+          a[i++]+=t[j++];
+        case 0:
+          break;
+        }
+      }
+    }
+  }
+  return(0);
+}
+
+long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
+  if(book->used_entries>0){
+    int i,j,entry;
+    float *t;
+
+    for(i=0;i<n;){
+      entry = decode_packed_entry_number(book,b);
+      if(entry==-1)return(-1);
+      t     = book->valuelist+entry*book->dim;
+      for (j=0;j<book->dim;)
+        a[i++]=t[j++];
+    }
+  }else{
+    int i,j;
+
+    for(i=0;i<n;){
+      for (j=0;j<book->dim;)
+        a[i++]=0.f;
+    }
+  }
+  return(0);
+}
+
+long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
+                              oggpack_buffer *b,int n){
+
+  long i,j,entry;
+  int chptr=0;
+  if(book->used_entries>0){
+    for(i=offset/ch;i<(offset+n)/ch;){
+      entry = decode_packed_entry_number(book,b);
+      if(entry==-1)return(-1);
+      {
+        const float *t = book->valuelist+entry*book->dim;
+        for (j=0;j<book->dim;j++){
+          a[chptr++][i]+=t[j];
+          if(chptr==ch){
+            chptr=0;
+            i++;
+          }
+        }
+      }
+    }
+  }
+  return(0);
+}
